@office-open/docx 0.10.15 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"parse-CgAxzk5K.mjs","names":[],"sources":["../src/parts/table-of-contents/toc-parse.ts","../src/parts/alt-chunk/alt-chunk-parse.ts","../src/parts/custom-xml/custom-xml-parse.ts","../src/parts/sub-doc/sub-doc-parse.ts","../src/parts/textbox/textbox-parse.ts","../src/parse/body.ts","../src/parse.ts"],"sourcesContent":["/**\n * Table of Contents parser for DOCX documents.\n *\n * Parses TOC-type SDT elements into TOC options.\n *\n * @module\n */\nimport { attr, children, findChild, findFirst, textOf } from \"@office-open/xml\";\nimport type { Element } from \"@office-open/xml\";\nimport type {\n StyleLevel,\n TableOfContentsOptions,\n} from \"@parts/table-of-contents/table-of-contents-properties\";\nimport type { SectionChild } from \"@shared/section\";\n\nimport type { DocxReadContext } from \"../../context\";\n\n/**\n * Try to parse a w:sdt element as a TOC.\n * Returns { alias, ...tocOptions } if it's a TOC, or undefined otherwise.\n *\n * Detects TOC in two ways:\n * 1. SDT with w:docPartObj > w:docPartGallery = \"Table of Contents\" (Word-generated)\n * 2. SDT whose content contains a TOC field instruction (library-generated)\n */\nexport function parseToc(\n el: Element,\n ctx: DocxReadContext,\n parseChildren?: (elements: Element[], ctx: DocxReadContext) => SectionChild[],\n):\n | ({\n alias?: string;\n } & TableOfContentsOptions)\n | undefined {\n const sdtPr = findChild(el, \"w:sdtPr\");\n if (!sdtPr) return undefined;\n\n // Detection method 1: docPartObj with gallery \"Table of Contents\"\n const docPartObj = findChild(sdtPr, \"w:docPartObj\");\n let isToc = false;\n\n if (docPartObj) {\n const gallery = findChild(docPartObj, \"w:docPartGallery\");\n if (gallery && textOf(gallery) === \"Table of Contents\") {\n isToc = true;\n }\n }\n\n // Detection method 2: scan content for TOC field instruction\n if (!isToc) {\n const sdtContent = findChild(el, \"w:sdtContent\");\n if (sdtContent) {\n isToc = hasTocFieldInstruction(sdtContent);\n }\n }\n\n if (!isToc) return undefined;\n\n // It's a TOC SDT\n const alias = (() => {\n const aliasEl = findChild(sdtPr, \"w:alias\");\n return aliasEl ? attr(aliasEl, \"w:val\") : undefined;\n })();\n\n // Parse field instruction from content to extract TOC options\n const tocOpts: Record<string, unknown> = {};\n const sdtContent = findChild(el, \"w:sdtContent\");\n\n if (sdtContent) {\n // Look for field instructions\n for (const p of children(sdtContent, \"w:p\")) {\n for (const r of children(p, \"w:r\")) {\n for (const instrText of children(r, \"w:instrText\")) {\n const instruction = textOf(instrText).trim();\n parseTocFieldInstruction(instruction, tocOpts);\n }\n }\n }\n // Rendered entries — the paragraphs between the field's separate and end\n // markers. Captured structurally so MS Office and WPS both display the\n // existing TOC instead of regenerating it from headings.\n if (parseChildren) {\n const entryEls = selectTocEntryElements(sdtContent.elements ?? []);\n if (entryEls.length > 0) {\n tocOpts.entries = parseChildren(entryEls, ctx);\n }\n }\n }\n\n return { alias, ...tocOpts } as { alias?: string } & TableOfContentsOptions;\n}\n\n/**\n * Check whether an element tree contains a TOC field instruction\n * (w:instrText with text starting with \"TOC\").\n */\nfunction hasTocFieldInstruction(el: Element): boolean {\n for (const p of children(el, \"w:p\")) {\n for (const r of children(p, \"w:r\")) {\n for (const instrText of children(r, \"w:instrText\")) {\n const instruction = textOf(instrText)?.trim();\n if (instruction?.startsWith(\"TOC\")) return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Parse a TOC field instruction string (e.g., ' TOC \\o \"1-3\" \\h \\z ')\n * into TableOfContentsOptions properties.\n */\nexport function parseTocFieldInstruction(instruction: string, opts: Record<string, unknown>): void {\n if (!instruction.startsWith(\"TOC\")) return;\n\n const rest = instruction.slice(3).trim();\n const switches = parseFieldSwitches(rest);\n\n if (switches[\"a\"]) opts.captionLabel = switches[\"a\"];\n if (switches[\"b\"]) opts.entriesFromBookmark = switches[\"b\"];\n if (switches[\"c\"]) opts.captionLabelIncludingNumbers = switches[\"c\"];\n if (switches[\"d\"]) opts.sequenceAndPageNumbersSeparator = switches[\"d\"];\n if (switches[\"f\"]) opts.tcFieldIdentifier = switches[\"f\"];\n if (\"h\" in switches) opts.hyperlink = true;\n if (switches[\"l\"]) opts.tcFieldLevelRange = switches[\"l\"];\n if (switches[\"n\"]) opts.pageNumbersEntryLevelsRange = switches[\"n\"];\n if (switches[\"o\"]) opts.headingStyleRange = switches[\"o\"];\n if (switches[\"p\"]) opts.entryAndPageNumberSeparator = switches[\"p\"];\n if (switches[\"s\"]) opts.seqFieldIdentifierForPrefix = switches[\"s\"];\n if (switches[\"t\"]) {\n // \\t \"Style1,1,Style2,2\" -> stylesWithLevels pairs\n const parts = switches[\"t\"]!.split(\",\");\n const stylesWithLevels: StyleLevel[] = [];\n for (let i = 0; i + 1 < parts.length; i += 2) {\n const styleName = parts[i];\n const level = parseInt(parts[i + 1] ?? \"\", 10);\n if (styleName && !Number.isNaN(level)) stylesWithLevels.push({ styleName, level });\n }\n if (stylesWithLevels.length > 0) opts.stylesWithLevels = stylesWithLevels;\n }\n if (\"u\" in switches) opts.useAppliedParagraphOutlineLevel = true;\n if (\"w\" in switches) opts.preserveTabInEntries = true;\n if (\"x\" in switches) opts.preserveNewLineInEntries = true;\n if (\"z\" in switches) opts.hideTabAndPageNumbersInWebView = true;\n}\n\n/**\n * Extract TOC options from the elements of a captured TOC field (SDT content or\n * a bare cross-paragraph field). Feeds every w:instrText to the instruction\n * parser; non-TOC fields (HYPERLINK/PAGEREF inside the rendered entries) are\n * ignored — parseTocFieldInstruction only acts on instructions starting \"TOC\".\n */\nexport function parseTocFieldFromElements(els: Element[]): TableOfContentsOptions {\n const opts: Record<string, unknown> = {};\n for (const el of els) collectTocInstructions(el, opts);\n return opts as TableOfContentsOptions;\n}\n\n/**\n * Select the rendered-entry paragraphs of a captured TOC field. Tracks field\n * depth so a nested HYPERLINK/PAGEREF field inside an entry doesn't fool the\n * boundary detection.\n *\n * A paragraph is an entry when, after walking it, the field is past `separate`\n * and not past `end` (depth ≥ 1) and the paragraph carries rendered text (`w:t`).\n * This captures an entry whose paragraph also opens the field (`begin`) or holds\n * the `separate` marker — common when Word emits begin + separate + first entry\n * in one paragraph — while the `w:t` requirement excludes a pure control\n * paragraph (field head / separate-only / end).\n */\nexport function selectTocEntryElements(els: Element[]): Element[] {\n const entries: Element[] = [];\n let depth = 0;\n let afterSeparate = false;\n for (const el of els) {\n const walk = (node: Element): void => {\n if (node.name === \"w:fldChar\") {\n const type = attr(node, \"w:fldCharType\");\n if (type === \"begin\") depth++;\n else if (type === \"separate\" && depth === 1) afterSeparate = true;\n else if (type === \"end\") depth--;\n }\n for (const c of node.elements ?? []) {\n if (c.type === \"element\") walk(c);\n }\n };\n walk(el);\n if (afterSeparate && depth >= 1 && findFirst(el, \"w:t\") !== undefined) {\n entries.push(el);\n }\n }\n return entries;\n}\n\n/** Recursively feed every w:instrText to the TOC instruction parser. */\nfunction collectTocInstructions(el: Element, opts: Record<string, unknown>): void {\n if (el.name === \"w:instrText\") {\n const instruction = textOf(el)?.trim();\n if (instruction) parseTocFieldInstruction(instruction, opts);\n }\n for (const c of el.elements ?? []) {\n if (c.type === \"element\") collectTocInstructions(c, opts);\n }\n}\n\n/**\n * Parse field switches like \\o \"1-3\" \\h \\z into a map.\n */\nfunction parseFieldSwitches(text: string): Record<string, string | undefined> {\n const result: Record<string, string | undefined> = {};\n let i = 0;\n\n while (i < text.length) {\n // Skip whitespace\n while (i < text.length && text[i] === \" \") i++;\n if (i >= text.length) break;\n\n // Expect backslash\n if (text[i] !== \"\\\\\") {\n i++;\n continue;\n }\n i++;\n\n // Read switch name\n const nameStart = i;\n while (i < text.length && /[a-zA-Z]/.test(text[i] ?? \"\")) i++;\n const name = text.slice(nameStart, i);\n if (!name) continue;\n\n // Skip whitespace\n while (i < text.length && text[i] === \" \") i++;\n\n // Read argument (quoted or unquoted)\n if (i < text.length && text[i] === '\"') {\n i++;\n const argStart = i;\n while (i < text.length && text[i] !== '\"') i++;\n result[name] = text.slice(argStart, i);\n if (i < text.length) i++; // skip closing quote\n } else if (i < text.length && text[i] !== \"\\\\\") {\n const argStart = i;\n while (i < text.length && text[i] !== \" \" && text[i] !== \"\\\\\") i++;\n const arg = text.slice(argStart, i).trim();\n if (arg) result[name] = arg;\n else result[name] = undefined;\n } else {\n result[name] = undefined;\n }\n }\n\n return result;\n}\n","/**\n * AltChunk parser for DOCX documents.\n *\n * Parses w:altChunk elements and extracts embedded content from the ZIP.\n *\n * @module\n */\nimport { attr } from \"@office-open/xml\";\nimport type { Element } from \"@office-open/xml\";\nimport type { AltChunkOptions } from \"@parts/alt-chunk/alt-chunk\";\n\nimport type { DocxReadContext } from \"../../context\";\n\n/**\n * Parse a w:altChunk element into AltChunkOptions.\n * Reads the referenced data from the ZIP package.\n */\nexport function parseAltChunk(el: Element, ctx: DocxReadContext): AltChunkOptions {\n const rId = attr(el, \"r:id\");\n if (!rId) {\n throw new Error(\"w:altChunk missing r:id attribute\");\n }\n\n // Look up the path from relationships\n const path = ctx.docx.partRefs.afChunks.get(rId);\n if (!path) {\n throw new Error(`AltChunk relationship ${rId} not found`);\n }\n\n // Read raw data from ZIP\n const data = ctx.docx.doc.getRaw(path);\n if (!data) {\n throw new Error(`AltChunk data not found at ${path}`);\n }\n\n // Determine content type from extension\n const ext = path.split(\".\").pop() ?? \"txt\";\n let contentType: \"text/html\" | \"application/rtf\" | \"text/plain\";\n let extension: \"html\" | \"rtf\" | \"txt\";\n\n switch (ext) {\n case \"html\":\n contentType = \"text/html\";\n extension = \"html\";\n break;\n case \"rtf\":\n contentType = \"application/rtf\";\n extension = \"rtf\";\n break;\n default:\n contentType = \"text/plain\";\n extension = \"txt\";\n break;\n }\n\n return {\n data,\n contentType,\n extension,\n };\n}\n","/**\n * Parser for custom XML block elements (w:customXml).\n *\n * @module\n */\nimport { attr, findChild } from \"@office-open/xml\";\nimport type { Element } from \"@office-open/xml\";\nimport type { SectionChild } from \"@shared/section\";\n\nimport type { DocxReadContext } from \"../../context\";\nimport { parseCustomXmlProperties } from \"../bodychildren\";\nimport type { CustomXmlBlockOptions } from \"./custom-xml\";\n\n/**\n * Parse w:customXml element into CustomXmlBlockOptions.\n *\n * Uses a callback for child parsing to avoid circular dependencies\n * (same pattern as parseTable).\n */\nexport function parseCustomXmlBlock(\n el: Element,\n ctx: DocxReadContext,\n parseChild: (el: Element, ctx: DocxReadContext) => SectionChild,\n): CustomXmlBlockOptions {\n const opts: Partial<CustomXmlBlockOptions> = {};\n\n // Required attribute\n const element = attr(el, \"w:element\");\n if (element) opts.element = element;\n\n // Optional URI\n const uri = attr(el, \"w:uri\");\n if (uri) opts.uri = uri;\n\n // Parse w:customXmlPr\n const xmlPr = findChild(el, \"w:customXmlPr\");\n if (xmlPr) {\n opts.customXmlPr = parseCustomXmlProperties(xmlPr);\n }\n\n // Parse block-level children\n const children: SectionChild[] = [];\n for (const child of el.elements ?? []) {\n if (child.name === \"w:customXmlPr\") continue;\n const parsed = parseChild(child, ctx);\n children.push(parsed);\n }\n if (children.length > 0) opts.children = children;\n\n return opts as CustomXmlBlockOptions;\n}\n","/**\n * SubDoc parser for DOCX documents.\n *\n * Parses w:subDoc elements and extracts embedded document data.\n *\n * @module\n */\nimport { attr } from \"@office-open/xml\";\nimport type { Element } from \"@office-open/xml\";\nimport type { SubDocOptions } from \"@parts/sub-doc/sub-doc\";\n\nimport type { DocxReadContext } from \"../../context\";\n\n/**\n * Parse a w:subDoc element into SubDocOptions.\n * Reads the referenced document data from the ZIP package.\n */\nexport function parseSubDoc(el: Element, ctx: DocxReadContext): SubDocOptions {\n const rId = attr(el, \"r:id\");\n if (!rId) {\n throw new Error(\"w:subDoc missing r:id attribute\");\n }\n\n const path = ctx.docx.partRefs.subDocs.get(rId);\n if (!path) {\n throw new Error(`SubDoc relationship ${rId} not found`);\n }\n\n const data = ctx.docx.doc.getRaw(path);\n if (!data) {\n throw new Error(`SubDoc data not found at ${path}`);\n }\n\n return { data };\n}\n","/**\n * Textbox parser for DOCX documents.\n *\n * Parses w:pict → v:shape → v:textbox → w:txbxContent elements.\n *\n * @module\n */\nimport { attr, findChild, findFirst } from \"@office-open/xml\";\nimport type { Element } from \"@office-open/xml\";\n\nimport type { DocxReadContext } from \"../../context\";\n\n/**\n * Parse VML shape style string into VmlShapeStyle-like object.\n */\nfunction parseVmlStyle(styleStr: string): Record<string, string> {\n const style: Record<string, string> = {};\n for (const part of styleStr.split(\";\")) {\n const [key, val] = part.split(\":\").map((s) => s.trim());\n if (key && val) style[key] = val;\n }\n return style;\n}\n\n/**\n * Parse a w:pict element that contains a textbox.\n * Returns an object suitable for the { textbox: ... } SectionChild variant.\n */\nexport function parseTextbox(\n el: Element,\n ctx: DocxReadContext,\n parseChildren: (elements: Element[], ctx: DocxReadContext) => unknown[],\n): {\n style?: Record<string, string>;\n children?: unknown[];\n} {\n const shape = findFirst(el, \"v:shape\");\n if (!shape) return {};\n\n const opts: Record<string, unknown> = {};\n\n // Parse VML style\n const styleAttr = attr(shape, \"style\");\n if (styleAttr) {\n opts.style = parseVmlStyle(styleAttr);\n }\n\n // Parse textbox content\n const textbox = findFirst(shape, \"v:textbox\");\n if (textbox) {\n const txbxContent = findChild(textbox, \"w:txbxContent\");\n if (txbxContent) {\n const childList = parseChildren(txbxContent.elements ?? [], ctx);\n if (childList.length > 0) opts.children = childList;\n }\n }\n\n return opts as { style?: Record<string, string>; children?: unknown[] };\n}\n","/**\n * Body parser for DOCX documents.\n *\n * Parses w:body → SectionOptions[] by splitting at w:sectPr boundaries.\n *\n * @module\n */\nimport { attr, findChild, findDeep, findFirst, textOf } from \"@office-open/xml\";\nimport type { Element } from \"@office-open/xml\";\nimport { parseAltChunk } from \"@parts/alt-chunk/alt-chunk-parse\";\nimport { parseCustomXmlBlock } from \"@parts/custom-xml/custom-xml-parse\";\nimport { parseSectionPropertiesEl } from \"@parts/document/body/section-properties/descriptor\";\nimport type { SectionPropertiesOptions } from \"@parts/document/body/section-properties/section-properties\";\nimport type { MarkupRangeOptions, BookmarkStartOptions } from \"@parts/paragraph/links/bookmark\";\nimport { parseSdtBlock } from \"@parts/sdt/sdt-parse\";\nimport { parseSubDoc } from \"@parts/sub-doc/sub-doc-parse\";\nimport {\n parseToc,\n parseTocFieldFromElements,\n selectTocEntryElements,\n} from \"@parts/table-of-contents/toc-parse\";\nimport { tableDesc } from \"@parts/table/descriptor\";\nimport type { TableOptions } from \"@parts/table/table\";\nimport { parseTextbox } from \"@parts/textbox/textbox-parse\";\nimport type { SectionOptions } from \"@shared/section\";\nimport type { SectionChild } from \"@shared/section\";\n\nimport { parseParagraph } from \"../body\";\nimport { DocxReadContext } from \"../context\";\nimport { setBodyParseChild } from \"../parts\";\nimport { stringifyElement } from \"../util/stringify-element\";\n\n// ── Section properties parser ────────────────────────────────────────────────\n\n/** Internal parse result: section properties with extracted header/footer refs. */\ntype ParsedSectionProperties = SectionPropertiesOptions & {\n parsedHeaders?: Record<string, SectionChild[]>;\n parsedFooters?: Record<string, SectionChild[]>;\n};\n\n/**\n * Parse w:sectPr element into SectionPropertiesOptions.\n * Delegates to the section properties descriptor's parse method.\n */\nfunction parseSectionProperties(el: Element, ctx: DocxReadContext): ParsedSectionProperties {\n const opts: ParsedSectionProperties = parseSectionPropertiesEl(el);\n\n // Headers/footers - parse from references and store in a separate field\n const headerRefs: Record<string, SectionChild[]> = {};\n const footerRefs: Record<string, SectionChild[]> = {};\n\n for (const child of el.elements ?? []) {\n if (child.name === \"w:headerReference\") {\n const rId = attr(child, \"r:id\");\n const type = attr(child, \"w:type\");\n if (rId && type) {\n const headerChildren = parseHeaderFooterRef(rId, ctx);\n if (headerChildren) headerRefs[type] = headerChildren;\n }\n }\n if (child.name === \"w:footerReference\") {\n const rId = attr(child, \"r:id\");\n const type = attr(child, \"w:type\");\n if (rId && type) {\n const footerChildren = parseHeaderFooterRef(rId, ctx);\n if (footerChildren) footerRefs[type] = footerChildren;\n }\n }\n }\n\n if (Object.keys(headerRefs).length > 0) {\n opts.parsedHeaders = headerRefs;\n }\n if (Object.keys(footerRefs).length > 0) {\n opts.parsedFooters = footerRefs;\n }\n\n return opts;\n}\n\n/**\n * Parse a header/footer reference by following the relationship to its XML part.\n */\nfunction parseHeaderFooterRef(rId: string, ctx: DocxReadContext): SectionChild[] | undefined {\n const path = ctx.docx.partRefs.headers.get(rId) ?? ctx.docx.partRefs.footers.get(rId);\n if (!path) return undefined;\n\n const partEl = ctx.docx.doc.get(path);\n if (!partEl) return undefined;\n\n // The header/footer XML root element contains w:p, w:tbl, etc. Parse under\n // the part's own relationship scope so its drawings resolve images correctly.\n const children: SectionChild[] = [];\n ctx.withPart(path, () => {\n for (const child of partEl.elements ?? []) {\n const sectionChild = parseSectionChild(child, ctx);\n if (sectionChild !== undefined) {\n children.push(sectionChild);\n }\n }\n });\n\n return children.length > 0 ? children : undefined;\n}\n\n// ── Section child dispatch ───────────────────────────────────────────────────\n\n/**\n * Parse a single body child element into a SectionChild.\n */\nexport function parseSectionChild(el: Element, ctx: DocxReadContext): SectionChild {\n switch (el.name) {\n case \"w:p\": {\n // Check for textbox (w:pict containing v:textbox)\n const pict = findChild(el, \"w:pict\");\n if (pict) {\n const textbox = findFirst(pict, \"v:textbox\");\n if (textbox) {\n const textboxOpts = parseTextbox(pict, ctx, parseSectionChildrenElements);\n return { textbox: textboxOpts as SectionChild extends { textbox: infer T } ? T : never };\n }\n }\n\n return { paragraph: parseParagraph(el, ctx) };\n }\n case \"w:tbl\":\n return { table: tableDesc.parse(el, ctx) as TableOptions };\n case \"w:sdt\": {\n // Try TOC first\n const tocResult = parseToc(el, ctx, parseSectionChildrenElements);\n if (tocResult) {\n return { toc: tocResult };\n }\n // Otherwise parse as generic SDT block\n const sdtResult = parseSdtBlock(el, ctx, parseSectionChildrenElements);\n return {\n sdt: {\n properties: sdtResult.properties,\n children: sdtResult.children as SectionChild[] | undefined,\n },\n };\n }\n case \"w:altChunk\":\n return { altChunk: parseAltChunk(el, ctx) };\n case \"w:subDoc\":\n return { subDoc: parseSubDoc(el, ctx) };\n case \"w:customXml\":\n return { customXml: parseCustomXmlBlock(el, ctx, parseSectionChild) };\n case \"w:bookmarkStart\": {\n // Body-level range markers sitting between paragraphs (e.g. _Toc bookmark\n // ends grouped after a heading). Carry them as first-class children so\n // they round-trip even though they are not wrapped in a paragraph.\n const idRaw = attr(el, \"w:id\");\n const name = attr(el, \"w:name\");\n if (idRaw !== undefined && name) {\n const bookmarkStart: Partial<BookmarkStartOptions> = { id: Number(idRaw), name };\n const disp = attr(el, \"w:displacedByCustomXml\");\n if (disp === \"before\" || disp === \"after\") bookmarkStart.displacedByCustomXml = disp;\n const colFirstRaw = attr(el, \"w:colFirst\");\n if (colFirstRaw !== undefined) bookmarkStart.colFirst = Number(colFirstRaw);\n const colLastRaw = attr(el, \"w:colLast\");\n if (colLastRaw !== undefined) bookmarkStart.colLast = Number(colLastRaw);\n return { bookmarkStart: bookmarkStart as BookmarkStartOptions };\n }\n return { rawXml: stringifyElement(el) };\n }\n case \"w:bookmarkEnd\": {\n const idRaw = attr(el, \"w:id\");\n if (idRaw !== undefined) {\n const bookmarkEnd: Partial<MarkupRangeOptions> = { id: Number(idRaw) };\n const disp = attr(el, \"w:displacedByCustomXml\");\n if (disp === \"before\" || disp === \"after\") bookmarkEnd.displacedByCustomXml = disp;\n return { bookmarkEnd: bookmarkEnd as MarkupRangeOptions };\n }\n return { rawXml: stringifyElement(el) };\n }\n default:\n return { rawXml: stringifyElement(el) };\n }\n}\n\n// ── Body parsing with section splitting ───────────────────────────────────────\n\n/**\n * Parse w:body element into SectionOptions[].\n *\n * Splits body content at w:sectPr boundaries to create sections.\n * The last w:sectPr (child of w:body directly) defines the last section.\n * Previous w:sectPr elements appear inside w:pPr elements.\n */\nexport function parseBody(body: Element, ctx: DocxReadContext): SectionOptions[] {\n // Register the body child parser for descriptor parse callbacks\n setBodyParseChild(parseSectionChild);\n\n // Collect body children and detect section breaks\n interface SectionBoundary {\n index: number;\n sectPr: Element;\n }\n\n const bodyChildren: Element[] = [];\n const boundaries: SectionBoundary[] = [];\n\n for (const child of body.elements ?? []) {\n if (child.name === \"w:sectPr\") {\n // Final section properties (last section)\n boundaries.push({ index: bodyChildren.length, sectPr: child });\n } else {\n bodyChildren.push(child);\n\n // Check for inline sectPr in paragraph properties\n if (child.name === \"w:p\") {\n const pPr = findChild(child, \"w:pPr\");\n if (pPr) {\n const sectPr = findChild(pPr, \"w:sectPr\");\n if (sectPr) {\n boundaries.push({ index: bodyChildren.length, sectPr });\n }\n }\n }\n }\n }\n\n // If no boundaries, the whole body is one section\n if (boundaries.length === 0) {\n return [\n {\n children: parseBodyChildren(bodyChildren, ctx),\n },\n ];\n }\n\n // Split into sections\n const sections: SectionOptions[] = [];\n let start = 0;\n\n for (const boundary of boundaries) {\n // A sectPr inside a paragraph's pPr marks that paragraph as the final\n // content paragraph of its section. Its runs/drawings ARE section content\n // (e.g. an inline image), so include it in the slice — the paragraph parser\n // ignores pPr/w:sectPr, and stringify re-injects the sectPr into this same\n // paragraph's pPr. The last boundary is a body-level sectPr (never in a\n // paragraph), so boundary.index already points past every real child.\n const endIdx = boundary.index;\n const sectionElements = bodyChildren.slice(start, endIdx);\n const parsedProps = parseSectionProperties(boundary.sectPr, ctx);\n\n // Extract headers/footers that were stored as parsedHeaders/parsedFooters\n const { parsedHeaders, parsedFooters } = parsedProps;\n\n // Build clean properties without internal fields\n const cleanProps = { ...parsedProps };\n delete cleanProps.parsedHeaders;\n delete cleanProps.parsedFooters;\n\n const section = {\n children: parseBodyChildren(sectionElements, ctx),\n properties: cleanProps,\n ...(parsedHeaders ? { headers: parsedHeaders } : {}),\n ...(parsedFooters ? { footers: parsedFooters } : {}),\n } as SectionOptions;\n\n sections.push(section);\n start = boundary.index;\n }\n\n // If there are elements after the last boundary, they form the last section\n // with the body-level w:sectPr (already captured)\n // Actually the body-level sectPr IS the last boundary\n\n return sections;\n}\n\n// ── Cross-paragraph TOC field aggregation ───────────────────────────────────\n\n/**\n * Net field-nesting change across all descendant fldChar markers\n * (begin: +1, end: -1). Balances cross-paragraph field boundaries without a\n * stack — the running depth hits 0 exactly when the outermost field closes.\n */\nfunction countFieldDelta(el: Element): number {\n let delta = 0;\n const walk = (node: Element): void => {\n if (node.name === \"w:fldChar\") {\n const type = attr(node, \"w:fldCharType\");\n if (type === \"begin\") delta += 1;\n else if (type === \"end\") delta -= 1;\n }\n for (const c of node.elements ?? []) {\n if (c.type === \"element\") walk(c);\n }\n };\n walk(el);\n return delta;\n}\n\n/**\n * True when a w:p opens a bare TOC complex field: it carries a fldChar begin\n * whose instrText starts with \"TOC\". Such fields span multiple paragraphs and\n * defeat the per-paragraph field accumulator, so they are aggregated as rawXml.\n */\nfunction isTocFieldBegin(el: Element): boolean {\n if (el.name !== \"w:p\") return false;\n let hasBegin = false;\n let instr = \"\";\n const walk = (node: Element): void => {\n if (node.name === \"w:fldChar\" && attr(node, \"w:fldCharType\") === \"begin\") hasBegin = true;\n if (node.name === \"w:instrText\") instr += textOf(node);\n for (const c of node.elements ?? []) {\n if (c.type === \"element\") walk(c);\n }\n };\n walk(el);\n return hasBegin && instr.trim().toUpperCase().startsWith(\"TOC\");\n}\n\n/**\n * Parse a run of body-level elements into SectionChild[], aggregating any\n * cross-paragraph TOC complex field into a single rawXml child so its nested\n * HYPERLINK/PAGEREF fields and bookmark markers round-trip intact.\n */\nfunction parseBodyChildren(elements: Element[], ctx: DocxReadContext): SectionChild[] {\n const children: SectionChild[] = [];\n let tocBuffer: Element[] | null = null;\n let tocDepth = 0;\n\n const flushToc = (): void => {\n if (!tocBuffer) return;\n children.push(buildTocChild(tocBuffer, ctx));\n // buildTocChild preserves the rendered entries (paragraphs between the\n // separate and end markers) but not the end-closing paragraph, which often\n // carries a trailing page break (the section break before the first\n // heading). Rescue that page break as a standalone child to avoid silently\n // dropping it on round-trip.\n const lastEl = tocBuffer[tocBuffer.length - 1];\n let pageBreakCount = 0;\n for (const br of findDeep(lastEl, \"w:br\")) {\n if (attr(br, \"w:type\") === \"page\") pageBreakCount++;\n }\n for (let i = 0; i < pageBreakCount; i++) {\n children.push({ paragraph: { children: [{ pageBreak: true }] } });\n }\n tocBuffer = null;\n tocDepth = 0;\n };\n\n for (const el of elements) {\n if (tocBuffer !== null) {\n tocBuffer.push(el);\n tocDepth += countFieldDelta(el);\n if (tocDepth <= 0) flushToc();\n continue;\n }\n if (isTocFieldBegin(el)) {\n tocBuffer = [el];\n tocDepth = countFieldDelta(el);\n if (tocDepth <= 0) flushToc();\n continue;\n }\n children.push(parseSectionChild(el, ctx));\n }\n\n // Unclosed TOC field at end of content — flush what we have (best effort).\n flushToc();\n\n return children;\n}\n\n/**\n * Build a structured TOC SectionChild from a captured bare TOC field. Extracts\n * the field instruction (switches → TableOfContentsOptions) and preserves the\n * rendered entries (separate→end paragraphs) structurally so MS Office and WPS\n * both display the existing TOC. The field is emitted clean (no dirty flag).\n */\nfunction buildTocChild(els: Element[], ctx: DocxReadContext): SectionChild {\n const tocOpts = parseTocFieldFromElements(els);\n const entryEls = selectTocEntryElements(els);\n if (entryEls.length > 0) {\n tocOpts.entries = entryEls.map((el) => parseSectionChild(el, ctx));\n }\n return { toc: tocOpts };\n}\n\n/**\n * Parse a list of elements into SectionChild[].\n * Used by SDT and textbox parsers for their content.\n */\nfunction parseSectionChildrenElements(elements: Element[], ctx: DocxReadContext): SectionChild[] {\n return parseBodyChildren(elements, ctx);\n}\n","import type { ParsedArchive } from \"@office-open/core\";\nimport { parseArchive } from \"@office-open/core\";\nimport type { DataType } from \"@office-open/core\";\nimport { toUint8Array } from \"@office-open/core\";\nimport { attr } from \"@office-open/xml\";\nimport type { Element } from \"@office-open/xml\";\nimport { appPropertiesDesc } from \"@parts/app-properties\";\nimport { bibliographyDesc } from \"@parts/bibliography\";\nimport { setBodyParseChild } from \"@parts/bodychildren\";\nimport { commentsDesc } from \"@parts/comments\";\nimport { contentTypesDesc } from \"@parts/contenttypes\";\nimport { corePropertiesDesc } from \"@parts/core-properties\";\nimport type { DocumentOptions } from \"@parts/core-properties\";\nimport { customPropertiesDesc } from \"@parts/custom-properties\";\nimport { endnotesDesc } from \"@parts/endnotes/descriptor\";\nimport { fontTableDesc } from \"@parts/fonts/descriptor\";\nimport type { EmbeddedFontOptionsWithKey } from \"@parts/fonts/font-wrapper\";\nimport { footnotesDesc } from \"@parts/footnotes/descriptor\";\nimport { glossaryDesc } from \"@parts/glossary-document\";\nimport { parseNumberingDefinitions } from \"@parts/numbering/numbering\";\nimport { settingsDesc } from \"@parts/settings/descriptor\";\nimport { buildStyleCache, buildNumberingCache, parseStyleDefinitions } from \"@parts/styles/styles\";\nimport { setTableParseChild } from \"@parts/table/descriptor\";\nimport { webSettingsDesc } from \"@parts/web-settings\";\n\nimport { parseParagraphProperties } from \"./body\";\nimport { DocxReadContext } from \"./context\";\nimport { parseBody, parseSectionChild } from \"./parse/body\";\nimport { replaceRelsWithPlaceholders } from \"./util/replace-media-placeholders\";\nimport { stringifyElement } from \"./util/stringify-element\";\n\nexport { parseArchive };\n\n/**\n * All part paths extracted from the DOCX package.\n * Field names correspond directly to the OOXML directory structure.\n */\nexport interface DocxPartRefs {\n /** word/headerN.xml keyed by rId */\n headers: Map<string, string>;\n /** word/footerN.xml keyed by rId */\n footers: Map<string, string>;\n /** word/footnotes.xml */\n footnotes?: string;\n /** word/endnotes.xml */\n endnotes?: string;\n /** word/comments.xml */\n comments?: string;\n /** Hyperlink targets keyed by rId (external URLs) */\n hyperlinks: Map<string, string>;\n /** word/charts/chartN.xml keyed by rId */\n charts: Map<string, string>;\n /** word/diagrams/dataN.xml keyed by rId */\n diagramData: Map<string, string>;\n /** word/media/* keyed by rId (from document.xml.rels) */\n media: Map<string, string>;\n /**\n * Per-part image/media relationships. Each part (document, headers, footers,\n * footnotes, …) has its own .rels with independent rId numbering, so drawings\n * inside a part must resolve images against that part's rels. Maps\n * partPath → (rId → mediaPath).\n */\n partMedia: Map<string, Map<string, string>>;\n /** Alternative format chunks (word/afchunkN.*) keyed by rId */\n afChunks: Map<string, string>;\n /** Sub-documents (word/subdocs/subdocN.docx) keyed by rId */\n subDocs: Map<string, string>;\n /** word/bibliography.xml */\n bibliography?: string;\n /** word/glossary/document.xml */\n glossary?: string;\n}\n\nexport interface DocxDocument {\n doc: ParsedArchive;\n /** word/document.xml → root w:document element */\n documentRoot: Element;\n /** word/document.xml → w:body element */\n body: Element;\n /** word/document.xml → w:background element */\n background?: Element;\n /** word/styles.xml */\n styles?: Element;\n /** word/numbering.xml */\n numbering?: Element;\n /** word/settings.xml */\n settings?: Element;\n /** word/fontTable.xml */\n fontTable?: Element;\n /** word/webSettings.xml */\n webSettings?: Element;\n partRefs: DocxPartRefs;\n /** docProps/core.xml */\n coreProps?: string;\n /** docProps/app.xml */\n appProps?: string;\n /** docProps/custom.xml */\n customProps?: string;\n /** [Content_Types].xml */\n contentTypes?: Element;\n}\n\nfunction resolveRelsPath(target: string): string {\n if (target.startsWith(\"/\")) return target.slice(1);\n if (target.startsWith(\"../\")) return target.replace(\"../\", \"\");\n return `word/${target}`;\n}\n\n/**\n * Resolve each embedded font's .odttf bytes through fontTable.xml.rels.\n * Reads the binary verbatim and flags it raw so the compiler copies it as-is\n * instead of re-obfuscating (the fontKey already matches the bytes).\n */\nfunction resolveEmbeddedFontData(fonts: EmbeddedFontOptionsWithKey[], doc: ParsedArchive): void {\n const relsEl = doc.get(\"word/_rels/fontTable.xml.rels\");\n if (!relsEl) return;\n const ridToPath = new Map<string, string>();\n for (const child of relsEl.elements ?? []) {\n if (child.name !== \"Relationship\") continue;\n const type = attr(child, \"Type\") ?? \"\";\n if (!type.includes(\"/font\")) continue;\n const id = attr(child, \"Id\") ?? \"\";\n const target = attr(child, \"Target\") ?? \"\";\n if (id && target) ridToPath.set(id, resolveRelsPath(target));\n }\n for (const font of fonts) {\n if (!font.embedRid) continue;\n const odttfPath = ridToPath.get(font.embedRid);\n if (!odttfPath) continue;\n const bytes = doc.getRaw(odttfPath);\n if (bytes) {\n font.data = Buffer.from(bytes);\n font.rawOdttf = true;\n font.odttfPath = odttfPath;\n }\n }\n}\n\nfunction parseDocPartRefs(doc: ParsedArchive): DocxPartRefs {\n const refs: DocxPartRefs = {\n headers: new Map(),\n footers: new Map(),\n hyperlinks: new Map(),\n charts: new Map(),\n diagramData: new Map(),\n media: new Map(),\n partMedia: new Map(),\n afChunks: new Map(),\n subDocs: new Map(),\n };\n\n const relsEl = doc.get(\"word/_rels/document.xml.rels\");\n if (!relsEl) return refs;\n\n for (const child of relsEl.elements ?? []) {\n if (child.name !== \"Relationship\") continue;\n const type = attr(child, \"Type\") ?? \"\";\n const target = attr(child, \"Target\") ?? \"\";\n const id = attr(child, \"Id\") ?? \"\";\n if (!target) continue;\n\n const path = resolveRelsPath(target);\n\n if (type.includes(\"/header\")) {\n refs.headers.set(id, path);\n } else if (type.includes(\"/footer\")) {\n refs.footers.set(id, path);\n } else if (type.includes(\"/footnotes\")) {\n refs.footnotes = path;\n } else if (type.includes(\"/endnotes\")) {\n refs.endnotes = path;\n } else if (type.includes(\"/comments\")) {\n refs.comments = path;\n } else if (type.includes(\"/chart\")) {\n refs.charts.set(id, path);\n } else if (type.includes(\"/diagramData\")) {\n refs.diagramData.set(id, path);\n } else if (type.includes(\"/image\") || type.includes(\"/media\")) {\n refs.media.set(id, path);\n } else if (type.includes(\"/aFChunk\")) {\n refs.afChunks.set(id, path);\n } else if (type.includes(\"/subDocument\")) {\n refs.subDocs.set(id, path);\n } else if (type.includes(\"/bibliography\")) {\n refs.bibliography = path;\n } else if (type.includes(\"/glossaryDocument\")) {\n refs.glossary = path;\n } else if (type.includes(\"/hyperlink\")) {\n refs.hyperlinks.set(id, target);\n }\n }\n\n // Per-part image relationships. Each part carries its own .rels with\n // independent rId numbering (document rId1 ≠ header rId1), so collect them\n // keyed by part path; drawings inside a part resolve images through its\n // own rels. Covers document, headers, footers, footnotes, endnotes, comments.\n for (const relsPath of doc.keys(\"word/_rels/\")) {\n if (!relsPath.endsWith(\".rels\")) continue;\n const relsEl = doc.get(relsPath);\n if (!relsEl) continue;\n const partPath = \"word/\" + relsPath.slice(\"word/_rels/\".length, -\".rels\".length);\n for (const rel of relsEl.elements ?? []) {\n if (rel.name !== \"Relationship\") continue;\n const type = attr(rel, \"Type\") ?? \"\";\n if (!type.includes(\"/image\") && !type.includes(\"/media\")) continue;\n const id = attr(rel, \"Id\") ?? \"\";\n const target = attr(rel, \"Target\") ?? \"\";\n if (!id || !target) continue;\n let partMap = refs.partMedia.get(partPath);\n if (!partMap) {\n partMap = new Map();\n refs.partMedia.set(partPath, partMap);\n }\n partMap.set(id, resolveRelsPath(target));\n }\n }\n\n return refs;\n}\n\nfunction parseRootRels(doc: ParsedArchive): {\n coreProps?: string;\n appProps?: string;\n customProps?: string;\n} {\n const relsEl = doc.get(\"_rels/.rels\");\n if (!relsEl) return {};\n\n let coreProps: string | undefined;\n let appProps: string | undefined;\n let customProps: string | undefined;\n\n for (const child of relsEl.elements ?? []) {\n if (child.name !== \"Relationship\") continue;\n const type = attr(child, \"Type\") ?? \"\";\n const target = attr(child, \"Target\") ?? \"\";\n if (!target) continue;\n\n const path = target.startsWith(\"/\") ? target.slice(1) : target;\n\n if (type.includes(\"/core-properties\")) {\n coreProps = path;\n } else if (type.includes(\"/extended-properties\")) {\n appProps = path;\n } else if (type.includes(\"/custom-properties\")) {\n customProps = path;\n }\n }\n\n return { coreProps, appProps, customProps };\n}\n\n/**\n * Parse a .docx file and convert it into DocumentOptions.\n *\n * This is the main public API for parsing DOCX files.\n * The returned options can be passed directly to `new Document(parsed)`\n * to recreate the document.\n *\n * @param data - Raw bytes of a .docx file\n * @returns Document options including sections and metadata\n */\nexport function parseDocument(data: DataType): DocumentOptions {\n const docx = parseDocx(data);\n const ctx = new DocxReadContext(\n docx,\n buildStyleCache(docx.styles),\n buildNumberingCache(docx.numbering),\n );\n\n // Register the child parser for table and body child descriptors\n setTableParseChild(parseSectionChild);\n setBodyParseChild(parseSectionChild);\n\n const sections = parseBody(docx.body, ctx);\n\n const opts: Partial<DocumentOptions> = { sections };\n\n // Document conformance class (w:document/@w:conformance)\n const conformance = attr(docx.documentRoot, \"w:conformance\");\n if (conformance === \"strict\" || conformance === \"transitional\") opts.conformance = conformance;\n\n // Background (w:background in document.xml)\n if (docx.background) {\n const hasChildren = (docx.background.elements ?? []).some((e) => e.type === \"element\");\n if (hasChildren) {\n // VML/structured background (e.g. v:background/v:fill pattern with a\n // texture image) that doesn't fit the color/theme model: carry the\n // element verbatim, rewriting relationship refs to {fileName} placeholders\n // so the media round-trips via the compiler's placeholder pass.\n const { rawXml, rawMedia } = replaceRelsWithPlaceholders(\n stringifyElement(docx.background),\n ctx,\n \"background\",\n );\n opts.background = rawMedia.length > 0 ? { rawXml, rawMedia } : { rawXml };\n } else {\n const bg: NonNullable<DocumentOptions[\"background\"]> = {};\n const color = attr(docx.background, \"w:color\");\n if (color) bg.color = color;\n const themeColor = attr(docx.background, \"w:themeColor\");\n if (themeColor) bg.themeColor = themeColor;\n const themeShade = attr(docx.background, \"w:themeShade\");\n if (themeShade) bg.themeShade = themeShade;\n const themeTint = attr(docx.background, \"w:themeTint\");\n if (themeTint) bg.themeTint = themeTint;\n if (Object.keys(bg).length > 0) opts.background = bg;\n }\n }\n\n // Core properties\n if (docx.coreProps) {\n const corePropsEl = docx.doc.get(docx.coreProps);\n if (corePropsEl) {\n const cp = corePropertiesDesc.parse(corePropsEl, ctx);\n if (cp.title) opts.title = cp.title;\n if (cp.subject) opts.subject = cp.subject;\n if (cp.creator) opts.creator = cp.creator;\n if (cp.keywords) opts.keywords = cp.keywords;\n if (cp.description) opts.description = cp.description;\n if (cp.lastModifiedBy) opts.lastModifiedBy = cp.lastModifiedBy;\n if (cp.revision) opts.revision = cp.revision;\n if (cp.lastPrinted) opts.lastPrinted = cp.lastPrinted;\n if (cp.created) opts.created = cp.created;\n if (cp.modified) opts.modified = cp.modified;\n }\n }\n\n // App (extended) properties\n if (docx.appProps) {\n const appPropsEl = docx.doc.get(docx.appProps);\n if (appPropsEl) {\n const ap = appPropertiesDesc.parse(appPropsEl, ctx);\n if (Object.keys(ap).length > 0) opts.appProperties = ap;\n }\n }\n\n // Settings — parse produces a structured SettingsOptions aligned with\n // generate (no verbatim rawXml fallback). Assign wholesale so context.ts\n // spreads it into _settingsOptions for the descriptor's stringify input.\n if (docx.settings) {\n opts.settings = settingsDesc.parse(docx.settings, ctx);\n }\n\n // Web settings — preserve the part on round-trip even when it has no\n // children. Dropping it leaves an orphaned Override in the passthrough\n // [Content_Types].xml (the part is gone but its Override remains), which is\n // an OPC violation; keeping presence keeps part + rel + Override in sync.\n if (docx.webSettings) {\n opts.webSettings = webSettingsDesc.parse(docx.webSettings, ctx);\n }\n\n // Custom properties\n if (docx.customProps) {\n const customPropsEl = docx.doc.get(docx.customProps);\n if (customPropsEl) {\n const cpResult = customPropertiesDesc.parse(customPropsEl, ctx);\n if (cpResult.properties && cpResult.properties.length > 0) {\n opts.customProperties = cpResult.properties;\n }\n }\n }\n\n // Comments content\n if (docx.partRefs.comments) {\n const commentsEl = docx.doc.get(docx.partRefs.comments);\n if (commentsEl) {\n const commentsResult = ctx.withPart(docx.partRefs.comments, () =>\n commentsDesc.parse(commentsEl, ctx),\n );\n const children = commentsResult.children;\n if (children && children.length > 0) {\n opts.comments = { children };\n }\n }\n }\n\n // Footnotes content\n if (docx.partRefs.footnotes) {\n const footnotesEl = docx.doc.get(docx.partRefs.footnotes);\n if (footnotesEl) {\n const fnResult = ctx.withPart(docx.partRefs.footnotes, () =>\n footnotesDesc.parse(footnotesEl, ctx),\n );\n const footnotesMap: NonNullable<DocumentOptions[\"footnotes\"]> = {};\n for (const [id, paragraphs] of fnResult.notes) {\n footnotesMap[String(id)] = { children: paragraphs };\n }\n // Preserve round-tripped separators so the generated ids stay consistent\n // with settings.footnotePr (which references them).\n if (\n Object.keys(footnotesMap).length > 0 ||\n fnResult.separator ||\n fnResult.continuationSeparator\n ) {\n if (fnResult.separator) footnotesMap.separator = fnResult.separator;\n if (fnResult.continuationSeparator)\n footnotesMap.continuationSeparator = fnResult.continuationSeparator;\n opts.footnotes = footnotesMap;\n }\n }\n }\n\n // Endnotes content\n if (docx.partRefs.endnotes) {\n const endnotesEl = docx.doc.get(docx.partRefs.endnotes);\n if (endnotesEl) {\n const enResult = ctx.withPart(docx.partRefs.endnotes, () =>\n endnotesDesc.parse(endnotesEl, ctx),\n );\n const endnotesMap: NonNullable<DocumentOptions[\"endnotes\"]> = {};\n for (const [id, paragraphs] of enResult.notes) {\n endnotesMap[String(id)] = { children: paragraphs };\n }\n if (\n Object.keys(endnotesMap).length > 0 ||\n enResult.separator ||\n enResult.continuationSeparator\n ) {\n if (enResult.separator) endnotesMap.separator = enResult.separator;\n if (enResult.continuationSeparator)\n endnotesMap.continuationSeparator = enResult.continuationSeparator;\n opts.endnotes = endnotesMap;\n }\n }\n }\n\n // Styles definitions\n if (docx.styles) {\n const styleOpts = parseStyleDefinitions(docx.styles, parseParagraphProperties, ctx);\n if (styleOpts) opts.styles = styleOpts;\n }\n\n // Numbering definitions\n if (docx.numbering) {\n const numOpts = parseNumberingDefinitions(docx.numbering, parseParagraphProperties, ctx);\n if (numOpts) opts.numbering = numOpts;\n }\n\n // Font table\n if (docx.fontTable) {\n const ftResult = fontTableDesc.parse(docx.fontTable, ctx);\n if (ftResult.fonts && ftResult.fonts.length > 0) {\n resolveEmbeddedFontData(ftResult.fonts, docx.doc);\n opts.fonts = ftResult.fonts;\n }\n }\n\n // Bibliography\n if (docx.partRefs.bibliography) {\n const bibEl = docx.doc.get(docx.partRefs.bibliography);\n if (bibEl) {\n const bibResult = bibliographyDesc.parse(bibEl, ctx);\n if (bibResult.sources && bibResult.sources.length > 0) opts.bibliography = bibResult;\n }\n }\n\n // Glossary document\n if (docx.partRefs.glossary) {\n const glossaryEl = docx.doc.get(docx.partRefs.glossary);\n if (glossaryEl) {\n const glossaryResult = ctx.withPart(docx.partRefs.glossary, () =>\n glossaryDesc.parse(glossaryEl, ctx),\n );\n if (glossaryResult.parts && glossaryResult.parts.length > 0) opts.glossary = glossaryResult;\n }\n }\n\n // Content types\n if (docx.contentTypes) {\n const ctResult = contentTypesDesc.parse(docx.contentTypes, ctx);\n if (ctResult) opts.contentTypes = ctResult;\n }\n\n // Raw passthrough: parts generate() doesn't rebuild (word/theme/*, customXml/*).\n // Carried verbatim so their [Content_Types] declarations stay valid and the\n // package opens in Word. (Media/fonts/headers/etc. are rebuilt by the compiler\n // and must NOT be passed through — they'd otherwise duplicate under renamed paths.)\n const rawParts: { path: string; data: Uint8Array }[] = [];\n for (const prefix of [\"word/theme/\", \"customXml/\"]) {\n for (const p of docx.doc.keys(prefix)) {\n if (p.endsWith(\"/\")) continue;\n const data = docx.doc.getRaw(p);\n if (data) rawParts.push({ path: p, data });\n }\n }\n if (rawParts.length > 0) opts.rawParts = rawParts;\n\n return opts as DocumentOptions;\n}\n\nexport function parseDocx(data: DataType): DocxDocument {\n const uint8 = toUint8Array(data);\n const doc = parseArchive(uint8);\n\n const documentEl = doc.get(\"word/document.xml\");\n if (!documentEl) throw new Error(\"word/document.xml not found\");\n const body = documentEl.elements?.find((e) => e.name === \"w:body\");\n if (!body) throw new Error(\"w:body not found in word/document.xml\");\n const background = documentEl.elements?.find((e) => e.name === \"w:background\");\n\n const styles = doc.get(\"word/styles.xml\");\n const numbering = doc.get(\"word/numbering.xml\");\n const settings = doc.get(\"word/settings.xml\");\n const fontTable = doc.get(\"word/fontTable.xml\");\n const webSettings = doc.get(\"word/webSettings.xml\");\n\n const partRefs = parseDocPartRefs(doc);\n const { coreProps, appProps, customProps } = parseRootRels(doc);\n\n const contentTypes = doc.get(\"[Content_Types].xml\");\n\n return {\n doc,\n documentRoot: documentEl,\n body,\n background,\n styles,\n numbering,\n settings,\n fontTable,\n webSettings,\n partRefs,\n coreProps,\n appProps,\n customProps,\n contentTypes,\n };\n}\n"],"mappings":"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K,OAAO,QAAQ;QACnB,OAAO,QAAQ,KAAA;EACtB,OACE,OAAO,QAAQ,KAAA;CAEnB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
package/dist/parse.d.mts DELETED
@@ -1,2 +0,0 @@
1
- import { _ as parseArchive, g as DocxPartRefs, h as DocxDocument, v as parseDocument, y as parseDocx } from "./core-properties-BLnZI4Tr.mjs";
2
- export { DocxDocument, DocxPartRefs, parseArchive, parseDocument, parseDocx };
package/dist/parse.mjs DELETED
@@ -1,2 +0,0 @@
1
- import { n as parseDocument, r as parseDocx, t as parseArchive } from "./parse-CgAxzk5K.mjs";
2
- export { parseArchive, parseDocument, parseDocx };
@@ -1,47 +0,0 @@
1
- import { Ba as RunOptions, Xt as SectionChild, Yn as ParagraphChild, _r as CommentOptions } from "../core-properties-BLnZI4Tr.mjs";
2
- import { BasePatchOptions, CorePropertiesOptions, DataType, OutputByType, OutputType } from "@office-open/core";
3
-
4
- //#region src/patch/from-docx.d.ts
5
- type PatchComment = Omit<CommentOptions, "id">;
6
- type Patch = {
7
- type: "paragraph";
8
- children: (string | RunOptions | ParagraphChild)[];
9
- } | {
10
- type: "document";
11
- children: SectionChild[];
12
- };
13
- interface PatchDocumentOptions<T extends OutputType = OutputType> extends BasePatchOptions<T> {
14
- placeholders?: Readonly<Record<string, Patch>>;
15
- findReplace?: Readonly<Record<string, Patch>>;
16
- coreProperties?: Partial<CorePropertiesOptions>;
17
- keepOriginalStyles?: boolean;
18
- recursive?: boolean;
19
- append?: SectionChild[];
20
- comments?: {
21
- paragraphs?: Readonly<Record<number, PatchComment[]>>;
22
- placeholders?: Readonly<Record<string, PatchComment[]>>;
23
- };
24
- }
25
- declare const patchDocument: <T extends OutputType = OutputType>({
26
- outputType,
27
- data,
28
- placeholders,
29
- findReplace,
30
- coreProperties,
31
- append,
32
- comments,
33
- keepOriginalStyles,
34
- placeholderDelimiters,
35
- recursive
36
- }: PatchDocumentOptions<T>) => Promise<OutputByType[T]>;
37
- //#endregion
38
- //#region src/patch/patch-detector.d.ts
39
- interface PatchDetectorOptions {
40
- data: DataType;
41
- }
42
- declare const patchDetector: ({
43
- data
44
- }: PatchDetectorOptions) => Promise<string[]>;
45
- //#endregion
46
- export { Patch, PatchComment, PatchDocumentOptions, patchDetector, patchDocument };
47
- //# sourceMappingURL=index.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/patch/from-docx.ts","../../src/patch/patch-detector.ts"],"mappings":";;;;KAyDY,YAAA,GAAe,IAAI,CAAC,cAAA;AAAA,KA+HpB,KAAA;EACN,IAAA;EAAmB,QAAA,YAAoB,UAAA,GAAa,cAAA;AAAA;EACpD,IAAA;EAAkB,QAAA,EAAU,YAAA;AAAA;AAAA,UAYjB,oBAAA,WACL,UAAA,GAAa,UAAA,UACf,gBAAA,CAAiB,CAAA;EAEzB,YAAA,GAAe,QAAA,CAAS,MAAA,SAAe,KAAA;EAEvC,WAAA,GAAc,QAAA,CAAS,MAAA,SAAe,KAAA;EAEtC,cAAA,GAAiB,OAAA,CAAQ,qBAAA;EACzB,kBAAA;EACA,SAAA;EAEA,MAAA,GAAS,YAAA;EAOT,QAAA;IACE,UAAA,GAAa,QAAA,CAAS,MAAA,SAAe,YAAA;IACrC,YAAA,GAAe,QAAA,CAAS,MAAA,SAAe,YAAA;EAAA;AAAA;AAAA,cAwB9B,aAAA,aAAiC,UAAA,GAAa,UAAA;EAAY,UAAA;EAAA,IAAA;EAAA,YAAA;EAAA,WAAA;EAAA,cAAA;EAAA,MAAA;EAAA,QAAA;EAAA,kBAAA;EAAA,qBAAA;EAAA;AAAA,GAWpE,oBAAA,CAAqB,CAAA,MAAK,OAAA,CAAQ,YAAA,CAAa,CAAA;;;UChPxC,oBAAA;EACR,IAAA,EAAM,QAAQ;AAAA;AAAA,cA4BH,aAAA;EAAuB;AAAA,GAAU,oBAAA,KAAuB,OAAA"}
@@ -1,416 +0,0 @@
1
- import { d as stringifyParagraphInline, f as stringifyRunInline, o as tableDesc, t as commentsDesc, u as stringifyChildDispatch, xt as Media } from "../comments-D_flVfxw.mjs";
2
- import { t as DocumentAttributeNamespaces } from "../document-attributes-C6PDT-ap.mjs";
3
- import { DOCX_NS, OoxmlMimeType, TargetModeType, appendContentType, appendOverride, appendRelationship, applyCorePropertiesOverride, createReplacer, createTraverser, getNextRelationshipIndex, getReferencedMedia, nextNumericId, replaceImagePlaceholders, strFromU8, toJson, toUint8Array, unzipSync, zipAndConvert } from "@office-open/core";
4
- import { escapeXml, js2xml, xml2js } from "@office-open/xml";
5
- //#region src/patch/from-docx.ts
6
- /** Reusable TextEncoder (stateless, safe to share). */
7
- const encoder = new TextEncoder();
8
- const COMMENTS_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
9
- const COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml";
10
- /**
11
- * Document patching module for modifying existing .docx files.
12
- *
13
- * Uses compile-path stringifiers (zero class instantiation) to serialize
14
- * patch content — no Formatter, no XmlComponent instances.
15
- *
16
- * @module
17
- */
18
- /**
19
- * Lightweight BodyContext adapter for patch serialization.
20
- * Captures hyperlink and image relationships for post-processing.
21
- */
22
- function createPatchContext(file, hyperlinkSink) {
23
- return {
24
- fileData: file,
25
- file,
26
- viewWrapper: { relationships: {
27
- addRelationship: (linkId, _type, target, _mode) => {
28
- hyperlinkSink.push({
29
- id: linkId,
30
- link: target
31
- });
32
- },
33
- relationshipCount: 0
34
- } },
35
- stringifyChild: () => "",
36
- addRelationship: () => "",
37
- addMedia: () => ""
38
- };
39
- }
40
- /**
41
- * Serialize a patch child (SectionChild / ParagraphChild / string) into XML
42
- * elements via the compile-path stringifiers. Shared by the placeholder
43
- * replacer and body-level `append`. Relies on the module-level
44
- * {@link currentPatchCtx} for relationship/media sinks.
45
- */
46
- const formatChildElement = (child) => {
47
- let xmlStr;
48
- if (typeof child === "string") xmlStr = `<w:r><w:t xml:space="preserve">${escapeXml(child)}</w:t></w:r>`;
49
- else if (typeof child === "object" && child !== null) {
50
- const obj = child;
51
- if ("paragraph" in obj) xmlStr = stringifyParagraphInline(obj.paragraph, currentPatchCtx);
52
- else if ("table" in obj) xmlStr = tableDesc.stringify(obj.table, currentPatchCtx) ?? "";
53
- else {
54
- const jr = stringifyChildDispatch(child, currentPatchCtx);
55
- if (jr !== void 0) xmlStr = Array.isArray(jr) ? jr.join("") : jr;
56
- else xmlStr = stringifyRunInline(child, currentPatchCtx);
57
- }
58
- } else xmlStr = "<w:r/>";
59
- const rootEl = xml2js(xmlStr, { captureSpacesBetweenElements: true }).elements?.[0];
60
- return rootEl ? [rootEl] : [];
61
- };
62
- const docxReplacer = createReplacer({
63
- ns: DOCX_NS,
64
- formatChild: formatChildElement
65
- });
66
- /**
67
- * Splice block-level children into `<w:body>` before the trailing `<w:sectPr>`
68
- * (the final section properties). If the body has no trailing sectPr, append at
69
- * the end. Reuses {@link formatChildElement} so the same serialization and
70
- * relationship/media sinks apply as placeholder patches.
71
- */
72
- const appendToBody = (root, children) => {
73
- const body = (root.elements?.find((e) => e.name === "w:document"))?.elements?.find((e) => e.name === "w:body");
74
- if (!body) return;
75
- const els = body.elements ?? (body.elements = []);
76
- const newEls = [];
77
- for (const child of children) newEls.push(...formatChildElement(child));
78
- let insertAt = els.length;
79
- for (let i = els.length - 1; i >= 0; i--) {
80
- const el = els[i];
81
- if (el && el.name === "w:sectPr") {
82
- insertAt = i;
83
- break;
84
- }
85
- }
86
- els.splice(insertAt, 0, ...newEls);
87
- };
88
- /** Current patch context — set per file in the main loop. */
89
- let currentPatchCtx;
90
- const UTF16LE = new Uint8Array([255, 254]);
91
- const UTF16BE = new Uint8Array([254, 255]);
92
- const compareByteArrays = (a, b) => {
93
- if (a.length !== b.length) return false;
94
- for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
95
- return true;
96
- };
97
- /**
98
- * Patches an existing .docx document by replacing placeholders with new content.
99
- *
100
- * @publicApi
101
- */
102
- const patchDocument = async ({ outputType, data, placeholders, findReplace, coreProperties, append, comments, keepOriginalStyles = true, placeholderDelimiters = {
103
- end: "}}",
104
- start: "{{"
105
- }, recursive = true }) => {
106
- const zipContent = unzipSync(toUint8Array(data));
107
- const contexts = /* @__PURE__ */ new Map();
108
- const media = new Media();
109
- const file = { media };
110
- const assignedComments = buildAssignedComments(zipContent, comments);
111
- const map = /* @__PURE__ */ new Map();
112
- const imageRelationshipAdditions = [];
113
- const hyperlinkRelationshipAdditions = [];
114
- let hasMedia = false;
115
- const binaryContentMap = /* @__PURE__ */ new Map();
116
- for (const [key, value] of Object.entries(zipContent)) {
117
- const startBytes = value.slice(0, 2);
118
- if (compareByteArrays(startBytes, UTF16LE) || compareByteArrays(startBytes, UTF16BE)) {
119
- binaryContentMap.set(key, value);
120
- continue;
121
- }
122
- if (!key.endsWith(".xml") && !key.endsWith(".rels")) {
123
- binaryContentMap.set(key, value);
124
- continue;
125
- }
126
- const json = toJson(strFromU8(value));
127
- if (key === "word/document.xml") {
128
- const document = json.elements?.find((i) => i.name === "w:document");
129
- if (document && document.attributes) {
130
- for (const ns of [
131
- "mc",
132
- "wp",
133
- "r",
134
- "w15",
135
- "m"
136
- ]) document.attributes[`xmlns:${ns}`] = DocumentAttributeNamespaces[ns];
137
- document.attributes["mc:Ignorable"] = `${document.attributes["mc:Ignorable"] || ""} w15`.trim();
138
- }
139
- }
140
- if (key.startsWith("word/") && !key.endsWith(".xml.rels")) {
141
- const hyperlinkSink = [];
142
- const context = {
143
- fileData: file,
144
- file,
145
- viewWrapper: { relationships: { addRelationship: (linkId, _, target, __) => {
146
- hyperlinkRelationshipAdditions.push({
147
- hyperlink: {
148
- id: linkId,
149
- link: target
150
- },
151
- key
152
- });
153
- } } },
154
- stringifyChild: () => "",
155
- addRelationship: () => "",
156
- addMedia: () => ""
157
- };
158
- contexts.set(key, context);
159
- if (!placeholderDelimiters?.start.trim() || !placeholderDelimiters?.end.trim()) throw new Error("Both start and end delimiters must be non-empty strings.");
160
- const { start, end } = placeholderDelimiters;
161
- currentPatchCtx = createPatchContext(file, hyperlinkSink);
162
- if (key === "word/document.xml") {
163
- for (const ac of assignedComments) if (ac.anchor.kind === "placeholder") wrapPlaceholderComment(json, `${start}${ac.anchor.key}${end}`, ac.id);
164
- }
165
- const entries = [];
166
- if (placeholders) for (const [key, value] of Object.entries(placeholders)) entries.push({
167
- find: `${start}${key}${end}`,
168
- patch: value
169
- });
170
- if (findReplace) for (const [key, value] of Object.entries(findReplace)) entries.push({
171
- find: key,
172
- patch: value
173
- });
174
- for (const { find: patchText, patch: patchValue } of entries) while (true) {
175
- const { didFindOccurrence } = docxReplacer({
176
- context,
177
- json,
178
- keepOriginalStyles,
179
- patch: patchValue,
180
- patchText
181
- });
182
- if (!recursive || !didFindOccurrence) break;
183
- }
184
- if (append && append.length > 0 && key === "word/document.xml") appendToBody(json, append);
185
- if (key === "word/document.xml") {
186
- for (const ac of assignedComments) if (ac.anchor.kind === "paragraph") wrapParagraphComment(json, ac.anchor.index, ac.id);
187
- }
188
- for (const hl of hyperlinkSink) hyperlinkRelationshipAdditions.push({
189
- hyperlink: {
190
- id: hl.id,
191
- link: hl.link
192
- },
193
- key
194
- });
195
- const mediaDatas = getReferencedMedia(JSON.stringify(json), media.array);
196
- if (mediaDatas.length > 0) {
197
- hasMedia = true;
198
- imageRelationshipAdditions.push({
199
- key,
200
- mediaDatas
201
- });
202
- }
203
- }
204
- map.set(key, json);
205
- }
206
- if (assignedComments.length > 0) mergeCommentsPart(map, assignedComments, file);
207
- for (const { key, mediaDatas } of imageRelationshipAdditions) {
208
- const relationshipKey = `word/_rels/${key.split("/").pop()}.rels`;
209
- const relationshipsJson = map.get(relationshipKey) ?? createRelationshipFile();
210
- map.set(relationshipKey, relationshipsJson);
211
- const index = getNextRelationshipIndex(relationshipsJson);
212
- const newJson = replaceImagePlaceholders(JSON.stringify(map.get(key)), mediaDatas, index, "plain");
213
- map.set(key, JSON.parse(newJson));
214
- for (const [i, media] of mediaDatas.entries()) {
215
- const { fileName } = media;
216
- appendRelationship(relationshipsJson, index + i, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", `media/${fileName}`);
217
- }
218
- }
219
- for (const { key, hyperlink } of hyperlinkRelationshipAdditions) {
220
- const relationshipKey = `word/_rels/${key.split("/").pop()}.rels`;
221
- const relationshipsJson = map.get(relationshipKey) ?? createRelationshipFile();
222
- map.set(relationshipKey, relationshipsJson);
223
- appendRelationship(relationshipsJson, hyperlink.id, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", hyperlink.link, TargetModeType.EXTERNAL);
224
- }
225
- if (hasMedia) {
226
- const contentTypesJson = map.get("[Content_Types].xml");
227
- if (!contentTypesJson) throw new Error("Could not find content types file");
228
- appendContentType(contentTypesJson, "image/png", "png");
229
- appendContentType(contentTypesJson, "image/jpeg", "jpeg");
230
- appendContentType(contentTypesJson, "image/jpeg", "jpg");
231
- appendContentType(contentTypesJson, "image/bmp", "bmp");
232
- appendContentType(contentTypesJson, "image/gif", "gif");
233
- appendContentType(contentTypesJson, "image/svg+xml", "svg");
234
- }
235
- const files = {};
236
- const XML_DECL = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
237
- for (const [key, value] of map) files[key] = key === "docProps/core.xml" && coreProperties ? encoder.encode(XML_DECL + applyCorePropertiesOverride(value, coreProperties)) : encoder.encode(js2xml(value));
238
- for (const [key, value] of binaryContentMap) files[key] = value;
239
- for (const { data: mediaData, fileName } of media.array) files[`word/media/${fileName}`] = mediaData instanceof Uint8Array ? mediaData : new Uint8Array(mediaData);
240
- return await zipAndConvert(files, outputType, OoxmlMimeType.DOCX);
241
- };
242
- const createRelationshipFile = () => ({
243
- declaration: { attributes: {
244
- encoding: "UTF-8",
245
- standalone: "yes",
246
- version: "1.0"
247
- } },
248
- elements: [{
249
- attributes: { xmlns: "http://schemas.openxmlformats.org/package/2006/relationships" },
250
- elements: [],
251
- name: "Relationships",
252
- type: "element"
253
- }]
254
- });
255
- /** Build a bare OOXML element node with attributes and no children. */
256
- function makeElement(name, attributes = {}) {
257
- return {
258
- type: "element",
259
- name,
260
- attributes,
261
- elements: []
262
- };
263
- }
264
- /** A `<w:r>` carrying a `<w:commentReference>` (CommentReference run style). */
265
- function commentReferenceRun(id) {
266
- return xml2js(`<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="${id}"/></w:r>`).elements[0];
267
- }
268
- /** Next continuation id for an appended `<w:comment>` (-1 seed → 0 when none). */
269
- function nextCommentId(commentsPart) {
270
- const root = commentsPart?.elements?.find((e) => e.name === "w:comments");
271
- return nextNumericId(root, "w:comment", "w:id", -1);
272
- }
273
- /** Assign continuation ids to every requested comment anchor. */
274
- function buildAssignedComments(zipContent, comments) {
275
- if (!comments) return [];
276
- const raw = zipContent["word/comments.xml"];
277
- let nextId = raw ? nextCommentId(toJson(strFromU8(raw))) : 0;
278
- const assigned = [];
279
- if (comments.placeholders) for (const [key, list] of Object.entries(comments.placeholders)) for (const options of list) assigned.push({
280
- id: nextId++,
281
- anchor: {
282
- kind: "placeholder",
283
- key
284
- },
285
- options
286
- });
287
- if (comments.paragraphs) for (const [indexStr, list] of Object.entries(comments.paragraphs)) {
288
- const index = Number(indexStr);
289
- for (const options of list) assigned.push({
290
- id: nextId++,
291
- anchor: {
292
- kind: "paragraph",
293
- index
294
- },
295
- options
296
- });
297
- }
298
- return assigned;
299
- }
300
- /** Wrap the Nth body paragraph with comment range markers + a reference run. */
301
- function wrapParagraphComment(json, index, commentId) {
302
- const body = json.elements?.find((e) => e.name === "w:document")?.elements?.find((e) => e.name === "w:body");
303
- if (!body) return;
304
- const target = (body.elements ?? []).filter((e) => e.name === "w:p")[index];
305
- if (!target) throw new Error(`patchDocument: no paragraph at index ${index} to comment`);
306
- const els = target.elements ?? (target.elements = []);
307
- const start = makeElement("w:commentRangeStart", { "w:id": String(commentId) });
308
- const end = makeElement("w:commentRangeEnd", { "w:id": String(commentId) });
309
- const first = els[0];
310
- const insertAt = first && first.name === "w:pPr" ? 1 : 0;
311
- els.splice(insertAt, 0, start);
312
- els.push(end, commentReferenceRun(commentId));
313
- }
314
- /** Wrap the first run whose `<w:t>` contains the placeholder with comment markers. */
315
- function wrapPlaceholderComment(json, placeholder, commentId) {
316
- const body = json.elements?.find((e) => e.name === "w:document")?.elements?.find((e) => e.name === "w:body");
317
- if (!body) return;
318
- for (const p of body.elements ?? []) {
319
- if (p.name !== "w:p") continue;
320
- const els = p.elements ?? [];
321
- for (const [i, el] of els.entries()) {
322
- if (el.name !== "w:r") continue;
323
- const text = (el.elements ?? []).find((e) => e.name === "w:t")?.elements?.[0]?.text;
324
- if (typeof text === "string" && text.includes(placeholder)) {
325
- els.splice(i, 0, makeElement("w:commentRangeStart", { "w:id": String(commentId) }));
326
- els.splice(i + 2, 0, makeElement("w:commentRangeEnd", { "w:id": String(commentId) }), commentReferenceRun(commentId));
327
- return;
328
- }
329
- }
330
- }
331
- }
332
- /**
333
- * Merge assigned comments into word/comments.xml (appending to an existing part
334
- * or creating one) and wire document.xml.rels + content types when newly added.
335
- */
336
- function mergeCommentsPart(map, assigned, file) {
337
- const newOpts = assigned.map((ac) => ({
338
- id: ac.id,
339
- ...ac.options
340
- }));
341
- const ctx = createPatchContext(file, []);
342
- const newXml = commentsDesc.stringify({ children: newOpts }, ctx) ?? "";
343
- const existingEl = map.get("word/comments.xml");
344
- const wasNew = !existingEl;
345
- if (existingEl) {
346
- const existingRoot = existingEl.elements?.find((e) => e.name === "w:comments");
347
- const newRoot = xml2js(newXml).elements?.find((e) => e.name === "w:comments");
348
- existingRoot?.elements?.push(...newRoot?.elements ?? []);
349
- } else map.set("word/comments.xml", toJson(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>${newXml}`));
350
- if (wasNew) {
351
- const relsKey = "word/_rels/document.xml.rels";
352
- const relsJson = map.get(relsKey) ?? createRelationshipFile();
353
- map.set(relsKey, relsJson);
354
- appendRelationship(relsJson, getNextRelationshipIndex(relsJson), COMMENTS_REL_TYPE, "comments.xml");
355
- }
356
- const contentTypes = map.get("[Content_Types].xml");
357
- if (contentTypes) appendOverride(contentTypes, "/word/comments.xml", COMMENTS_CONTENT_TYPE);
358
- }
359
- //#endregion
360
- //#region src/patch/patch-detector.ts
361
- /**
362
- * Patch detector for discovering placeholders in document templates.
363
- *
364
- * @module
365
- */
366
- /**
367
- * Detects all placeholders present in a document template.
368
- *
369
- * Scans through all XML content in a .docx file to find placeholder text
370
- * enclosed in delimiters (default: {{placeholder}}). This is useful for
371
- * discovering what patches a template expects before performing replacement.
372
- *
373
- * @param options - Patch detector configuration
374
- * @returns Array of placeholder keys found in the document
375
- *
376
- * @example
377
- * ```typescript
378
- * const placeholders = await patchDetector({ data: templateBuffer });
379
- * // Returns: ["name", "date", "address"] if template contains {{name}}, {{date}}, {{address}}
380
- *
381
- * // Use detected placeholders to create patches
382
- * const patches = {};
383
- * for (const key of placeholders) {
384
- * patches[key] = {
385
- * type: "paragraph",
386
- * children: [new TextRun(getUserData(key))],
387
- * };
388
- * });
389
- * ```
390
- */
391
- const patchDetector = async ({ data }) => {
392
- const zipContent = unzipSync(toUint8Array(data));
393
- const patches = /* @__PURE__ */ new Set();
394
- for (const [key, value] of Object.entries(zipContent)) {
395
- if (!key.endsWith(".xml") && !key.endsWith(".rels")) continue;
396
- if (key.startsWith("word/") && !key.endsWith(".xml.rels")) {
397
- const json = toJson(strFromU8(value));
398
- const { traverse } = createTraverser(DOCX_NS);
399
- for (const p of traverse(json)) for (const patch of findPatchKeys(p.text)) patches.add(patch);
400
- }
401
- }
402
- return [...patches];
403
- };
404
- /**
405
- * Extracts placeholder keys from text using regex pattern.
406
- *
407
- * @param text - Text to search for placeholders
408
- * @returns Array of placeholder keys (without delimiters)
409
- */
410
- const findPatchKeys = (text) => {
411
- return text.match(/(?<=\{\{).+?(?=\}\})/gs) ?? [];
412
- };
413
- //#endregion
414
- export { patchDetector, patchDocument };
415
-
416
- //# sourceMappingURL=index.mjs.map