@bendyline/squisq-formats 1.3.0 → 1.4.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.
Files changed (224) hide show
  1. package/dist/chunk-6M7Z25LA.js +46 -0
  2. package/dist/chunk-6M7Z25LA.js.map +1 -0
  3. package/dist/{chunk-S3Y7H2BK.js → chunk-APSIAEXL.js} +9 -8
  4. package/dist/chunk-APSIAEXL.js.map +1 -0
  5. package/dist/{chunk-UDS45KUJ.js → chunk-BJQIJ4S4.js} +36 -52
  6. package/dist/chunk-BJQIJ4S4.js.map +1 -0
  7. package/dist/{chunk-33YRFXZZ.js → chunk-CRTC6DEX.js} +259 -13
  8. package/dist/chunk-CRTC6DEX.js.map +1 -0
  9. package/dist/chunk-FMOIGA5T.js +201 -0
  10. package/dist/chunk-FMOIGA5T.js.map +1 -0
  11. package/dist/{chunk-VN2KEOYB.js → chunk-I2GFTEOV.js} +321 -91
  12. package/dist/chunk-I2GFTEOV.js.map +1 -0
  13. package/dist/chunk-JBNVE2GV.js +116 -0
  14. package/dist/chunk-JBNVE2GV.js.map +1 -0
  15. package/dist/chunk-L53YIGYS.js +141 -0
  16. package/dist/chunk-L53YIGYS.js.map +1 -0
  17. package/dist/{chunk-ERZ627GR.js → chunk-ON232HJR.js} +11 -26
  18. package/dist/chunk-ON232HJR.js.map +1 -0
  19. package/dist/chunk-PN52A5AA.js +32 -0
  20. package/dist/chunk-PN52A5AA.js.map +1 -0
  21. package/dist/{chunk-7DEUGIOO.js → chunk-QSE7EWE7.js} +12 -87
  22. package/dist/chunk-QSE7EWE7.js.map +1 -0
  23. package/dist/container/index.d.ts +7 -5
  24. package/dist/container/index.js +39 -70
  25. package/dist/container/index.js.map +1 -1
  26. package/dist/csv/index.d.ts +37 -0
  27. package/dist/csv/index.js +13 -0
  28. package/dist/csv/index.js.map +1 -0
  29. package/dist/docx/index.d.ts +128 -15
  30. package/dist/docx/index.js +19 -22
  31. package/dist/docx/index.js.map +1 -1
  32. package/dist/epub/index.d.ts +66 -11
  33. package/dist/epub/index.js +11 -18
  34. package/dist/epub/index.js.map +1 -1
  35. package/dist/html/index.d.ts +315 -15
  36. package/dist/html/index.js +32 -165
  37. package/dist/html/index.js.map +1 -1
  38. package/dist/index.d.ts +10 -38
  39. package/dist/index.js +80 -37
  40. package/dist/index.js.map +1 -1
  41. package/dist/ooxml/index.d.ts +353 -14
  42. package/dist/ooxml/index.js +116 -22
  43. package/dist/ooxml/index.js.map +1 -1
  44. package/dist/pdf/index.d.ts +143 -17
  45. package/dist/pdf/index.js +16 -25
  46. package/dist/pdf/index.js.map +1 -1
  47. package/dist/pptx/index.d.ts +98 -21
  48. package/dist/pptx/index.js +18 -34
  49. package/dist/pptx/index.js.map +1 -1
  50. package/dist/xlsx/index.d.ts +29 -25
  51. package/dist/xlsx/index.js +13 -44
  52. package/dist/xlsx/index.js.map +1 -1
  53. package/package.json +7 -2
  54. package/src/__tests__/csvImport.test.ts +51 -0
  55. package/src/__tests__/exportThemeReconciliation.test.ts +87 -0
  56. package/src/__tests__/htmlImport.test.ts +57 -0
  57. package/src/__tests__/plainHtml.test.ts +31 -0
  58. package/src/__tests__/pptxExport.test.ts +138 -0
  59. package/src/__tests__/pptxImport.test.ts +70 -0
  60. package/src/__tests__/roundTripMatrix.fixtures.ts +86 -0
  61. package/src/__tests__/roundTripMatrix.helpers.ts +154 -0
  62. package/src/__tests__/roundTripMatrix.test.ts +136 -0
  63. package/src/__tests__/xlsxImport.test.ts +80 -0
  64. package/src/csv/index.ts +165 -0
  65. package/src/docx/export.ts +27 -44
  66. package/src/docx/import.ts +1 -2
  67. package/src/epub/export.ts +10 -27
  68. package/src/html/import.ts +297 -0
  69. package/src/html/index.ts +4 -0
  70. package/src/html/plainHtml.ts +66 -16
  71. package/src/index.ts +10 -3
  72. package/src/ooxml/namespaces.ts +3 -0
  73. package/src/pdf/export.ts +10 -5
  74. package/src/pdf/import.ts +1 -1
  75. package/src/pptx/export.ts +225 -85
  76. package/src/pptx/import.ts +156 -0
  77. package/src/pptx/index.ts +10 -28
  78. package/src/shared/inlineRuns.ts +99 -0
  79. package/src/shared/text.ts +41 -0
  80. package/src/xlsx/import.ts +159 -0
  81. package/src/xlsx/index.ts +11 -28
  82. package/dist/__tests__/container.test.d.ts +0 -8
  83. package/dist/__tests__/container.test.d.ts.map +0 -1
  84. package/dist/__tests__/container.test.js +0 -147
  85. package/dist/__tests__/container.test.js.map +0 -1
  86. package/dist/__tests__/docxExport.test.d.ts +0 -8
  87. package/dist/__tests__/docxExport.test.d.ts.map +0 -1
  88. package/dist/__tests__/docxExport.test.js +0 -383
  89. package/dist/__tests__/docxExport.test.js.map +0 -1
  90. package/dist/__tests__/docxImport.test.d.ts +0 -8
  91. package/dist/__tests__/docxImport.test.d.ts.map +0 -1
  92. package/dist/__tests__/docxImport.test.js +0 -309
  93. package/dist/__tests__/docxImport.test.js.map +0 -1
  94. package/dist/__tests__/epub.test.d.ts +0 -8
  95. package/dist/__tests__/epub.test.d.ts.map +0 -1
  96. package/dist/__tests__/epub.test.js +0 -472
  97. package/dist/__tests__/epub.test.js.map +0 -1
  98. package/dist/__tests__/html.test.d.ts +0 -8
  99. package/dist/__tests__/html.test.d.ts.map +0 -1
  100. package/dist/__tests__/html.test.js +0 -317
  101. package/dist/__tests__/html.test.js.map +0 -1
  102. package/dist/__tests__/ooxml.test.d.ts +0 -5
  103. package/dist/__tests__/ooxml.test.d.ts.map +0 -1
  104. package/dist/__tests__/ooxml.test.js +0 -152
  105. package/dist/__tests__/ooxml.test.js.map +0 -1
  106. package/dist/__tests__/pdfExport.test.d.ts +0 -8
  107. package/dist/__tests__/pdfExport.test.d.ts.map +0 -1
  108. package/dist/__tests__/pdfExport.test.js +0 -275
  109. package/dist/__tests__/pdfExport.test.js.map +0 -1
  110. package/dist/__tests__/pdfImport.test.d.ts +0 -11
  111. package/dist/__tests__/pdfImport.test.d.ts.map +0 -1
  112. package/dist/__tests__/pdfImport.test.js +0 -254
  113. package/dist/__tests__/pdfImport.test.js.map +0 -1
  114. package/dist/__tests__/plainHtml.test.d.ts +0 -5
  115. package/dist/__tests__/plainHtml.test.d.ts.map +0 -1
  116. package/dist/__tests__/plainHtml.test.js +0 -327
  117. package/dist/__tests__/plainHtml.test.js.map +0 -1
  118. package/dist/__tests__/plainHtmlBundle.test.d.ts +0 -11
  119. package/dist/__tests__/plainHtmlBundle.test.d.ts.map +0 -1
  120. package/dist/__tests__/plainHtmlBundle.test.js +0 -210
  121. package/dist/__tests__/plainHtmlBundle.test.js.map +0 -1
  122. package/dist/__tests__/roundTrip.test.d.ts +0 -7
  123. package/dist/__tests__/roundTrip.test.d.ts.map +0 -1
  124. package/dist/__tests__/roundTrip.test.js +0 -173
  125. package/dist/__tests__/roundTrip.test.js.map +0 -1
  126. package/dist/chunk-33YRFXZZ.js.map +0 -1
  127. package/dist/chunk-67KIJHV2.js +0 -21
  128. package/dist/chunk-67KIJHV2.js.map +0 -1
  129. package/dist/chunk-7DEUGIOO.js.map +0 -1
  130. package/dist/chunk-ERZ627GR.js.map +0 -1
  131. package/dist/chunk-S3Y7H2BK.js.map +0 -1
  132. package/dist/chunk-UDS45KUJ.js.map +0 -1
  133. package/dist/chunk-VN2KEOYB.js.map +0 -1
  134. package/dist/chunk-YN5HFCEW.js +0 -120
  135. package/dist/chunk-YN5HFCEW.js.map +0 -1
  136. package/dist/container/index.d.ts.map +0 -1
  137. package/dist/docx/export.d.ts +0 -69
  138. package/dist/docx/export.d.ts.map +0 -1
  139. package/dist/docx/export.js +0 -985
  140. package/dist/docx/export.js.map +0 -1
  141. package/dist/docx/import.d.ts +0 -65
  142. package/dist/docx/import.d.ts.map +0 -1
  143. package/dist/docx/import.js +0 -779
  144. package/dist/docx/import.js.map +0 -1
  145. package/dist/docx/index.d.ts.map +0 -1
  146. package/dist/docx/styles.d.ts +0 -68
  147. package/dist/docx/styles.d.ts.map +0 -1
  148. package/dist/docx/styles.js +0 -125
  149. package/dist/docx/styles.js.map +0 -1
  150. package/dist/epub/export.d.ts +0 -72
  151. package/dist/epub/export.d.ts.map +0 -1
  152. package/dist/epub/export.js +0 -698
  153. package/dist/epub/export.js.map +0 -1
  154. package/dist/epub/index.d.ts.map +0 -1
  155. package/dist/html/docsHtmlBundle.d.ts +0 -53
  156. package/dist/html/docsHtmlBundle.d.ts.map +0 -1
  157. package/dist/html/docsHtmlBundle.js +0 -299
  158. package/dist/html/docsHtmlBundle.js.map +0 -1
  159. package/dist/html/htmlTemplate.d.ts +0 -70
  160. package/dist/html/htmlTemplate.d.ts.map +0 -1
  161. package/dist/html/htmlTemplate.js +0 -282
  162. package/dist/html/htmlTemplate.js.map +0 -1
  163. package/dist/html/imageUtils.d.ts +0 -29
  164. package/dist/html/imageUtils.d.ts.map +0 -1
  165. package/dist/html/imageUtils.js +0 -63
  166. package/dist/html/imageUtils.js.map +0 -1
  167. package/dist/html/index.d.ts.map +0 -1
  168. package/dist/html/plainHtml.d.ts +0 -79
  169. package/dist/html/plainHtml.d.ts.map +0 -1
  170. package/dist/html/plainHtml.js +0 -614
  171. package/dist/html/plainHtml.js.map +0 -1
  172. package/dist/html/plainHtmlBundle.d.ts +0 -93
  173. package/dist/html/plainHtmlBundle.d.ts.map +0 -1
  174. package/dist/html/plainHtmlBundle.js +0 -357
  175. package/dist/html/plainHtmlBundle.js.map +0 -1
  176. package/dist/index.d.ts.map +0 -1
  177. package/dist/ooxml/index.d.ts.map +0 -1
  178. package/dist/ooxml/namespaces.d.ts +0 -77
  179. package/dist/ooxml/namespaces.d.ts.map +0 -1
  180. package/dist/ooxml/namespaces.js +0 -104
  181. package/dist/ooxml/namespaces.js.map +0 -1
  182. package/dist/ooxml/reader.d.ts +0 -52
  183. package/dist/ooxml/reader.d.ts.map +0 -1
  184. package/dist/ooxml/reader.js +0 -190
  185. package/dist/ooxml/reader.js.map +0 -1
  186. package/dist/ooxml/types.d.ts +0 -82
  187. package/dist/ooxml/types.d.ts.map +0 -1
  188. package/dist/ooxml/types.js +0 -9
  189. package/dist/ooxml/types.js.map +0 -1
  190. package/dist/ooxml/writer.d.ts +0 -71
  191. package/dist/ooxml/writer.d.ts.map +0 -1
  192. package/dist/ooxml/writer.js +0 -200
  193. package/dist/ooxml/writer.js.map +0 -1
  194. package/dist/ooxml/xmlUtils.d.ts +0 -76
  195. package/dist/ooxml/xmlUtils.d.ts.map +0 -1
  196. package/dist/ooxml/xmlUtils.js +0 -108
  197. package/dist/ooxml/xmlUtils.js.map +0 -1
  198. package/dist/pdf/export.d.ts +0 -56
  199. package/dist/pdf/export.d.ts.map +0 -1
  200. package/dist/pdf/export.js +0 -768
  201. package/dist/pdf/export.js.map +0 -1
  202. package/dist/pdf/import.d.ts +0 -94
  203. package/dist/pdf/import.d.ts.map +0 -1
  204. package/dist/pdf/import.js +0 -796
  205. package/dist/pdf/import.js.map +0 -1
  206. package/dist/pdf/index.d.ts.map +0 -1
  207. package/dist/pdf/styles.d.ts +0 -142
  208. package/dist/pdf/styles.d.ts.map +0 -1
  209. package/dist/pdf/styles.js +0 -145
  210. package/dist/pdf/styles.js.map +0 -1
  211. package/dist/pptx/export.d.ts +0 -75
  212. package/dist/pptx/export.d.ts.map +0 -1
  213. package/dist/pptx/export.js +0 -724
  214. package/dist/pptx/export.js.map +0 -1
  215. package/dist/pptx/index.d.ts.map +0 -1
  216. package/dist/pptx/styles.d.ts +0 -54
  217. package/dist/pptx/styles.d.ts.map +0 -1
  218. package/dist/pptx/styles.js +0 -73
  219. package/dist/pptx/styles.js.map +0 -1
  220. package/dist/pptx/templates.d.ts +0 -24
  221. package/dist/pptx/templates.d.ts.map +0 -1
  222. package/dist/pptx/templates.js +0 -158
  223. package/dist/pptx/templates.js.map +0 -1
  224. package/dist/xlsx/index.d.ts.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/docx/export.ts","../src/docx/styles.ts","../src/docx/import.ts"],"sourcesContent":["/**\n * DOCX Export\n *\n * Converts a squisq MarkdownDocument (or Doc) into a .docx file\n * by generating WordprocessingML XML and assembling the OOXML package.\n *\n * No third-party docx library — all XML is generated directly using\n * the shared ooxml/ infrastructure of this package.\n *\n * @example\n * ```ts\n * import { parseMarkdown } from '@bendyline/squisq/markdown';\n * import { markdownDocToDocx } from '@bendyline/squisq-formats/docx';\n *\n * const md = parseMarkdown('# Hello\\n\\nWorld **bold** text');\n * const blob = await markdownDocToDocx(md);\n * ```\n */\n\nimport type { Doc, Theme } from '@bendyline/squisq/schemas';\nimport { resolveTheme, resolveFontFamily } from '@bendyline/squisq/schemas';\nimport { docToMarkdown } from '@bendyline/squisq/doc';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownInlineNode,\n MarkdownHeading,\n MarkdownParagraph,\n MarkdownBlockquote,\n MarkdownList,\n MarkdownListItem,\n MarkdownCodeBlock,\n MarkdownTable,\n MarkdownTableRow,\n MarkdownTableCell,\n MarkdownHtmlBlock,\n MarkdownMathBlock,\n MarkdownFootnoteDefinition,\n MarkdownLink,\n MarkdownImage,\n MarkdownFootnoteReference,\n} from '@bendyline/squisq/markdown';\nimport { readFrontmatterThemeId } from '@bendyline/squisq/markdown';\n\nimport { createPackage } from '../ooxml/writer.js';\nimport { xmlDeclaration, escapeXml } from '../ooxml/xmlUtils.js';\nimport {\n NS_WML,\n NS_R,\n NS_MC,\n REL_OFFICE_DOCUMENT,\n REL_STYLES,\n REL_NUMBERING,\n REL_SETTINGS,\n REL_FONT_TABLE,\n REL_HYPERLINK,\n REL_IMAGE,\n REL_FOOTNOTES,\n CONTENT_TYPE_DOCX_DOCUMENT,\n CONTENT_TYPE_DOCX_STYLES,\n CONTENT_TYPE_DOCX_NUMBERING,\n CONTENT_TYPE_DOCX_SETTINGS,\n CONTENT_TYPE_DOCX_FONT_TABLE,\n CONTENT_TYPE_DOCX_FOOTNOTES,\n} from '../ooxml/namespaces.js';\nimport {\n DEPTH_TO_STYLE_ID,\n HEADING_FONT_SIZES,\n DEFAULT_FONT,\n DEFAULT_HEADING_FONT,\n DEFAULT_FONT_SIZE_HALF_POINTS,\n DEFAULT_CODE_FONT,\n DEFAULT_CODE_FONT_SIZE,\n HYPERLINK_COLOR,\n pointsToTwips,\n} from './styles.js';\n\n// ============================================\n// Public API\n// ============================================\n\n/**\n * Options for DOCX export.\n */\nexport interface DocxExportOptions {\n /** Document title (appears in core properties) */\n title?: string;\n /** Document author */\n author?: string;\n /** Document description */\n description?: string;\n /** Default body font family. Default: \"Calibri\" */\n defaultFont?: string;\n /** Default body font size in points. Default: 11 */\n defaultFontSize?: number;\n /**\n * Squisq theme ID to apply (e.g., 'documentary', 'cinematic').\n * When set, overrides fonts with the theme's typography and applies\n * the theme's primary color to headings.\n */\n themeId?: string;\n /**\n * Pre-resolved image data keyed by image URL/path as it appears in the\n * markdown source. When provided, images are embedded in the .docx file\n * as binary parts instead of emitting placeholder text.\n */\n images?: Map<string, { data: ArrayBuffer | Uint8Array; contentType: string }>;\n}\n\n/**\n * Convert a MarkdownDocument to a .docx Blob.\n *\n * @param doc - The parsed markdown document\n * @param options - Export options\n * @returns An ArrayBuffer containing the .docx file\n */\nexport async function markdownDocToDocx(\n doc: MarkdownDocument,\n options: DocxExportOptions = {},\n): Promise<ArrayBuffer> {\n // Mirror the PPTX export: fall back to the doc's frontmatter themeId\n // when the caller didn't pass one explicitly. Lets the editor's\n // `squisq-theme: …` frontmatter flow straight through without each\n // host wiring its own resolution.\n const resolvedOptions: DocxExportOptions =\n options.themeId !== undefined\n ? options\n : { ...options, themeId: readFrontmatterThemeId(doc.frontmatter) };\n const ctx = new ExportContext(resolvedOptions);\n const bodyXml = convertBlocks(doc.children, ctx);\n return buildDocxPackage(bodyXml, ctx, resolvedOptions);\n}\n\n/**\n * Convert a squisq Doc to a .docx Blob.\n *\n * Convenience wrapper that converts Doc → MarkdownDocument → DOCX.\n *\n * @param doc - The squisq Doc\n * @param options - Export options\n * @returns An ArrayBuffer containing the .docx file\n */\nexport async function docToDocx(doc: Doc, options: DocxExportOptions = {}): Promise<ArrayBuffer> {\n const markdownDoc = docToMarkdown(doc);\n return markdownDocToDocx(markdownDoc, options);\n}\n\n// ============================================\n// Export Context\n// ============================================\n\n/**\n * Tracks state during export: relationship IDs, numbering definitions,\n * footnote bodies, and embedded images.\n */\nclass ExportContext {\n private nextRelId = 1;\n private nextNumId = 1;\n private nextFootnoteId = 1; // 0 is separator, start user footnotes at 1\n\n /** Relationships for word/_rels/document.xml.rels */\n readonly relationships: Array<{\n id: string;\n type: string;\n target: string;\n targetMode?: 'External';\n }> = [];\n\n /** Numbering definitions (abstract + num) */\n readonly numberingDefs: NumberingDef[] = [];\n\n /** Footnote XML bodies (keyed by footnote id) */\n readonly footnotes = new Map<number, string>();\n\n /** Footnote identifier → numeric id mapping */\n readonly footnoteIdMap = new Map<string, number>();\n\n /** Embedded images: rId → { path, data, contentType } */\n readonly images: Array<{\n relId: string;\n path: string;\n data: ArrayBuffer | Uint8Array;\n contentType: string;\n }> = [];\n\n /** Whether we have any lists (determines if numbering.xml is needed) */\n hasLists = false;\n\n /** Whether we have any footnotes */\n hasFootnotes = false;\n\n readonly font: string;\n readonly headingFont: string;\n readonly fontSize: number;\n /** Heading text color (hex without #), or undefined for default */\n readonly headingColor: string | undefined;\n /** Body text color (hex without #), or undefined for default */\n readonly bodyColor: string | undefined;\n /** Muted text color (hex without #), used by Quote style. Undefined for default. */\n readonly mutedColor: string | undefined;\n /** Page background color (hex without #), or undefined for default white. */\n readonly backgroundColor: string | undefined;\n\n /** Pre-resolved image data keyed by markdown image URL */\n readonly resolvedImages: Map<string, { data: ArrayBuffer | Uint8Array; contentType: string }>;\n\n private nextDocPrId = 1;\n\n constructor(options: DocxExportOptions) {\n let themeFont: string | undefined;\n let themeTitleFont: string | undefined;\n let themeHeadingColor: string | undefined;\n let themeBodyColor: string | undefined;\n let themeMutedColor: string | undefined;\n let themeBackgroundColor: string | undefined;\n\n if (options.themeId) {\n const theme: Theme = resolveTheme(options.themeId);\n // Theme fonts arrive as CSS stacks (e.g. `\"Oswald\", Impact,\n // \"Arial Black\", sans-serif`). Word's `w:ascii` attribute is a\n // single font name — passing the whole stack is treated as a\n // bogus literal name and Word falls through to Calibri. Take the\n // first concrete name from the stack so Word can resolve it (or\n // gracefully fall back to its own default if the font isn't\n // installed on the reader's machine).\n themeFont = firstFontFromStack(resolveFontFamily(theme.typography?.bodyFont, ''));\n themeTitleFont = firstFontFromStack(resolveFontFamily(theme.typography?.titleFont, ''));\n const stripHash = (c: string) => (c.startsWith('#') ? c.slice(1) : c);\n if (theme.colors?.primary) themeHeadingColor = stripHash(theme.colors.primary);\n if (theme.colors?.text) themeBodyColor = stripHash(theme.colors.text);\n if (theme.colors?.textMuted) themeMutedColor = stripHash(theme.colors.textMuted);\n if (theme.colors?.background) themeBackgroundColor = stripHash(theme.colors.background);\n }\n\n this.font = options.defaultFont ?? themeFont ?? DEFAULT_FONT;\n this.headingFont = themeTitleFont ?? this.font;\n this.fontSize = options.defaultFontSize\n ? options.defaultFontSize * 2\n : DEFAULT_FONT_SIZE_HALF_POINTS;\n this.headingColor = themeHeadingColor;\n this.bodyColor = themeBodyColor;\n this.mutedColor = themeMutedColor;\n this.backgroundColor = themeBackgroundColor;\n this.resolvedImages = options.images ?? new Map();\n }\n\n /** Allocate a new relationship ID */\n allocRelId(): string {\n return `rId${this.nextRelId++}`;\n }\n\n /** Add a hyperlink relationship and return the rId */\n addHyperlink(url: string): string {\n const id = this.allocRelId();\n this.relationships.push({\n id,\n type: REL_HYPERLINK,\n target: url,\n targetMode: 'External',\n });\n return id;\n }\n\n /** Add an embedded image and return the rId and docPrId */\n addImage(\n data: ArrayBuffer | Uint8Array,\n contentType: string,\n filename: string,\n ): { relId: string; docPrId: number } {\n const relId = this.allocRelId();\n const docPrId = this.nextDocPrId++;\n const path = `word/media/${filename}`;\n\n this.images.push({ relId, path, data, contentType });\n this.relationships.push({\n id: relId,\n type: REL_IMAGE,\n target: `media/${filename}`,\n });\n\n return { relId, docPrId };\n }\n\n /** Allocate a numbering definition for a list */\n allocNumbering(ordered: boolean): number {\n const numId = this.nextNumId++;\n this.numberingDefs.push({ numId, ordered });\n this.hasLists = true;\n return numId;\n }\n\n /** Register or look up a footnote by its string identifier */\n getFootnoteId(identifier: string): number {\n let id = this.footnoteIdMap.get(identifier);\n if (id === undefined) {\n id = this.nextFootnoteId++;\n this.footnoteIdMap.set(identifier, id);\n this.hasFootnotes = true;\n }\n return id;\n }\n}\n\ninterface NumberingDef {\n numId: number;\n ordered: boolean;\n}\n\n/**\n * Pull the first concrete font name out of a CSS-style stack.\n *\n * `resolveFontFamily` returns CSS values like `\"Oswald\", Impact,\n * \"Arial Black\", sans-serif`. Word's `w:ascii` / `w:hAnsi` attributes\n * expect a single font name — feeding the whole stack causes Word to\n * fall back to its default font instead of any of the named faces.\n * We pick the first non-generic name (skipping `sans-serif`, `serif`,\n * `monospace`, etc.) and strip the surrounding quotes that CSS lets\n * you wrap multi-word family names in.\n */\nfunction firstFontFromStack(stack: string): string {\n if (!stack) return '';\n const generics = new Set([\n 'sans-serif',\n 'serif',\n 'monospace',\n 'system-ui',\n 'cursive',\n 'fantasy',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'inherit',\n 'initial',\n ]);\n for (const raw of stack.split(',')) {\n const name = raw.trim().replace(/^[\"']|[\"']$/g, '');\n if (!name) continue;\n if (generics.has(name.toLowerCase())) continue;\n return name;\n }\n return '';\n}\n\n// ============================================\n// Block Conversion\n// ============================================\n\nfunction convertBlocks(nodes: MarkdownBlockNode[], ctx: ExportContext): string {\n const parts: string[] = [];\n for (const node of nodes) {\n parts.push(convertBlock(node, ctx, 0));\n }\n return parts.join('');\n}\n\nfunction convertBlock(node: MarkdownBlockNode, ctx: ExportContext, listDepth: number): string {\n switch (node.type) {\n case 'heading':\n return convertHeading(node, ctx);\n case 'paragraph':\n return convertParagraph(node, ctx);\n case 'blockquote':\n return convertBlockquote(node, ctx);\n case 'list':\n return convertList(node, ctx, listDepth);\n case 'code':\n return convertCodeBlock(node);\n case 'table':\n return convertTable(node, ctx);\n case 'thematicBreak':\n return convertThematicBreak();\n case 'htmlBlock':\n return convertHtmlBlock(node);\n case 'math':\n return convertMathBlock(node);\n case 'footnoteDefinition':\n return convertFootnoteDefinition(node, ctx);\n default:\n // Definition lists, directives, link definitions — skip or emit as plain text\n return '';\n }\n}\n\nfunction convertHeading(node: MarkdownHeading, ctx: ExportContext): string {\n const styleId = DEPTH_TO_STYLE_ID[node.depth] ?? 'Heading1';\n const runs = convertInlines(node.children, ctx);\n return `<w:p>` + `<w:pPr><w:pStyle w:val=\"${styleId}\"/></w:pPr>` + runs + `</w:p>`;\n}\n\nfunction convertParagraph(node: MarkdownParagraph, ctx: ExportContext): string {\n // Force body color on every run rather than relying on `Normal` /\n // `rPrDefault` style inheritance — see InlineFormat.color comment.\n // Headings render via `convertHeading` and skip this path so the\n // heading style's own color wins.\n const runs = convertInlines(node.children, ctx, bodyFormat(ctx));\n return `<w:p>${runs}</w:p>`;\n}\n\n/** Default inline format for body-text contexts (paragraphs, list items,\n * blockquote bodies, table cells). Carries the theme body color so runs\n * render in the right color regardless of style-resolution quirks. */\nfunction bodyFormat(ctx: ExportContext): InlineFormat {\n return ctx.bodyColor ? { color: ctx.bodyColor } : {};\n}\n\nfunction convertBlockquote(node: MarkdownBlockquote, ctx: ExportContext): string {\n // Render each child block as a paragraph with Quote style\n const parts: string[] = [];\n for (const child of node.children) {\n if (child.type === 'paragraph') {\n // Use the theme's muted color when set (Quote style already\n // declares it but explicit run-level color survives Word's\n // style overrides — see InlineFormat.color comment).\n const quoteFormat: InlineFormat = ctx.mutedColor\n ? { color: ctx.mutedColor }\n : bodyFormat(ctx);\n const runs = convertInlines(child.children, ctx, quoteFormat);\n parts.push(\n `<w:p>` +\n `<w:pPr><w:pStyle w:val=\"Quote\"/>` +\n `<w:ind w:left=\"${pointsToTwips(36)}\"/>` +\n `<w:pBdr><w:left w:val=\"single\" w:sz=\"12\" w:space=\"4\" w:color=\"CCCCCC\"/></w:pBdr>` +\n `</w:pPr>` +\n runs +\n `</w:p>`,\n );\n } else {\n // Nested non-paragraph (e.g., nested blockquote, list) — recurse\n parts.push(convertBlock(child, ctx, 0));\n }\n }\n return parts.join('');\n}\n\nfunction convertList(node: MarkdownList, ctx: ExportContext, depth: number): string {\n const numId = ctx.allocNumbering(node.ordered ?? false);\n const parts: string[] = [];\n for (const item of node.children) {\n parts.push(convertListItem(item, ctx, numId, depth));\n }\n return parts.join('');\n}\n\nfunction convertListItem(\n item: MarkdownListItem,\n ctx: ExportContext,\n numId: number,\n depth: number,\n): string {\n const parts: string[] = [];\n for (const child of item.children) {\n if (child.type === 'paragraph') {\n const runs = convertInlines(child.children, ctx, bodyFormat(ctx));\n parts.push(\n `<w:p>` +\n `<w:pPr>` +\n `<w:pStyle w:val=\"ListParagraph\"/>` +\n `<w:numPr><w:ilvl w:val=\"${depth}\"/><w:numId w:val=\"${numId}\"/></w:numPr>` +\n `</w:pPr>` +\n runs +\n `</w:p>`,\n );\n } else if (child.type === 'list') {\n // Nested list — increase depth\n parts.push(convertList(child, ctx, depth + 1));\n } else {\n parts.push(convertBlock(child, ctx, depth));\n }\n }\n return parts.join('');\n}\n\nfunction convertCodeBlock(node: MarkdownCodeBlock): string {\n // Emit each line as a separate paragraph with code styling\n const lines = node.value.split('\\n');\n const parts: string[] = [];\n for (const line of lines) {\n parts.push(\n `<w:p>` +\n `<w:pPr>` +\n `<w:pStyle w:val=\"Code\"/>` +\n `<w:pBdr>` +\n `<w:top w:val=\"single\" w:sz=\"4\" w:space=\"1\" w:color=\"CCCCCC\"/>` +\n `<w:left w:val=\"single\" w:sz=\"4\" w:space=\"4\" w:color=\"CCCCCC\"/>` +\n `<w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"1\" w:color=\"CCCCCC\"/>` +\n `<w:right w:val=\"single\" w:sz=\"4\" w:space=\"4\" w:color=\"CCCCCC\"/>` +\n `</w:pBdr>` +\n `<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"F5F5F5\"/>` +\n `</w:pPr>` +\n `<w:r>` +\n `<w:rPr><w:rFonts w:ascii=\"${DEFAULT_CODE_FONT}\" w:hAnsi=\"${DEFAULT_CODE_FONT}\"/>` +\n `<w:sz w:val=\"${DEFAULT_CODE_FONT_SIZE}\"/></w:rPr>` +\n `<w:t xml:space=\"preserve\">${escapeXml(line)}</w:t>` +\n `</w:r>` +\n `</w:p>`,\n );\n }\n return parts.join('');\n}\n\nfunction convertTable(node: MarkdownTable, ctx: ExportContext): string {\n const rows: string[] = [];\n for (let ri = 0; ri < node.children.length; ri++) {\n const row = node.children[ri];\n rows.push(convertTableRow(row, ctx, ri === 0, node.align));\n }\n\n return (\n `<w:tbl>` +\n `<w:tblPr>` +\n `<w:tblStyle w:val=\"TableGrid\"/>` +\n `<w:tblW w:w=\"0\" w:type=\"auto\"/>` +\n `<w:tblBorders>` +\n `<w:top w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:left w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:right w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideH w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideV w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `</w:tblBorders>` +\n `</w:tblPr>` +\n `<w:tblGrid/>` +\n rows.join('') +\n `</w:tbl>`\n );\n}\n\nfunction convertTableRow(\n row: MarkdownTableRow,\n ctx: ExportContext,\n isHeader: boolean,\n align?: (('left' | 'right' | 'center') | null)[],\n): string {\n const cells: string[] = [];\n for (let ci = 0; ci < row.children.length; ci++) {\n const cell = row.children[ci];\n const cellAlign = align?.[ci] ?? null;\n cells.push(convertTableCell(cell, ctx, isHeader, cellAlign));\n }\n const trPr = isHeader ? '<w:trPr><w:tblHeader/></w:trPr>' : '';\n return `<w:tr>${trPr}${cells.join('')}</w:tr>`;\n}\n\nfunction convertTableCell(\n cell: MarkdownTableCell,\n ctx: ExportContext,\n isHeader: boolean,\n align: 'left' | 'right' | 'center' | null,\n): string {\n const runs = convertInlines(cell.children, ctx, bodyFormat(ctx));\n const rPr = isHeader ? '<w:rPr><w:b/></w:rPr>' : '';\n const jcMap = { left: 'left', center: 'center', right: 'right' };\n const jc = align ? `<w:jc w:val=\"${jcMap[align]}\"/>` : '';\n const pPr = rPr || jc ? `<w:pPr>${jc}</w:pPr>` : '';\n return `<w:tc><w:p>${pPr}${runs}</w:p></w:tc>`;\n}\n\nfunction convertThematicBreak(): string {\n return (\n `<w:p>` +\n `<w:pPr>` +\n `<w:pBdr><w:bottom w:val=\"single\" w:sz=\"6\" w:space=\"1\" w:color=\"auto\"/></w:pBdr>` +\n `</w:pPr>` +\n `</w:p>`\n );\n}\n\nfunction convertHtmlBlock(node: MarkdownHtmlBlock): string {\n // Best-effort: extract text content from the HTML\n const text = stripHtmlTags(node.rawHtml);\n if (!text.trim()) return '';\n return `<w:p><w:r><w:t xml:space=\"preserve\">${escapeXml(text)}</w:t></w:r></w:p>`;\n}\n\nfunction convertMathBlock(node: MarkdownMathBlock): string {\n // Emit as a styled paragraph with the raw LaTeX\n return (\n `<w:p>` +\n `<w:pPr><w:jc w:val=\"center\"/></w:pPr>` +\n `<w:r>` +\n `<w:rPr><w:rFonts w:ascii=\"Cambria Math\" w:hAnsi=\"Cambria Math\"/><w:i/></w:rPr>` +\n `<w:t xml:space=\"preserve\">${escapeXml(node.value)}</w:t>` +\n `</w:r>` +\n `</w:p>`\n );\n}\n\nfunction convertFootnoteDefinition(node: MarkdownFootnoteDefinition, ctx: ExportContext): string {\n const fnId = ctx.getFootnoteId(node.identifier);\n\n // Build the footnote body XML\n const bodyParts: string[] = [];\n for (const child of node.children) {\n if (child.type === 'paragraph') {\n const runs = convertInlines(child.children, ctx, bodyFormat(ctx));\n bodyParts.push(`<w:p>${runs}</w:p>`);\n }\n }\n\n const footnoteXml =\n `<w:footnote w:id=\"${fnId}\">` +\n (bodyParts.length > 0 ? bodyParts.join('') : `<w:p/>`) +\n `</w:footnote>`;\n\n ctx.footnotes.set(fnId, footnoteXml);\n\n // Don't emit anything in the main body for the definition\n return '';\n}\n\n// ============================================\n// Inline Conversion\n// ============================================\n\n/**\n * Formatting state passed down through nested inline elements.\n */\ninterface InlineFormat {\n bold?: boolean;\n italic?: boolean;\n strike?: boolean;\n code?: boolean;\n /**\n * Explicit run color (hex without `#`). When set, every emitted run\n * gets `<w:color>` directly in its `<w:rPr>` — bypassing Word's style\n * inheritance, which some Word configurations silently override.\n * Body paragraphs pass `ctx.bodyColor` here; headings leave it unset\n * so the heading style's own color wins.\n */\n color?: string;\n}\n\nfunction convertInlines(\n nodes: MarkdownInlineNode[],\n ctx: ExportContext,\n format: InlineFormat = {},\n): string {\n const parts: string[] = [];\n for (const node of nodes) {\n parts.push(convertInline(node, ctx, format));\n }\n return parts.join('');\n}\n\nfunction convertInline(node: MarkdownInlineNode, ctx: ExportContext, format: InlineFormat): string {\n switch (node.type) {\n case 'text':\n return makeRun(node.value, format);\n case 'strong':\n return convertInlines(node.children, ctx, { ...format, bold: true });\n case 'emphasis':\n return convertInlines(node.children, ctx, { ...format, italic: true });\n case 'delete':\n return convertInlines(node.children, ctx, { ...format, strike: true });\n case 'inlineCode':\n return makeRun(node.value, { ...format, code: true });\n case 'link':\n return convertLink(node, ctx, format);\n case 'image':\n return convertImage(node, ctx);\n case 'break':\n return `<w:r><w:br/></w:r>`;\n case 'htmlInline':\n return makeRun(stripHtmlTags(node.rawHtml), format);\n case 'inlineMath':\n return makeRun(node.value, { ...format, code: true });\n case 'footnoteReference':\n return convertFootnoteRef(node, ctx);\n default:\n // linkReference, imageReference, textDirective — skip or emit plain\n return '';\n }\n}\n\nfunction makeRun(text: string, format: InlineFormat): string {\n if (!text) return '';\n\n const rPrParts: string[] = [];\n if (format.bold) rPrParts.push('<w:b/>');\n if (format.italic) rPrParts.push('<w:i/>');\n if (format.strike) rPrParts.push('<w:strike/>');\n if (format.color) rPrParts.push(`<w:color w:val=\"${format.color}\"/>`);\n if (format.code) {\n rPrParts.push(\n `<w:rFonts w:ascii=\"${DEFAULT_CODE_FONT}\" w:hAnsi=\"${DEFAULT_CODE_FONT}\"/>`,\n `<w:sz w:val=\"${DEFAULT_CODE_FONT_SIZE}\"/>`,\n );\n }\n\n const rPr = rPrParts.length > 0 ? `<w:rPr>${rPrParts.join('')}</w:rPr>` : '';\n\n // Use xml:space=\"preserve\" to keep leading/trailing whitespace\n return `<w:r>${rPr}<w:t xml:space=\"preserve\">${escapeXml(text)}</w:t></w:r>`;\n}\n\nfunction convertLink(node: MarkdownLink, ctx: ExportContext, format: InlineFormat): string {\n const rId = ctx.addHyperlink(node.url);\n const styledRuns = convertInlinesWithHyperlinkStyle(node.children, ctx, format);\n\n return `<w:hyperlink r:id=\"${rId}\">${styledRuns}</w:hyperlink>`;\n}\n\nfunction convertInlinesWithHyperlinkStyle(\n nodes: MarkdownInlineNode[],\n ctx: ExportContext,\n format: InlineFormat,\n): string {\n const parts: string[] = [];\n for (const node of nodes) {\n if (node.type === 'text') {\n parts.push(makeHyperlinkRun(node.value, format));\n } else {\n // For nested formatting inside links, add hyperlink style\n parts.push(convertInline(node, ctx, format));\n }\n }\n return parts.join('');\n}\n\nfunction makeHyperlinkRun(text: string, format: InlineFormat): string {\n if (!text) return '';\n\n const rPrParts: string[] = [\n '<w:rStyle w:val=\"Hyperlink\"/>',\n `<w:color w:val=\"${HYPERLINK_COLOR}\"/>`,\n '<w:u w:val=\"single\"/>',\n ];\n if (format.bold) rPrParts.push('<w:b/>');\n if (format.italic) rPrParts.push('<w:i/>');\n\n return (\n `<w:r><w:rPr>${rPrParts.join('')}</w:rPr>` +\n `<w:t xml:space=\"preserve\">${escapeXml(text)}</w:t></w:r>`\n );\n}\n\nfunction convertImage(node: MarkdownImage, ctx: ExportContext): string {\n const imageEntry = ctx.resolvedImages.get(node.url);\n if (!imageEntry) {\n // No resolved data — emit placeholder text\n const alt = node.alt || node.url;\n return makeRun(`[Image: ${alt}]`, { italic: true });\n }\n\n const { data, contentType } = imageEntry;\n const ext = contentType.split('/')[1]?.replace('jpeg', 'jpg') || 'png';\n const filename = `image${ctx.images.length + 1}.${ext}`;\n const { relId, docPrId } = ctx.addImage(data, contentType, filename);\n\n // Read dimensions from binary header; fall back to 5×3 inches\n const dims = readImageDimensions(data);\n const EMU_PER_INCH = 914400;\n const MAX_WIDTH_EMU = 6 * EMU_PER_INCH; // 6 inch content width\n let cx: number;\n let cy: number;\n\n if (dims) {\n // Scale to fit within max width, assuming 96 DPI for pixel → inch\n const widthEmu = (dims.width / 96) * EMU_PER_INCH;\n const heightEmu = (dims.height / 96) * EMU_PER_INCH;\n if (widthEmu > MAX_WIDTH_EMU) {\n const scale = MAX_WIDTH_EMU / widthEmu;\n cx = MAX_WIDTH_EMU;\n cy = Math.round(heightEmu * scale);\n } else {\n cx = Math.round(widthEmu);\n cy = Math.round(heightEmu);\n }\n } else {\n cx = 5 * EMU_PER_INCH;\n cy = 3 * EMU_PER_INCH;\n }\n\n const name = escapeXml(node.alt || filename);\n const NS_A = 'http://schemas.openxmlformats.org/drawingml/2006/main';\n const NS_PIC = 'http://schemas.openxmlformats.org/drawingml/2006/picture';\n\n return (\n `<w:r><w:drawing>` +\n `<wp:inline distT=\"0\" distB=\"0\" distL=\"0\" distR=\"0\">` +\n `<wp:extent cx=\"${cx}\" cy=\"${cy}\"/>` +\n `<wp:docPr id=\"${docPrId}\" name=\"${name}\"/>` +\n `<wp:cNvGraphicFramePr>` +\n `<a:graphicFrameLocks xmlns:a=\"${NS_A}\" noChangeAspect=\"1\"/>` +\n `</wp:cNvGraphicFramePr>` +\n `<a:graphic xmlns:a=\"${NS_A}\">` +\n `<a:graphicData uri=\"${NS_PIC}\">` +\n `<pic:pic xmlns:pic=\"${NS_PIC}\">` +\n `<pic:nvPicPr>` +\n `<pic:cNvPr id=\"0\" name=\"${name}\"/>` +\n `<pic:cNvPicPr/>` +\n `</pic:nvPicPr>` +\n `<pic:blipFill>` +\n `<a:blip r:embed=\"${relId}\"/>` +\n `<a:stretch><a:fillRect/></a:stretch>` +\n `</pic:blipFill>` +\n `<pic:spPr>` +\n `<a:xfrm>` +\n `<a:off x=\"0\" y=\"0\"/>` +\n `<a:ext cx=\"${cx}\" cy=\"${cy}\"/>` +\n `</a:xfrm>` +\n `<a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom>` +\n `</pic:spPr>` +\n `</pic:pic>` +\n `</a:graphicData>` +\n `</a:graphic>` +\n `</wp:inline>` +\n `</w:drawing></w:r>`\n );\n}\n\n/** Read width/height from PNG or JPEG binary headers. */\nfunction readImageDimensions(\n data: ArrayBuffer | Uint8Array,\n): { width: number; height: number } | null {\n const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);\n if (bytes.length < 24) return null;\n\n // PNG: signature 0x89504E47, IHDR chunk at byte 16\n if (bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47) {\n const width = (bytes[16] << 24) | (bytes[17] << 16) | (bytes[18] << 8) | bytes[19];\n const height = (bytes[20] << 24) | (bytes[21] << 16) | (bytes[22] << 8) | bytes[23];\n return { width, height };\n }\n\n // JPEG: search for SOF0 (0xFFC0) or SOF2 (0xFFC2) marker\n if (bytes[0] === 0xff && bytes[1] === 0xd8) {\n let offset = 2;\n while (offset < bytes.length - 9) {\n if (bytes[offset] !== 0xff) break;\n const marker = bytes[offset + 1];\n if (marker === 0xc0 || marker === 0xc2) {\n const height = (bytes[offset + 5] << 8) | bytes[offset + 6];\n const width = (bytes[offset + 7] << 8) | bytes[offset + 8];\n return { width, height };\n }\n const segLen = (bytes[offset + 2] << 8) | bytes[offset + 3];\n offset += 2 + segLen;\n }\n }\n\n // GIF: width at bytes 6-7, height at bytes 8-9 (little-endian)\n if (bytes[0] === 0x47 && bytes[1] === 0x49 && bytes[2] === 0x46) {\n const width = bytes[6] | (bytes[7] << 8);\n const height = bytes[8] | (bytes[9] << 8);\n return { width, height };\n }\n\n return null;\n}\n\nfunction convertFootnoteRef(node: MarkdownFootnoteReference, ctx: ExportContext): string {\n const fnId = ctx.getFootnoteId(node.identifier);\n return (\n `<w:r>` +\n `<w:rPr><w:rStyle w:val=\"FootnoteReference\"/><w:vertAlign w:val=\"superscript\"/></w:rPr>` +\n `<w:footnoteReference w:id=\"${fnId}\"/>` +\n `</w:r>`\n );\n}\n\n// ============================================\n// Package Assembly\n// ============================================\n\nasync function buildDocxPackage(\n bodyXml: string,\n ctx: ExportContext,\n options: DocxExportOptions,\n): Promise<ArrayBuffer> {\n const pkg = createPackage();\n\n // --- Register fixed relationships ---\n let relCounter = 100; // Start high to avoid collisions with dynamic rels\n const stylesRelId = `rId${relCounter++}`;\n const numberingRelId = `rId${relCounter++}`;\n const settingsRelId = `rId${relCounter++}`;\n const fontTableRelId = `rId${relCounter++}`;\n const footnotesRelId = `rId${relCounter++}`;\n\n // --- word/document.xml ---\n const documentXml = buildDocumentXml(bodyXml, ctx.backgroundColor);\n pkg.addPart('word/document.xml', documentXml, CONTENT_TYPE_DOCX_DOCUMENT);\n\n // --- word/styles.xml ---\n const stylesXml = buildStylesXml(options, ctx);\n pkg.addPart('word/styles.xml', stylesXml, CONTENT_TYPE_DOCX_STYLES);\n\n // --- word/settings.xml ---\n // `displayBackgroundShape` is what makes Word actually paint the\n // `<w:background>` element from document.xml on screen + print.\n // Without it the bg color is in the file but invisible.\n const settingsXml = buildSettingsXml(ctx.backgroundColor !== undefined);\n pkg.addPart('word/settings.xml', settingsXml, CONTENT_TYPE_DOCX_SETTINGS);\n\n // --- word/fontTable.xml ---\n const fontTableXml = buildFontTableXml(options);\n pkg.addPart('word/fontTable.xml', fontTableXml, CONTENT_TYPE_DOCX_FONT_TABLE);\n\n // --- word/numbering.xml (only if lists present) ---\n if (ctx.hasLists) {\n const numberingXml = buildNumberingXml(ctx);\n pkg.addPart('word/numbering.xml', numberingXml, CONTENT_TYPE_DOCX_NUMBERING);\n }\n\n // --- word/footnotes.xml (only if footnotes present) ---\n if (ctx.hasFootnotes) {\n const footnotesXml = buildFootnotesXml(ctx);\n pkg.addPart('word/footnotes.xml', footnotesXml, CONTENT_TYPE_DOCX_FOOTNOTES);\n }\n\n // --- Root relationship: this package contains a word document ---\n pkg.addRelationship('', {\n id: 'rId1',\n type: REL_OFFICE_DOCUMENT,\n target: 'word/document.xml',\n });\n\n // --- Document relationships ---\n pkg.addRelationship('word/document.xml', {\n id: stylesRelId,\n type: REL_STYLES,\n target: 'styles.xml',\n });\n pkg.addRelationship('word/document.xml', {\n id: settingsRelId,\n type: REL_SETTINGS,\n target: 'settings.xml',\n });\n pkg.addRelationship('word/document.xml', {\n id: fontTableRelId,\n type: REL_FONT_TABLE,\n target: 'fontTable.xml',\n });\n\n if (ctx.hasLists) {\n pkg.addRelationship('word/document.xml', {\n id: numberingRelId,\n type: REL_NUMBERING,\n target: 'numbering.xml',\n });\n }\n\n if (ctx.hasFootnotes) {\n pkg.addRelationship('word/document.xml', {\n id: footnotesRelId,\n type: REL_FOOTNOTES,\n target: 'footnotes.xml',\n });\n }\n\n // --- Dynamic relationships (hyperlinks, images) ---\n for (const rel of ctx.relationships) {\n pkg.addRelationship('word/document.xml', {\n id: rel.id,\n type: rel.type,\n target: rel.target,\n ...(rel.targetMode ? { targetMode: rel.targetMode } : {}),\n });\n }\n\n // --- Embedded images ---\n for (const img of ctx.images) {\n pkg.addBinaryPart(img.path, img.data, img.contentType);\n }\n\n // --- Core properties ---\n if (options.title || options.author || options.description) {\n pkg.setCoreProperties({\n title: options.title,\n creator: options.author,\n description: options.description,\n created: new Date().toISOString(),\n modified: new Date().toISOString(),\n });\n }\n\n return pkg.toArrayBuffer();\n}\n\n// ============================================\n// XML Part Generators\n// ============================================\n\nfunction buildDocumentXml(bodyXml: string, backgroundColor?: string): string {\n // `<w:background>` must be the FIRST child of `<w:document>` per the\n // WordprocessingML schema. Word also requires `<w:displayBackgroundShape/>`\n // in settings.xml before the bg actually paints (see buildSettingsXml).\n const backgroundEl = backgroundColor ? `<w:background w:color=\"${backgroundColor}\"/>` : '';\n return (\n xmlDeclaration() +\n `<w:document` +\n ` xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\"` +\n ` xmlns:mc=\"${NS_MC}\"` +\n ` xmlns:o=\"urn:schemas-microsoft-com:office:office\"` +\n ` xmlns:r=\"${NS_R}\"` +\n ` xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\"` +\n ` xmlns:v=\"urn:schemas-microsoft-com:vml\"` +\n ` xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\"` +\n ` xmlns:w10=\"urn:schemas-microsoft-com:office:word\"` +\n ` xmlns:w=\"${NS_WML}\"` +\n ` xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\">` +\n backgroundEl +\n `<w:body>` +\n bodyXml +\n `<w:sectPr>` +\n `<w:pgSz w:w=\"12240\" w:h=\"15840\"/>` +\n `<w:pgMar w:top=\"1440\" w:right=\"1440\" w:bottom=\"1440\" w:left=\"1440\" w:header=\"720\" w:footer=\"720\" w:gutter=\"0\"/>` +\n `<w:cols w:space=\"720\"/>` +\n `</w:sectPr>` +\n `</w:body>` +\n `</w:document>`\n );\n}\n\nfunction buildStylesXml(options: DocxExportOptions, ctx: ExportContext): string {\n const font = ctx.font;\n const headingFont = ctx.headingFont;\n // Body color from the theme's `text`. We set it on BOTH the\n // `<w:rPrDefault>` (for any rogue run that doesn't inherit Normal) and\n // on the `Normal` style itself. Setting it only on rPrDefault was\n // experimentally insufficient — Word's resolved formatting in Print\n // Layout view ignored the docDefault color for direct-typed body\n // paragraphs even though headings (with explicit rPr) honored their\n // own color. Setting it on Normal puts the color one level higher in\n // the precedence chain (paragraph-style > docDefaults) so it sticks.\n const bodyColorXml = ctx.bodyColor ? `<w:color w:val=\"${ctx.bodyColor}\"/>` : '';\n const quoteColor = ctx.mutedColor ?? '404040';\n\n return (\n xmlDeclaration() +\n `<w:styles xmlns:w=\"${NS_WML}\">` +\n // Default run properties\n `<w:docDefaults>` +\n `<w:rPrDefault><w:rPr>` +\n `<w:rFonts w:ascii=\"${escapeXml(font)}\" w:hAnsi=\"${escapeXml(font)}\" w:eastAsia=\"${escapeXml(font)}\" w:cs=\"${escapeXml(font)}\"/>` +\n bodyColorXml +\n `<w:sz w:val=\"${DEFAULT_FONT_SIZE_HALF_POINTS}\"/>` +\n `<w:szCs w:val=\"${DEFAULT_FONT_SIZE_HALF_POINTS}\"/>` +\n `</w:rPr></w:rPrDefault>` +\n `<w:pPrDefault/>` +\n `</w:docDefaults>` +\n // Normal style — carries the body color explicitly so direct-typed\n // body paragraphs render in the theme's text color in every Word\n // view (not just Web Layout).\n `<w:style w:type=\"paragraph\" w:default=\"1\" w:styleId=\"Normal\">` +\n `<w:name w:val=\"Normal\"/>` +\n `<w:qFormat/>` +\n (bodyColorXml ? `<w:rPr>${bodyColorXml}</w:rPr>` : '') +\n `</w:style>` +\n // Heading styles\n buildHeadingStyles(headingFont, ctx.headingColor) +\n // Quote style — muted text color from theme.textMuted (falls back\n // to a neutral grey when no theme is supplied).\n `<w:style w:type=\"paragraph\" w:styleId=\"Quote\">` +\n `<w:name w:val=\"Quote\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:pPr><w:ind w:left=\"720\"/></w:pPr>` +\n `<w:rPr><w:i/><w:color w:val=\"${quoteColor}\"/></w:rPr>` +\n `</w:style>` +\n // Code style\n `<w:style w:type=\"paragraph\" w:styleId=\"Code\">` +\n `<w:name w:val=\"Code\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:rPr>` +\n `<w:rFonts w:ascii=\"${DEFAULT_CODE_FONT}\" w:hAnsi=\"${DEFAULT_CODE_FONT}\"/>` +\n `<w:sz w:val=\"${DEFAULT_CODE_FONT_SIZE}\"/>` +\n `</w:rPr>` +\n `</w:style>` +\n // ListParagraph style\n `<w:style w:type=\"paragraph\" w:styleId=\"ListParagraph\">` +\n `<w:name w:val=\"List Paragraph\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:pPr><w:ind w:left=\"720\"/></w:pPr>` +\n `</w:style>` +\n // Hyperlink character style\n `<w:style w:type=\"character\" w:styleId=\"Hyperlink\">` +\n `<w:name w:val=\"Hyperlink\"/>` +\n `<w:rPr><w:color w:val=\"${HYPERLINK_COLOR}\"/><w:u w:val=\"single\"/></w:rPr>` +\n `</w:style>` +\n // FootnoteReference character style\n `<w:style w:type=\"character\" w:styleId=\"FootnoteReference\">` +\n `<w:name w:val=\"footnote reference\"/>` +\n `<w:rPr><w:vertAlign w:val=\"superscript\"/></w:rPr>` +\n `</w:style>` +\n // Table Grid style\n `<w:style w:type=\"table\" w:styleId=\"TableGrid\">` +\n `<w:name w:val=\"Table Grid\"/>` +\n `<w:tblPr>` +\n `<w:tblBorders>` +\n `<w:top w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:left w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:bottom w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:right w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideH w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `<w:insideV w:val=\"single\" w:sz=\"4\" w:space=\"0\" w:color=\"auto\"/>` +\n `</w:tblBorders>` +\n `</w:tblPr>` +\n `</w:style>` +\n `</w:styles>`\n );\n}\n\nfunction buildHeadingStyles(headingFont: string, headingColor?: string): string {\n let result = '';\n for (let depth = 1; depth <= 6; depth++) {\n const styleId = DEPTH_TO_STYLE_ID[depth];\n const fontSize = HEADING_FONT_SIZES[depth] ?? 22;\n const colorXml = headingColor ? `<w:color w:val=\"${headingColor}\"/>` : '';\n result +=\n `<w:style w:type=\"paragraph\" w:styleId=\"${styleId}\">` +\n `<w:name w:val=\"heading ${depth}\"/>` +\n `<w:basedOn w:val=\"Normal\"/>` +\n `<w:next w:val=\"Normal\"/>` +\n `<w:qFormat/>` +\n `<w:pPr><w:outlineLvl w:val=\"${depth - 1}\"/><w:spacing w:before=\"240\" w:after=\"60\"/></w:pPr>` +\n `<w:rPr>` +\n `<w:rFonts w:ascii=\"${escapeXml(headingFont)}\" w:hAnsi=\"${escapeXml(headingFont)}\"/>` +\n `<w:b/>` +\n colorXml +\n `<w:sz w:val=\"${fontSize}\"/>` +\n `<w:szCs w:val=\"${fontSize}\"/>` +\n `</w:rPr>` +\n `</w:style>`;\n }\n return result;\n}\n\nfunction buildSettingsXml(displayBackground: boolean): string {\n // `<w:compat>` with `compatibilityMode=15` is what tells Word \"this\n // is a Word 2016+ .docx, render with modern features.\" Without it,\n // Word opens the file in Compatibility Mode and silently disables\n // newer behaviors — including page-background rendering in Print\n // Layout view and several default style precedence rules. The other\n // compatSetting flags match what Word 2016+ writes by default.\n const compatXml =\n `<w:compat>` +\n `<w:compatSetting w:name=\"compatibilityMode\" w:uri=\"http://schemas.microsoft.com/office/word\" w:val=\"15\"/>` +\n `<w:compatSetting w:name=\"overrideTableStyleFontSizeAndJustification\" w:uri=\"http://schemas.microsoft.com/office/word\" w:val=\"1\"/>` +\n `<w:compatSetting w:name=\"enableOpenTypeFeatures\" w:uri=\"http://schemas.microsoft.com/office/word\" w:val=\"1\"/>` +\n `<w:compatSetting w:name=\"doNotFlipMirrorIndents\" w:uri=\"http://schemas.microsoft.com/office/word\" w:val=\"1\"/>` +\n `<w:compatSetting w:name=\"differentiateMultirowTableHeaders\" w:uri=\"http://schemas.microsoft.com/office/word\" w:val=\"1\"/>` +\n `</w:compat>`;\n // Element order inside `<w:settings>` matters — ECMA-376 defines a\n // strict sequence (`displayBackgroundShape` → `defaultTabStop` →\n // `characterSpacingControl` → … → `compat`). Word silently drops\n // out-of-order children, which is why `<w:background>` looks correct\n // in the file but doesn't paint when opened.\n return (\n xmlDeclaration() +\n `<w:settings xmlns:w=\"${NS_WML}\">` +\n (displayBackground ? `<w:displayBackgroundShape/>` : '') +\n `<w:defaultTabStop w:val=\"720\"/>` +\n `<w:characterSpacingControl w:val=\"doNotCompress\"/>` +\n compatXml +\n `</w:settings>`\n );\n}\n\nfunction buildFontTableXml(options: DocxExportOptions): string {\n const font = options.defaultFont ?? DEFAULT_FONT;\n return (\n xmlDeclaration() +\n `<w:fonts xmlns:w=\"${NS_WML}\">` +\n `<w:font w:name=\"${escapeXml(font)}\">` +\n `<w:panose1 w:val=\"020F0502020204030204\"/>` +\n `<w:charset w:val=\"00\"/>` +\n `<w:family w:val=\"swiss\"/>` +\n `<w:pitch w:val=\"variable\"/>` +\n `</w:font>` +\n `<w:font w:name=\"${DEFAULT_HEADING_FONT}\">` +\n `<w:panose1 w:val=\"020F0302020204030204\"/>` +\n `<w:charset w:val=\"00\"/>` +\n `<w:family w:val=\"swiss\"/>` +\n `<w:pitch w:val=\"variable\"/>` +\n `</w:font>` +\n `<w:font w:name=\"${DEFAULT_CODE_FONT}\">` +\n `<w:charset w:val=\"00\"/>` +\n `<w:family w:val=\"modern\"/>` +\n `<w:pitch w:val=\"fixed\"/>` +\n `</w:font>` +\n `</w:fonts>`\n );\n}\n\nfunction buildNumberingXml(ctx: ExportContext): string {\n const abstract: string[] = [];\n const concrete: string[] = [];\n\n for (const def of ctx.numberingDefs) {\n const absId = def.numId;\n const levels: string[] = [];\n\n for (let lvl = 0; lvl < 9; lvl++) {\n if (def.ordered) {\n levels.push(\n `<w:lvl w:ilvl=\"${lvl}\">` +\n `<w:start w:val=\"1\"/>` +\n `<w:numFmt w:val=\"decimal\"/>` +\n `<w:lvlText w:val=\"%${lvl + 1}.\"/>` +\n `<w:lvlJc w:val=\"left\"/>` +\n `<w:pPr><w:ind w:left=\"${720 * (lvl + 1)}\" w:hanging=\"360\"/></w:pPr>` +\n `</w:lvl>`,\n );\n } else {\n const bullets = ['\\u2022', '\\u25E6', '\\u25AA']; // •, ◦, ▪\n const bullet = bullets[lvl % bullets.length];\n levels.push(\n `<w:lvl w:ilvl=\"${lvl}\">` +\n `<w:start w:val=\"1\"/>` +\n `<w:numFmt w:val=\"bullet\"/>` +\n `<w:lvlText w:val=\"${bullet}\"/>` +\n `<w:lvlJc w:val=\"left\"/>` +\n `<w:pPr><w:ind w:left=\"${720 * (lvl + 1)}\" w:hanging=\"360\"/></w:pPr>` +\n // Bullet glyph renders in the document's body font, not\n // Word's legacy `Symbol` font. `Symbol` only maps codes\n // 0x20-0xFF to Greek/math glyphs, so the Unicode bullets\n // we use (U+2022, U+25E6, U+25AA) come out as \"tofu\"\n // empty boxes when forced into Symbol. Every modern OS\n // font has these codepoints, so omitting the font\n // override gets a real bullet.\n `</w:lvl>`,\n );\n }\n }\n\n abstract.push(\n `<w:abstractNum w:abstractNumId=\"${absId}\">` + levels.join('') + `</w:abstractNum>`,\n );\n concrete.push(\n `<w:num w:numId=\"${def.numId}\">` + `<w:abstractNumId w:val=\"${absId}\"/>` + `</w:num>`,\n );\n }\n\n return (\n xmlDeclaration() +\n `<w:numbering xmlns:w=\"${NS_WML}\">` +\n abstract.join('') +\n concrete.join('') +\n `</w:numbering>`\n );\n}\n\nfunction buildFootnotesXml(ctx: ExportContext): string {\n const footnotes: string[] = [];\n\n // Separator and continuation separator (required by Word)\n footnotes.push(\n `<w:footnote w:type=\"separator\" w:id=\"-1\">` +\n `<w:p><w:r><w:separator/></w:r></w:p>` +\n `</w:footnote>`,\n );\n footnotes.push(\n `<w:footnote w:type=\"continuationSeparator\" w:id=\"0\">` +\n `<w:p><w:r><w:continuationSeparator/></w:r></w:p>` +\n `</w:footnote>`,\n );\n\n // User footnotes\n for (const [_id, xml] of ctx.footnotes) {\n footnotes.push(xml);\n }\n\n return (\n xmlDeclaration() +\n `<w:footnotes xmlns:w=\"${NS_WML}\" xmlns:r=\"${NS_R}\">` +\n footnotes.join('') +\n `</w:footnotes>`\n );\n}\n\n// ============================================\n// Helpers\n// ============================================\n\n/**\n * Strip HTML tags from a string, keeping only text content.\n */\nfunction stripHtmlTags(html: string): string {\n return html.replace(/<[^>]*>/g, '');\n}\n","/**\n * DOCX Constants & Style Definitions\n *\n * Shared constants for DOCX import and export: built-in style IDs,\n * numbering format mappings, content type strings, and default\n * formatting values.\n */\n\n// ============================================\n// Built-in Style IDs\n// ============================================\n\n/**\n * Word built-in paragraph style IDs → heading depth.\n * These are the default style IDs in Word's Normal.dotm template.\n * Import uses these to detect heading levels from pStyle values.\n */\nexport const HEADING_STYLE_MAP: Record<string, number> = {\n Heading1: 1,\n Heading2: 2,\n Heading3: 3,\n Heading4: 4,\n Heading5: 5,\n Heading6: 6,\n heading1: 1,\n heading2: 2,\n heading3: 3,\n heading4: 4,\n heading5: 5,\n heading6: 6,\n // Some localized/legacy variants\n Title: 1,\n Subtitle: 2,\n};\n\n/**\n * Heading depth → Word style ID mapping (for export).\n */\nexport const DEPTH_TO_STYLE_ID: Record<number, string> = {\n 1: 'Heading1',\n 2: 'Heading2',\n 3: 'Heading3',\n 4: 'Heading4',\n 5: 'Heading5',\n 6: 'Heading6',\n};\n\n/**\n * Paragraph style IDs that map to blockquotes on import.\n */\nexport const QUOTE_STYLE_IDS = new Set(['Quote', 'IntenseQuote', 'quote', 'BlockQuote']);\n\n/**\n * Paragraph style ID for code blocks.\n */\nexport const CODE_STYLE_IDS = new Set(['Code', 'CodeBlock', 'HTMLCode', 'PlainText']);\n\n/**\n * Character style IDs that indicate inline code.\n */\nexport const INLINE_CODE_STYLE_IDS = new Set(['CodeChar', 'HTMLCodeChar', 'VerbatimChar']);\n\n// ============================================\n// Numbering Formats\n// ============================================\n\n/**\n * Word numbering format values that indicate an unordered (bullet) list.\n */\nexport const BULLET_NUM_FORMATS = new Set(['bullet', 'none']);\n\n/**\n * Word numbering format values that indicate an ordered (numbered) list.\n */\nexport const ORDERED_NUM_FORMATS = new Set([\n 'decimal',\n 'upperRoman',\n 'lowerRoman',\n 'upperLetter',\n 'lowerLetter',\n 'ordinal',\n 'cardinalText',\n 'ordinalText',\n]);\n\n// ============================================\n// Default Formatting\n// ============================================\n\n/** Default font family for document body text */\nexport const DEFAULT_FONT = 'Calibri';\n\n/** Default font family for headings */\nexport const DEFAULT_HEADING_FONT = 'Calibri Light';\n\n/** Default font size in half-points (22 = 11pt) */\nexport const DEFAULT_FONT_SIZE_HALF_POINTS = 22;\n\n/** Default code font */\nexport const DEFAULT_CODE_FONT = 'Consolas';\n\n/** Default code font size in half-points (20 = 10pt) */\nexport const DEFAULT_CODE_FONT_SIZE = 20;\n\n/**\n * Heading font sizes in half-points (Word default sizes).\n */\nexport const HEADING_FONT_SIZES: Record<number, number> = {\n 1: 32, // 16pt\n 2: 26, // 13pt\n 3: 24, // 12pt\n 4: 22, // 11pt\n 5: 22, // 11pt\n 6: 22, // 11pt\n};\n\n/** Hyperlink color (standard Word blue) */\nexport const HYPERLINK_COLOR = '0563C1';\n\n// ============================================\n// EMU (English Metric Units) Helpers\n// ============================================\n\n/**\n * Convert inches to EMUs (English Metric Units).\n * 1 inch = 914400 EMUs.\n */\nexport function inchesToEmu(inches: number): number {\n return Math.round(inches * 914400);\n}\n\n/**\n * Convert points to half-points (Word's internal unit for font sizes).\n */\nexport function pointsToHalfPoints(points: number): number {\n return Math.round(points * 2);\n}\n\n/**\n * Convert points to twentieths of a point (twips), used for spacing/margins.\n * 1 point = 20 twips.\n */\nexport function pointsToTwips(points: number): number {\n return Math.round(points * 20);\n}\n","/**\n * DOCX Import\n *\n * Parses a .docx file (Office Open XML WordprocessingML) and converts\n * its content into a squisq MarkdownDocument (or Doc).\n *\n * Uses JSZip + DOMParser to read the archive and parse the XML — no\n * third-party docx library. Handles headings, paragraphs, inline\n * formatting (bold, italic, strikethrough), hyperlinks, lists, tables,\n * blockquotes, code blocks, images, and footnotes.\n *\n * @example\n * ```ts\n * import { docxToMarkdownDoc } from '@bendyline/squisq-formats/docx';\n *\n * const response = await fetch('document.docx');\n * const data = await response.arrayBuffer();\n * const doc = await docxToMarkdownDoc(data);\n * ```\n */\n\nimport type { Doc } from '@bendyline/squisq/schemas';\nimport { markdownToDoc } from '@bendyline/squisq/doc';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownInlineNode,\n MarkdownHeading,\n MarkdownParagraph,\n MarkdownBlockquote,\n MarkdownList,\n MarkdownListItem,\n MarkdownCodeBlock,\n MarkdownTable,\n MarkdownTableRow,\n MarkdownTableCell,\n MarkdownText,\n MarkdownEmphasis,\n MarkdownStrong,\n MarkdownStrikethrough,\n MarkdownInlineCode,\n MarkdownLink,\n MarkdownImage,\n MarkdownBreak,\n MarkdownFootnoteReference,\n MarkdownFootnoteDefinition,\n} from '@bendyline/squisq/markdown';\n\nimport { openPackage, getPartXml, getPartBinary, getPartRelationships } from '../ooxml/reader.js';\nimport type { OoxmlPackage, Relationship } from '../ooxml/types.js';\nimport { NS_WML, NS_R } from '../ooxml/namespaces.js';\nimport { MemoryContentContainer } from '@bendyline/squisq/storage';\nimport type { ContentContainer } from '@bendyline/squisq/storage';\nimport {\n HEADING_STYLE_MAP,\n QUOTE_STYLE_IDS,\n CODE_STYLE_IDS,\n INLINE_CODE_STYLE_IDS,\n BULLET_NUM_FORMATS,\n} from './styles.js';\n\n// ============================================\n// Public API\n// ============================================\n\n/**\n * Options for DOCX import.\n */\nexport interface DocxImportOptions {\n /**\n * Whether to extract embedded images as base64 data URIs.\n * When false, images are represented as `[Image]` placeholders.\n * Default: false\n */\n extractImages?: boolean;\n}\n\n/**\n * Convert a .docx file to a MarkdownDocument.\n *\n * @param data - The raw .docx file as ArrayBuffer or Blob\n * @param options - Import options\n * @returns A MarkdownDocument representing the document content\n */\nexport async function docxToMarkdownDoc(\n data: ArrayBuffer | Blob,\n options: DocxImportOptions = {},\n): Promise<MarkdownDocument> {\n const pkg = await openPackage(data);\n const ctx = await buildImportContext(pkg, options);\n\n const documentXml = await getPartXml(pkg, 'word/document.xml');\n if (!documentXml) {\n return { type: 'document', children: [] };\n }\n\n const body = getFirstElement(documentXml, 'body');\n if (!body) {\n return { type: 'document', children: [] };\n }\n\n const blocks = await convertBody(body, ctx);\n\n return { type: 'document', children: blocks };\n}\n\n/**\n * Convert a .docx file to a squisq Doc.\n *\n * Convenience wrapper: DOCX → MarkdownDocument → Doc.\n *\n * @param data - The raw .docx file as ArrayBuffer or Blob\n * @param options - Import options\n * @returns A squisq Doc\n */\nexport async function docxToDoc(\n data: ArrayBuffer | Blob,\n options: DocxImportOptions = {},\n): Promise<Doc> {\n const markdownDoc = await docxToMarkdownDoc(data, options);\n return markdownToDoc(markdownDoc);\n}\n\n/**\n * Convert a .docx file to a ContentContainer with markdown + extracted images.\n *\n * The container will contain:\n * - The primary markdown document (index.md)\n * - Any embedded images under images/ (e.g., images/image1.png)\n *\n * @param data - The raw .docx file as ArrayBuffer or Blob\n * @param options - Import options\n * @returns A ContentContainer with the document and its media\n */\nexport async function docxToContainer(\n data: ArrayBuffer | Blob,\n options: DocxImportOptions = {},\n): Promise<ContentContainer> {\n const pkg = await openPackage(data);\n const ctx = await buildImportContext(pkg, { ...options, extractImages: true });\n\n const documentXml = await getPartXml(pkg, 'word/document.xml');\n if (!documentXml) {\n const container = new MemoryContentContainer();\n await container.writeDocument('');\n return container;\n }\n\n const body = getFirstElement(documentXml, 'body');\n if (!body) {\n const container = new MemoryContentContainer();\n await container.writeDocument('');\n return container;\n }\n\n const blocks = await convertBody(body, ctx);\n const markdownDoc: MarkdownDocument = { type: 'document', children: blocks };\n\n // Serialize to markdown\n const { stringifyMarkdown } = await import('@bendyline/squisq/markdown');\n const markdown = stringifyMarkdown(markdownDoc);\n\n // Build container with markdown + images\n const container = new MemoryContentContainer();\n await container.writeDocument(markdown);\n\n for (const [path, { data: imageData, mimeType }] of ctx.extractedImages) {\n await container.writeFile(path, new Uint8Array(imageData), mimeType);\n }\n\n return container;\n}\n\n// ============================================\n// Import Context\n// ============================================\n\ninterface ImportContext {\n /** Style ID → heading depth mapping (from styles.xml) */\n headingStyles: Map<string, number>;\n /** Style IDs that represent blockquotes */\n quoteStyles: Set<string>;\n /** Style IDs that represent code blocks */\n codeStyles: Set<string>;\n /** Character style IDs that represent inline code */\n inlineCodeStyles: Set<string>;\n /** Document relationship map: rId → Relationship */\n documentRels: Map<string, Relationship>;\n /** Numbering definitions: numId → { levels: Map<ilvl, isOrdered> } */\n numbering: Map<string, NumberingInfo>;\n /** Footnote bodies: footnoteId → Element */\n footnotes: Map<string, Element>;\n /** Reference to the OOXML package (for extracting images) */\n pkg: OoxmlPackage;\n /** Import options */\n options: DocxImportOptions;\n /** Collected image files: relative path → { data, mimeType } */\n extractedImages: Map<string, { data: ArrayBuffer; mimeType: string }>;\n /** Counter for generating unique image filenames */\n imageCounter: number;\n}\n\ninterface NumberingInfo {\n levels: Map<number, boolean>; // ilvl → isOrdered\n}\n\nasync function buildImportContext(\n pkg: OoxmlPackage,\n options: DocxImportOptions,\n): Promise<ImportContext> {\n const ctx: ImportContext = {\n headingStyles: new Map(),\n quoteStyles: new Set(),\n codeStyles: new Set(),\n inlineCodeStyles: new Set(),\n documentRels: new Map(),\n numbering: new Map(),\n footnotes: new Map(),\n pkg,\n options,\n extractedImages: new Map(),\n imageCounter: 0,\n };\n\n // Initialize with built-in defaults\n for (const [id, depth] of Object.entries(HEADING_STYLE_MAP)) {\n ctx.headingStyles.set(id, depth);\n }\n for (const id of QUOTE_STYLE_IDS) {\n ctx.quoteStyles.add(id);\n }\n for (const id of CODE_STYLE_IDS) {\n ctx.codeStyles.add(id);\n }\n for (const id of INLINE_CODE_STYLE_IDS) {\n ctx.inlineCodeStyles.add(id);\n }\n\n // Parse styles.xml for custom heading/quote/code mappings\n await parseStyles(pkg, ctx);\n\n // Parse document relationships\n const rels = await getPartRelationships(pkg, 'word/document.xml');\n for (const rel of rels) {\n ctx.documentRels.set(rel.id, rel);\n }\n\n // Parse numbering.xml\n await parseNumbering(pkg, ctx);\n\n // Parse footnotes.xml\n await parseFootnotes(pkg, ctx);\n\n return ctx;\n}\n\n// ============================================\n// Styles Parsing\n// ============================================\n\nasync function parseStyles(pkg: OoxmlPackage, ctx: ImportContext): Promise<void> {\n const doc = await getPartXml(pkg, 'word/styles.xml');\n if (!doc) return;\n\n const styles = doc.getElementsByTagNameNS(NS_WML, 'style');\n // Fallback for documents that don't use namespace prefixes properly\n const stylesList = styles.length > 0 ? styles : doc.getElementsByTagName('style');\n\n for (let i = 0; i < stylesList.length; i++) {\n const style = stylesList[i];\n const styleId = style.getAttributeNS(NS_WML, 'styleId') ?? style.getAttribute('w:styleId');\n if (!styleId) continue;\n\n const nameEl = getFirstChildElement(style, 'name');\n const styleName = nameEl?.getAttributeNS(NS_WML, 'val') ?? nameEl?.getAttribute('w:val') ?? '';\n\n // Check if this is a heading style by name\n const headingMatch = styleName.match(/^heading\\s+(\\d+)$/i);\n if (headingMatch) {\n const depth = parseInt(headingMatch[1], 10);\n if (depth >= 1 && depth <= 6) {\n ctx.headingStyles.set(styleId, depth);\n }\n }\n\n // Check pPr > outlineLvl for heading detection\n const pPr = getFirstChildElement(style, 'pPr');\n if (pPr) {\n const outlineLvl = getFirstChildElement(pPr, 'outlineLvl');\n if (outlineLvl) {\n const val = outlineLvl.getAttributeNS(NS_WML, 'val') ?? outlineLvl.getAttribute('w:val');\n if (val !== null) {\n const depth = parseInt(val, 10) + 1;\n if (depth >= 1 && depth <= 6) {\n ctx.headingStyles.set(styleId, depth);\n }\n }\n }\n }\n }\n}\n\n// ============================================\n// Numbering Parsing\n// ============================================\n\nasync function parseNumbering(pkg: OoxmlPackage, ctx: ImportContext): Promise<void> {\n const doc = await getPartXml(pkg, 'word/numbering.xml');\n if (!doc) return;\n\n // Parse abstract numbering definitions\n const abstractNums = new Map<string, Map<number, boolean>>(); // abstractNumId → levels(ilvl → isOrdered)\n\n const abstractNumEls = getAllElements(doc, 'abstractNum');\n for (const absNum of abstractNumEls) {\n const absId = getAttr(absNum, 'abstractNumId');\n if (!absId) continue;\n\n const levels = new Map<number, boolean>();\n const lvlEls = getAllChildElements(absNum, 'lvl');\n for (const lvl of lvlEls) {\n const ilvlStr = getAttr(lvl, 'ilvl');\n if (ilvlStr === null) continue;\n const ilvl = parseInt(ilvlStr, 10);\n\n const numFmtEl = getFirstChildElement(lvl, 'numFmt');\n const numFmt = numFmtEl ? getAttr(numFmtEl, 'val') : null;\n\n const isOrdered = numFmt !== null && !BULLET_NUM_FORMATS.has(numFmt);\n levels.set(ilvl, isOrdered);\n }\n\n abstractNums.set(absId, levels);\n }\n\n // Parse concrete num → abstractNum mappings\n const numEls = getAllElements(doc, 'num');\n for (const num of numEls) {\n const numId = getAttr(num, 'numId');\n if (!numId) continue;\n\n const abstractNumIdEl = getFirstChildElement(num, 'abstractNumId');\n const absId = abstractNumIdEl ? getAttr(abstractNumIdEl, 'val') : null;\n if (!absId) continue;\n\n const levels = abstractNums.get(absId);\n if (levels) {\n ctx.numbering.set(numId, { levels });\n }\n }\n}\n\n// ============================================\n// Footnotes Parsing\n// ============================================\n\nasync function parseFootnotes(pkg: OoxmlPackage, ctx: ImportContext): Promise<void> {\n const doc = await getPartXml(pkg, 'word/footnotes.xml');\n if (!doc) return;\n\n const footnoteEls = getAllElements(doc, 'footnote');\n for (const fn of footnoteEls) {\n const id = getAttr(fn, 'id');\n const type = getAttr(fn, 'type');\n // Skip separator and continuation separator footnotes\n if (!id || type === 'separator' || type === 'continuationSeparator') continue;\n ctx.footnotes.set(id, fn);\n }\n}\n\n// ============================================\n// Body Conversion\n// ============================================\n\nasync function convertBody(body: Element, ctx: ImportContext): Promise<MarkdownBlockNode[]> {\n const result: MarkdownBlockNode[] = [];\n const children = Array.from(body.children);\n\n let i = 0;\n while (i < children.length) {\n const el = children[i];\n const localName = el.localName;\n\n if (localName === 'p') {\n // Check if this is part of a list\n const numPr = getNumPr(el);\n if (numPr) {\n // Collect consecutive list paragraphs\n const { node, consumed } = await collectList(children, i, ctx);\n result.push(node);\n i += consumed;\n continue;\n }\n\n const block = await convertParagraph(el, ctx);\n if (block) {\n result.push(block);\n }\n i++;\n } else if (localName === 'tbl') {\n const table = await convertTable(el, ctx);\n if (table) result.push(table);\n i++;\n } else {\n // Skip unknown elements (sectPr, bookmarkStart, etc.)\n i++;\n }\n }\n\n // Append footnote definitions at the end\n const footnoteNodes = await convertFootnoteDefinitions(ctx);\n result.push(...footnoteNodes);\n\n return result;\n}\n\n// ============================================\n// Paragraph Conversion\n// ============================================\n\nasync function convertParagraph(\n el: Element,\n ctx: ImportContext,\n): Promise<MarkdownBlockNode | null> {\n const pPr = getFirstChildElement(el, 'pPr');\n const styleId = getParagraphStyleId(pPr);\n\n // Check for heading\n if (styleId && ctx.headingStyles.has(styleId)) {\n const depth = ctx.headingStyles.get(styleId)!;\n const inlines = await convertRuns(el, ctx);\n if (inlines.length === 0) return null;\n return {\n type: 'heading',\n depth: Math.min(Math.max(depth, 1), 6) as 1 | 2 | 3 | 4 | 5 | 6,\n children: inlines,\n } satisfies MarkdownHeading;\n }\n\n // Check for blockquote\n if (styleId && ctx.quoteStyles.has(styleId)) {\n const inlines = await convertRuns(el, ctx);\n if (inlines.length === 0) return null;\n const paragraph: MarkdownParagraph = { type: 'paragraph', children: inlines };\n return { type: 'blockquote', children: [paragraph] } satisfies MarkdownBlockquote;\n }\n\n // Check for code block\n if (styleId && ctx.codeStyles.has(styleId)) {\n const text = getElementTextContent(el);\n return { type: 'code', value: text } satisfies MarkdownCodeBlock;\n }\n\n // Regular paragraph\n const inlines = await convertRuns(el, ctx);\n if (inlines.length === 0) return null;\n return { type: 'paragraph', children: inlines } satisfies MarkdownParagraph;\n}\n\n// ============================================\n// Run (Inline) Conversion\n// ============================================\n\nasync function convertRuns(\n paragraphEl: Element,\n ctx: ImportContext,\n): Promise<MarkdownInlineNode[]> {\n const result: MarkdownInlineNode[] = [];\n const children = Array.from(paragraphEl.children);\n\n for (const child of children) {\n const localName = child.localName;\n\n if (localName === 'r') {\n const inlines = await convertRun(child, ctx);\n result.push(...inlines);\n } else if (localName === 'hyperlink') {\n const link = await convertHyperlink(child, ctx);\n if (link) result.push(link);\n }\n // Skip pPr, bookmarkStart, bookmarkEnd, etc.\n }\n\n return mergeAdjacentText(result);\n}\n\nasync function convertRun(runEl: Element, ctx: ImportContext): Promise<MarkdownInlineNode[]> {\n const result: MarkdownInlineNode[] = [];\n const rPr = getFirstChildElement(runEl, 'rPr');\n const format = parseRunFormat(rPr, ctx);\n\n for (const child of Array.from(runEl.children)) {\n const localName = child.localName;\n\n if (localName === 't') {\n const text = child.textContent ?? '';\n if (!text) continue;\n\n if (format.code) {\n result.push({ type: 'inlineCode', value: text } satisfies MarkdownInlineCode);\n } else {\n let node: MarkdownInlineNode = { type: 'text', value: text } satisfies MarkdownText;\n if (format.strike) {\n node = { type: 'delete', children: [node] } satisfies MarkdownStrikethrough;\n }\n if (format.italic) {\n node = { type: 'emphasis', children: [node] } satisfies MarkdownEmphasis;\n }\n if (format.bold) {\n node = { type: 'strong', children: [node] } satisfies MarkdownStrong;\n }\n result.push(node);\n }\n } else if (localName === 'br') {\n result.push({ type: 'break' } satisfies MarkdownBreak);\n } else if (localName === 'footnoteReference') {\n const fnId = getAttr(child, 'id');\n if (fnId && fnId !== '0' && fnId !== '-1') {\n result.push({\n type: 'footnoteReference',\n identifier: `fn${fnId}`,\n } satisfies MarkdownFootnoteReference);\n }\n } else if (localName === 'drawing' || localName === 'pict') {\n const img = await extractImage(child, ctx);\n if (img) result.push(img);\n }\n }\n\n return result;\n}\n\ninterface RunFormat {\n bold: boolean;\n italic: boolean;\n strike: boolean;\n code: boolean;\n}\n\nfunction parseRunFormat(rPr: Element | null, ctx: ImportContext): RunFormat {\n if (!rPr) return { bold: false, italic: false, strike: false, code: false };\n\n const bold = hasChildElement(rPr, 'b') && !isFalseToggle(getFirstChildElement(rPr, 'b')!);\n const italic = hasChildElement(rPr, 'i') && !isFalseToggle(getFirstChildElement(rPr, 'i')!);\n const strike =\n hasChildElement(rPr, 'strike') && !isFalseToggle(getFirstChildElement(rPr, 'strike')!);\n\n // Check for inline code via character style\n const rStyle = getFirstChildElement(rPr, 'rStyle');\n const charStyleId = rStyle ? getAttr(rStyle, 'val') : null;\n const isCodeStyle = charStyleId ? ctx.inlineCodeStyles.has(charStyleId) : false;\n\n // Check for monospace font as a code indicator\n const rFonts = getFirstChildElement(rPr, 'rFonts');\n const fontName = rFonts ? (getAttr(rFonts, 'ascii') ?? getAttr(rFonts, 'hAnsi') ?? '') : '';\n const isMonospace = /consolas|courier|mono/i.test(fontName);\n\n return { bold, italic, strike, code: isCodeStyle || isMonospace };\n}\n\nfunction isFalseToggle(el: Element): boolean {\n const val = getAttr(el, 'val');\n return val === '0' || val === 'false';\n}\n\n// ============================================\n// Hyperlink Conversion\n// ============================================\n\nasync function convertHyperlink(el: Element, ctx: ImportContext): Promise<MarkdownLink | null> {\n const rId = el.getAttributeNS(NS_R, 'id') ?? el.getAttribute('r:id');\n\n let url = '';\n if (rId) {\n const rel = ctx.documentRels.get(rId);\n if (rel) url = rel.target;\n }\n\n // Also check for w:anchor (internal bookmarks)\n if (!url) {\n const anchor = el.getAttributeNS(NS_WML, 'anchor') ?? el.getAttribute('w:anchor');\n if (anchor) url = `#${anchor}`;\n }\n\n const inlines: MarkdownInlineNode[] = [];\n for (const child of Array.from(el.children)) {\n if (child.localName === 'r') {\n inlines.push(...(await convertRun(child, ctx)));\n }\n }\n\n if (inlines.length === 0) return null;\n\n return {\n type: 'link',\n url,\n children: mergeAdjacentText(inlines),\n };\n}\n\n// ============================================\n// Image Extraction\n// ============================================\n\nasync function extractImage(el: Element, ctx: ImportContext): Promise<MarkdownImage | null> {\n // Find <a:blip r:embed=\"rIdX\"/> anywhere in the drawing tree\n const blip = findDescendant(el, 'blip');\n if (!blip) {\n return { type: 'image', url: '', alt: 'Image' };\n }\n\n const rId = blip.getAttributeNS(NS_R, 'embed') ?? blip.getAttribute('r:embed');\n if (!rId) {\n return { type: 'image', url: '', alt: 'Image' };\n }\n\n const rel = ctx.documentRels.get(rId);\n if (!rel) {\n return { type: 'image', url: '', alt: 'Image' };\n }\n\n // Resolve the target path relative to word/\n const target = rel.target.startsWith('/') ? rel.target.slice(1) : `word/${rel.target}`;\n\n // Extract binary data from the zip\n const data = await getPartBinary(ctx.pkg, target);\n if (!data) {\n return { type: 'image', url: '', alt: 'Image' };\n }\n\n // Determine extension and MIME type\n const dot = target.lastIndexOf('.');\n const ext = dot !== -1 ? target.slice(dot).toLowerCase() : '.png';\n const mimeType = IMAGE_MIME_MAP[ext] ?? 'application/octet-stream';\n\n // Generate a unique image path\n ctx.imageCounter++;\n const imagePath = `images/image${ctx.imageCounter}${ext}`;\n\n // Store the extracted image data\n ctx.extractedImages.set(imagePath, { data, mimeType });\n\n // Try to extract alt text from the drawing's docPr element\n const docPr = findDescendant(el, 'docPr');\n const alt = docPr?.getAttribute('descr') || docPr?.getAttribute('title') || 'Image';\n\n return {\n type: 'image',\n url: imagePath,\n alt,\n };\n}\n\nconst IMAGE_MIME_MAP: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.bmp': 'image/bmp',\n '.tiff': 'image/tiff',\n '.tif': 'image/tiff',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.emf': 'image/emf',\n '.wmf': 'image/wmf',\n};\n\n/** Recursively find the first descendant element with the given local name. */\nfunction findDescendant(el: Element, localName: string): Element | null {\n for (const child of Array.from(el.children)) {\n if (child.localName === localName) return child;\n const found = findDescendant(child, localName);\n if (found) return found;\n }\n return null;\n}\n\n// ============================================\n// List Collection\n// ============================================\n\ninterface ListResult {\n node: MarkdownList;\n consumed: number;\n}\n\ninterface NumPrInfo {\n numId: string;\n ilvl: number;\n}\n\nasync function collectList(\n elements: Element[],\n startIdx: number,\n ctx: ImportContext,\n): Promise<ListResult> {\n const firstNumPr = getNumPr(elements[startIdx])!;\n const { numId } = firstNumPr;\n\n // Determine if ordered from numbering definition\n const numInfo = ctx.numbering.get(numId);\n const isOrdered = numInfo?.levels.get(0) ?? false;\n\n const items: MarkdownListItem[] = [];\n let consumed = 0;\n\n let i = startIdx;\n while (i < elements.length) {\n const el = elements[i];\n if (el.localName !== 'p') break;\n\n const numPr = getNumPr(el);\n if (!numPr || numPr.numId !== numId) break;\n\n // Convert this paragraph's inline content\n const inlines = await convertRuns(el, ctx);\n if (inlines.length > 0) {\n const paragraph: MarkdownParagraph = { type: 'paragraph', children: inlines };\n\n // Check if this is a nested list item\n if (numPr.ilvl > firstNumPr.ilvl) {\n // Collect nested list items\n const nested = await collectNestedList(elements, i, ctx, firstNumPr.ilvl);\n if (items.length > 0) {\n // Attach nested list to the last item\n const lastItem = items[items.length - 1];\n const nestedIsOrdered = numInfo?.levels.get(numPr.ilvl) ?? false;\n const nestedList: MarkdownList = {\n type: 'list',\n ordered: nestedIsOrdered,\n children: nested.items,\n };\n lastItem.children.push(nestedList);\n }\n i += nested.consumed;\n consumed += nested.consumed;\n continue;\n }\n\n items.push({\n type: 'listItem',\n children: [paragraph],\n });\n }\n\n i++;\n consumed++;\n }\n\n return {\n node: {\n type: 'list',\n ordered: isOrdered,\n children: items,\n },\n consumed,\n };\n}\n\ninterface NestedListResult {\n items: MarkdownListItem[];\n consumed: number;\n}\n\nasync function collectNestedList(\n elements: Element[],\n startIdx: number,\n ctx: ImportContext,\n parentIlvl: number,\n): Promise<NestedListResult> {\n const items: MarkdownListItem[] = [];\n let consumed = 0;\n\n let i = startIdx;\n while (i < elements.length) {\n const el = elements[i];\n if (el.localName !== 'p') break;\n\n const numPr = getNumPr(el);\n if (!numPr) break;\n if (numPr.ilvl <= parentIlvl) break;\n\n const inlines = await convertRuns(el, ctx);\n if (inlines.length > 0) {\n const paragraph: MarkdownParagraph = { type: 'paragraph', children: inlines };\n items.push({ type: 'listItem', children: [paragraph] });\n }\n\n i++;\n consumed++;\n }\n\n return { items, consumed };\n}\n\nfunction getNumPr(el: Element): NumPrInfo | null {\n const pPr = getFirstChildElement(el, 'pPr');\n if (!pPr) return null;\n\n const numPr = getFirstChildElement(pPr, 'numPr');\n if (!numPr) return null;\n\n const ilvlEl = getFirstChildElement(numPr, 'ilvl');\n const numIdEl = getFirstChildElement(numPr, 'numId');\n\n const ilvlVal = ilvlEl ? getAttr(ilvlEl, 'val') : null;\n const numIdVal = numIdEl ? getAttr(numIdEl, 'val') : null;\n\n if (!numIdVal || numIdVal === '0') return null; // numId 0 means \"no list\"\n\n return {\n numId: numIdVal,\n ilvl: ilvlVal ? parseInt(ilvlVal, 10) : 0,\n };\n}\n\n// ============================================\n// Table Conversion\n// ============================================\n\nasync function convertTable(tblEl: Element, ctx: ImportContext): Promise<MarkdownTable | null> {\n const rows: MarkdownTableRow[] = [];\n\n const trEls = getAllChildElements(tblEl, 'tr');\n for (let ri = 0; ri < trEls.length; ri++) {\n const row = await convertTableRow(trEls[ri], ctx, ri === 0);\n rows.push(row);\n }\n\n if (rows.length === 0) return null;\n\n // If first row isn't explicitly a header, treat it as one anyway\n // (Markdown tables require a header row)\n return {\n type: 'table',\n children: rows,\n };\n}\n\nasync function convertTableRow(\n trEl: Element,\n ctx: ImportContext,\n isHeader: boolean,\n): Promise<MarkdownTableRow> {\n const cells: MarkdownTableCell[] = [];\n const tcEls = getAllChildElements(trEl, 'tc');\n\n for (const tc of tcEls) {\n const cell = await convertTableCell(tc, ctx, isHeader);\n cells.push(cell);\n }\n\n return { type: 'tableRow', children: cells };\n}\n\nasync function convertTableCell(\n tcEl: Element,\n ctx: ImportContext,\n isHeader: boolean,\n): Promise<MarkdownTableCell> {\n const inlines: MarkdownInlineNode[] = [];\n\n // A cell can contain multiple paragraphs; flatten them with breaks\n const paragraphs = getAllChildElements(tcEl, 'p');\n for (let pi = 0; pi < paragraphs.length; pi++) {\n if (pi > 0) {\n inlines.push({ type: 'break' } as MarkdownBreak);\n }\n const runs = await convertRuns(paragraphs[pi], ctx);\n inlines.push(...runs);\n }\n\n return {\n type: 'tableCell',\n isHeader,\n children: mergeAdjacentText(inlines),\n };\n}\n\n// ============================================\n// Footnote Definition Conversion\n// ============================================\n\nasync function convertFootnoteDefinitions(\n ctx: ImportContext,\n): Promise<MarkdownFootnoteDefinition[]> {\n const results: MarkdownFootnoteDefinition[] = [];\n\n for (const [id, el] of ctx.footnotes) {\n const children: MarkdownBlockNode[] = [];\n const paragraphs = getAllChildElements(el, 'p');\n\n for (const p of paragraphs) {\n const inlines = await convertRuns(p, ctx);\n if (inlines.length > 0) {\n children.push({\n type: 'paragraph',\n children: inlines,\n } satisfies MarkdownParagraph);\n }\n }\n\n if (children.length > 0) {\n results.push({\n type: 'footnoteDefinition',\n identifier: `fn${id}`,\n children,\n });\n }\n }\n\n return results;\n}\n\n// ============================================\n// XML Helper Utilities\n// ============================================\n\n/**\n * Get the first element child with a given local name.\n * Handles both namespaced and non-namespaced elements.\n */\nfunction getFirstChildElement(parent: Element | Document, localName: string): Element | null {\n for (const child of Array.from(parent.children ?? [])) {\n if (child.localName === localName) return child;\n }\n return null;\n}\n\n/**\n * Get all direct child elements with a given local name.\n */\nfunction getAllChildElements(parent: Element, localName: string): Element[] {\n const result: Element[] = [];\n for (const child of Array.from(parent.children)) {\n if (child.localName === localName) result.push(child);\n }\n return result;\n}\n\n/**\n * Get all elements with a given local name in the document.\n */\nfunction getAllElements(doc: Document | Element, localName: string): Element[] {\n // Try namespace-aware first\n const nsEls =\n 'getElementsByTagNameNS' in doc ? doc.getElementsByTagNameNS(NS_WML, localName) : null;\n if (nsEls && nsEls.length > 0) return Array.from(nsEls);\n\n // Fallback: try with w: prefix\n const prefixed = doc.getElementsByTagName(`w:${localName}`);\n if (prefixed.length > 0) return Array.from(prefixed);\n\n // Final fallback: bare name\n return Array.from(doc.getElementsByTagName(localName));\n}\n\n/**\n * Get the first element with given local name in the document or subtree.\n */\nfunction getFirstElement(doc: Document | Element, localName: string): Element | null {\n const els = getAllElements(doc, localName);\n return els.length > 0 ? els[0] : null;\n}\n\n/**\n * Get a w:-prefixed attribute, trying namespace-aware first then fallback.\n */\nfunction getAttr(el: Element, localName: string): string | null {\n return el.getAttributeNS(NS_WML, localName) || el.getAttribute(`w:${localName}`) || null;\n}\n\n/**\n * Check if an element has a direct child with the given local name.\n */\nfunction hasChildElement(parent: Element, localName: string): boolean {\n return getFirstChildElement(parent, localName) !== null;\n}\n\n/**\n * Get the paragraph style ID from a pPr element.\n */\nfunction getParagraphStyleId(pPr: Element | null): string | null {\n if (!pPr) return null;\n const pStyle = getFirstChildElement(pPr, 'pStyle');\n if (!pStyle) return null;\n return getAttr(pStyle, 'val');\n}\n\n/**\n * Get all text content from an element (concatenating all w:t descendants).\n */\nfunction getElementTextContent(el: Element): string {\n const parts: string[] = [];\n\n function walk(node: Element): void {\n if (node.localName === 't') {\n parts.push(node.textContent ?? '');\n }\n for (const child of Array.from(node.children)) {\n walk(child);\n }\n }\n\n walk(el);\n return parts.join('');\n}\n\n/**\n * Merge adjacent MarkdownText nodes to reduce fragmentation.\n */\nfunction mergeAdjacentText(nodes: MarkdownInlineNode[]): MarkdownInlineNode[] {\n if (nodes.length <= 1) return nodes;\n\n const result: MarkdownInlineNode[] = [];\n for (const node of nodes) {\n const prev = result[result.length - 1];\n if (node.type === 'text' && prev?.type === 'text') {\n // Merge into previous text node\n (prev as MarkdownText).value += (node as MarkdownText).value;\n } else {\n result.push(node);\n }\n }\n return result;\n}\n"],"mappings":"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","names":["container","convertParagraph","convertTable","inlines","convertTableRow","convertTableCell"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pptx/export.ts","../src/pptx/styles.ts","../src/pptx/templates.ts","../src/pptx/index.ts"],"sourcesContent":["/**\n * PPTX Export\n *\n * Converts a squisq MarkdownDocument (or Doc) into a .pptx file\n * by generating PresentationML + DrawingML XML and assembling the\n * OOXML package.\n *\n * Slide segmentation: each H1 or H2 heading starts a new slide.\n * The heading becomes the slide title; content below becomes the body.\n *\n * Supports:\n * - Theme-based styling (background, text colors, fonts from squisq themes)\n * - Image embedding (pass images as ArrayBuffers via options)\n * - Inline formatting (bold, italic, strikethrough, code, links)\n * - Lists, code blocks, blockquotes, tables, math\n *\n * No third-party pptx library — all XML is generated directly using\n * the shared ooxml/ infrastructure.\n *\n * @example\n * ```ts\n * import { parseMarkdown } from '@bendyline/squisq/markdown';\n * import { markdownDocToPptx } from '@bendyline/squisq-formats/pptx';\n *\n * const md = parseMarkdown('# Slide 1\\n\\nHello world\\n\\n## Slide 2\\n\\nMore content');\n * const blob = await markdownDocToPptx(md, { themeId: 'documentary' });\n * ```\n */\n\nimport type { Doc } from '@bendyline/squisq/schemas';\nimport { resolveTheme, resolveFontFamily } from '@bendyline/squisq/schemas';\nimport type { Theme } from '@bendyline/squisq/schemas';\nimport { docToMarkdown } from '@bendyline/squisq/doc';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownInlineNode,\n MarkdownHeading,\n MarkdownParagraph,\n MarkdownBlockquote,\n MarkdownList,\n MarkdownListItem,\n MarkdownCodeBlock,\n MarkdownTable,\n MarkdownTableRow,\n MarkdownHtmlBlock,\n MarkdownMathBlock,\n MarkdownLink,\n MarkdownImage,\n} from '@bendyline/squisq/markdown';\nimport { readFrontmatterThemeId } from '@bendyline/squisq/markdown';\n\nimport { createPackage } from '../ooxml/writer.js';\nimport { xmlDeclaration, escapeXml } from '../ooxml/xmlUtils.js';\nimport {\n NS_PML,\n NS_DRAWINGML,\n NS_R,\n REL_OFFICE_DOCUMENT,\n REL_SLIDE,\n REL_SLIDE_LAYOUT,\n REL_SLIDE_MASTER,\n REL_THEME,\n REL_HYPERLINK,\n REL_IMAGE,\n CONTENT_TYPE_PPTX_PRESENTATION,\n CONTENT_TYPE_PPTX_SLIDE,\n CONTENT_TYPE_PPTX_SLIDE_LAYOUT,\n CONTENT_TYPE_PPTX_SLIDE_MASTER,\n CONTENT_TYPE_PPTX_THEME,\n} from '../ooxml/namespaces.js';\nimport {\n DEFAULT_FONT,\n DEFAULT_TITLE_FONT,\n DEFAULT_CODE_FONT,\n DEFAULT_TITLE_SIZE,\n DEFAULT_CODE_SIZE,\n HYPERLINK_COLOR,\n TITLE_LEFT,\n TITLE_TOP,\n TITLE_WIDTH,\n TITLE_HEIGHT,\n BODY_LEFT,\n BODY_TOP,\n BODY_WIDTH,\n BODY_HEIGHT,\n} from './styles.js';\nimport {\n buildPresentationXml,\n buildSlideMasterXml,\n buildSlideLayoutXml,\n buildThemeXml,\n} from './templates.js';\n\n// ============================================\n// Public API\n// ============================================\n\n/**\n * Options for PPTX export.\n */\nexport interface PptxExportOptions {\n /** Presentation title (appears in core properties) */\n title?: string;\n /** Presentation author */\n author?: string;\n /** Presentation description */\n description?: string;\n /**\n * Which heading depth triggers a new slide.\n * - `'h1'` — only H1 headings start slides\n * - `'h2'` — H1 and H2 headings start slides (default)\n * - `'heading'` — any heading (H1–H6) starts a slide\n */\n slideBreak?: 'h1' | 'h2' | 'heading';\n /** Default body font family. Default: \"Calibri\" */\n defaultFont?: string;\n /** Default body font size in points. Default: 18 */\n defaultFontSize?: number;\n /**\n * Squisq theme ID to apply (e.g., 'documentary', 'cinematic', 'bold').\n * Controls slide background, text colors, and fonts.\n * Falls back to the document's frontmatter `themeId` if not set here.\n */\n themeId?: string;\n /**\n * Image data keyed by the path/URL used in markdown.\n * When provided, images are embedded as picture shapes instead of\n * showing `[Image: alt]` placeholders.\n */\n images?: Map<string, ArrayBuffer>;\n}\n\n/**\n * Convert a MarkdownDocument to a .pptx ArrayBuffer.\n */\nexport async function markdownDocToPptx(\n doc: MarkdownDocument,\n options: PptxExportOptions = {},\n): Promise<ArrayBuffer> {\n // Resolve theme from options or frontmatter. The frontmatter lookup\n // accepts the editor's canonical `squisq-theme` key as well as the\n // shorter legacy `themeId` / `theme` aliases — see\n // `readFrontmatterThemeId` for the precedence.\n const themeId = options.themeId ?? readFrontmatterThemeId(doc.frontmatter);\n const style = resolveSlideStyle(themeId, options);\n\n const slides = segmentIntoSlides(doc.children, options.slideBreak ?? 'h2');\n\n // Ensure at least one slide\n if (slides.length === 0) {\n slides.push({ bodyNodes: [] });\n }\n\n const slideXmls: string[] = [];\n const slideContexts: SlideContext[] = [];\n\n for (let i = 0; i < slides.length; i++) {\n const ctx = new SlideContext(style, options.images, i);\n const xml = buildSlideXml(slides[i], ctx);\n slideXmls.push(xml);\n slideContexts.push(ctx);\n }\n\n return buildPptxPackage(slideXmls, slideContexts, options);\n}\n\n/**\n * Convert a squisq Doc to a .pptx ArrayBuffer.\n *\n * Convenience wrapper: Doc -> MarkdownDocument -> PPTX.\n */\nexport async function docToPptx(doc: Doc, options: PptxExportOptions = {}): Promise<ArrayBuffer> {\n const markdownDoc = docToMarkdown(doc);\n // Carry themeId from Doc if not set in options\n if (!options.themeId && doc.themeId) {\n options = { ...options, themeId: doc.themeId };\n }\n return markdownDocToPptx(markdownDoc, options);\n}\n\n// ============================================\n// Resolved Style\n// ============================================\n\n/** Resolved visual style for slides, derived from a Theme or defaults. */\ninterface SlideStyle {\n background: string; // hex without #\n text: string;\n titleColor: string;\n mutedColor: string;\n titleFont: string;\n bodyFont: string;\n codeFont: string;\n codeColor: string;\n hasTheme: boolean;\n}\n\nfunction resolveSlideStyle(themeId: string | undefined, options: PptxExportOptions): SlideStyle {\n if (!themeId) {\n return {\n background: 'FFFFFF',\n text: '333333',\n titleColor: '333333',\n mutedColor: '666666',\n titleFont: options.defaultFont ?? DEFAULT_TITLE_FONT,\n bodyFont: options.defaultFont ?? DEFAULT_FONT,\n codeFont: DEFAULT_CODE_FONT,\n codeColor: '333333',\n hasTheme: false,\n };\n }\n\n const theme: Theme = resolveTheme(themeId);\n const c = theme.colors;\n\n return {\n background: stripHash(c.background),\n text: stripHash(c.text),\n titleColor: stripHash(c.highlight || c.secondary || c.text),\n mutedColor: stripHash(c.textMuted || c.text),\n titleFont: resolveFontFamily(theme.typography?.titleFont, DEFAULT_TITLE_FONT),\n bodyFont: resolveFontFamily(theme.typography?.bodyFont, options.defaultFont || DEFAULT_FONT),\n codeFont: resolveFontFamily(theme.typography?.monoFont, DEFAULT_CODE_FONT),\n codeColor: stripHash(c.textMuted || c.text),\n hasTheme: true,\n };\n}\n\nfunction stripHash(color: string): string {\n return color.startsWith('#') ? color.slice(1) : color;\n}\n\n// ============================================\n// Slide Segmentation\n// ============================================\n\ninterface SlideData {\n title?: string;\n titleDepth?: number;\n bodyNodes: MarkdownBlockNode[];\n}\n\nfunction segmentIntoSlides(\n children: MarkdownBlockNode[],\n slideBreak: 'h1' | 'h2' | 'heading',\n): SlideData[] {\n const maxDepth = slideBreak === 'h1' ? 1 : slideBreak === 'h2' ? 2 : 6;\n const slides: SlideData[] = [];\n let current: SlideData | undefined;\n\n for (const node of children) {\n if (node.type === 'heading' && node.depth <= maxDepth) {\n if (current) slides.push(current);\n current = {\n title: extractPlainText(node.children),\n titleDepth: node.depth,\n bodyNodes: [],\n };\n } else {\n if (!current) {\n current = { bodyNodes: [] };\n }\n current.bodyNodes.push(node);\n }\n }\n\n if (current) slides.push(current);\n return slides;\n}\n\nfunction extractPlainText(nodes: MarkdownInlineNode[]): string {\n const parts: string[] = [];\n for (const node of nodes) {\n switch (node.type) {\n case 'text':\n parts.push(node.value);\n break;\n case 'inlineCode':\n parts.push(node.value);\n break;\n case 'strong':\n case 'emphasis':\n case 'delete':\n parts.push(extractPlainText(node.children));\n break;\n case 'link':\n parts.push(extractPlainText(node.children));\n break;\n case 'image':\n parts.push(node.alt ?? '');\n break;\n case 'inlineMath':\n parts.push(node.value);\n break;\n default:\n break;\n }\n }\n return parts.join('');\n}\n\n// ============================================\n// Slide Context\n// ============================================\n\ninterface EmbeddedImage {\n relId: string;\n mediaPath: string; // e.g. ppt/media/image_s0_1.png\n data: ArrayBuffer;\n contentType: string;\n alt: string;\n}\n\nclass SlideContext {\n private nextRelId = 1;\n\n readonly relationships: Array<{\n id: string;\n type: string;\n target: string;\n targetMode?: 'External';\n }> = [];\n\n readonly style: SlideStyle;\n readonly images: Map<string, ArrayBuffer> | undefined;\n readonly slideIndex: number;\n readonly embeddedImages: EmbeddedImage[] = [];\n private nextShapeId = 4; // 1=group, 2=title, 3=body\n\n constructor(style: SlideStyle, images: Map<string, ArrayBuffer> | undefined, slideIndex: number) {\n this.style = style;\n this.images = images;\n this.slideIndex = slideIndex;\n }\n\n allocRelId(): string {\n return `rId${this.nextRelId++ + 1}`;\n }\n\n allocShapeId(): number {\n return this.nextShapeId++;\n }\n\n addHyperlink(url: string): string {\n const id = this.allocRelId();\n this.relationships.push({\n id,\n type: REL_HYPERLINK,\n target: url,\n targetMode: 'External',\n });\n return id;\n }\n\n /** Register an embedded image and return its relationship ID */\n addImage(src: string, data: ArrayBuffer, alt: string): string {\n const relId = this.allocRelId();\n const ext = inferExtension(src);\n const contentType = inferMimeType(ext);\n const imgIndex = this.embeddedImages.length + 1;\n const mediaPath = `ppt/media/image_s${this.slideIndex}_${imgIndex}.${ext}`;\n\n this.embeddedImages.push({ relId, mediaPath, data, contentType, alt });\n this.relationships.push({\n id: relId,\n type: REL_IMAGE,\n target: `../media/image_s${this.slideIndex}_${imgIndex}.${ext}`,\n });\n\n return relId;\n }\n}\n\n// ============================================\n// Slide XML Generation\n// ============================================\n\nfunction buildSlideXml(slide: SlideData, ctx: SlideContext): string {\n const shapes: string[] = [];\n\n shapes.push(\n `<p:nvGrpSpPr><p:cNvPr id=\"1\" name=\"\"/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr>` + `<p:grpSpPr/>`,\n );\n\n if (slide.title) {\n shapes.push(buildTitleShape(slide.title, ctx.style));\n }\n\n // Convert body blocks and collect any image-only paragraphs\n const bodyParas = convertBodyBlocks(slide.bodyNodes, ctx);\n const hasImages = ctx.embeddedImages.length > 0;\n const hasText = bodyParas.length > 0;\n\n if (hasText && hasImages) {\n // Split: text in top half of body area, images below\n const textHeight = Math.round(BODY_HEIGHT * 0.45);\n const imgTop = BODY_TOP + textHeight + 91440; // 0.1\" gap\n const imgHeight = BODY_HEIGHT - textHeight - 91440;\n shapes.push(buildBodyShapeCustom(bodyParas, BODY_TOP, textHeight, ctx.style));\n shapes.push(\n buildImageShape(\n ctx.embeddedImages[0],\n ctx.allocShapeId(),\n BODY_LEFT,\n imgTop,\n BODY_WIDTH,\n imgHeight,\n ),\n );\n } else if (hasImages && !hasText) {\n // Full content area for image\n shapes.push(\n buildImageShape(\n ctx.embeddedImages[0],\n ctx.allocShapeId(),\n BODY_LEFT,\n BODY_TOP,\n BODY_WIDTH,\n BODY_HEIGHT,\n ),\n );\n } else {\n // Text only (or empty)\n shapes.push(\n buildBodyShapeCustom(\n bodyParas || `<a:p><a:endParaRPr lang=\"en-US\"/></a:p>`,\n BODY_TOP,\n BODY_HEIGHT,\n ctx.style,\n ),\n );\n }\n\n // Additional images beyond the first get placed as extra shapes\n for (let i = 1; i < ctx.embeddedImages.length; i++) {\n shapes.push(\n buildImageShape(\n ctx.embeddedImages[i],\n ctx.allocShapeId(),\n BODY_LEFT,\n BODY_TOP,\n BODY_WIDTH,\n BODY_HEIGHT,\n ),\n );\n }\n\n // Build background\n const bgXml = ctx.style.hasTheme\n ? `<p:bg><p:bgPr><a:solidFill><a:srgbClr val=\"${ctx.style.background}\"/></a:solidFill><a:effectLst/></p:bgPr></p:bg>`\n : '';\n\n return (\n xmlDeclaration() +\n `<p:sld xmlns:a=\"${NS_DRAWINGML}\" xmlns:r=\"${NS_R}\" xmlns:p=\"${NS_PML}\">` +\n `<p:cSld>` +\n bgXml +\n `<p:spTree>` +\n shapes.join('') +\n `</p:spTree>` +\n `</p:cSld>` +\n `</p:sld>`\n );\n}\n\nfunction buildTitleShape(title: string, style: SlideStyle): string {\n return (\n `<p:sp>` +\n `<p:nvSpPr>` +\n `<p:cNvPr id=\"2\" name=\"Title\"/>` +\n `<p:cNvSpPr><a:spLocks noGrp=\"1\"/></p:cNvSpPr>` +\n `<p:nvPr><p:ph type=\"title\"/></p:nvPr>` +\n `</p:nvSpPr>` +\n `<p:spPr>` +\n `<a:xfrm><a:off x=\"${TITLE_LEFT}\" y=\"${TITLE_TOP}\"/>` +\n `<a:ext cx=\"${TITLE_WIDTH}\" cy=\"${TITLE_HEIGHT}\"/></a:xfrm>` +\n `</p:spPr>` +\n `<p:txBody>` +\n `<a:bodyPr/>` +\n `<a:lstStyle/>` +\n `<a:p>` +\n `<a:r>` +\n `<a:rPr lang=\"en-US\" sz=\"${DEFAULT_TITLE_SIZE}\" dirty=\"0\">` +\n `<a:solidFill><a:srgbClr val=\"${style.titleColor}\"/></a:solidFill>` +\n `<a:latin typeface=\"${escapeXml(style.titleFont)}\"/>` +\n `</a:rPr>` +\n `<a:t>${escapeXml(title)}</a:t>` +\n `</a:r>` +\n `</a:p>` +\n `</p:txBody>` +\n `</p:sp>`\n );\n}\n\nfunction buildBodyShapeCustom(\n bodyContent: string,\n top: number,\n height: number,\n style: SlideStyle,\n): string {\n // Set default text color for the body via defRPr\n const defRPr = style.hasTheme\n ? `<a:defRPr><a:solidFill><a:srgbClr val=\"${style.text}\"/></a:solidFill><a:latin typeface=\"${escapeXml(style.bodyFont)}\"/></a:defRPr>`\n : '';\n\n return (\n `<p:sp>` +\n `<p:nvSpPr>` +\n `<p:cNvPr id=\"3\" name=\"Content\"/>` +\n `<p:cNvSpPr><a:spLocks noGrp=\"1\"/></p:cNvSpPr>` +\n `<p:nvPr><p:ph idx=\"1\"/></p:nvPr>` +\n `</p:nvSpPr>` +\n `<p:spPr>` +\n `<a:xfrm><a:off x=\"${BODY_LEFT}\" y=\"${top}\"/>` +\n `<a:ext cx=\"${BODY_WIDTH}\" cy=\"${height}\"/></a:xfrm>` +\n `</p:spPr>` +\n `<p:txBody>` +\n `<a:bodyPr/>` +\n `<a:lstStyle>` +\n `<a:lvl1pPr>${defRPr}</a:lvl1pPr>` +\n `</a:lstStyle>` +\n bodyContent +\n `</p:txBody>` +\n `</p:sp>`\n );\n}\n\nfunction buildImageShape(\n img: EmbeddedImage,\n shapeId: number,\n left: number,\n top: number,\n maxWidth: number,\n maxHeight: number,\n): string {\n return (\n `<p:pic>` +\n `<p:nvPicPr>` +\n `<p:cNvPr id=\"${shapeId}\" name=\"${escapeXml(img.alt || 'Picture')}\"/>` +\n `<p:cNvPicPr><a:picLocks noChangeAspect=\"1\"/></p:cNvPicPr>` +\n `<p:nvPr/>` +\n `</p:nvPicPr>` +\n `<p:blipFill>` +\n `<a:blip r:embed=\"${img.relId}\"/>` +\n `<a:stretch><a:fillRect/></a:stretch>` +\n `</p:blipFill>` +\n `<p:spPr>` +\n `<a:xfrm><a:off x=\"${left}\" y=\"${top}\"/>` +\n `<a:ext cx=\"${maxWidth}\" cy=\"${maxHeight}\"/></a:xfrm>` +\n `<a:prstGeom prst=\"rect\"><a:avLst/></a:prstGeom>` +\n `</p:spPr>` +\n `</p:pic>`\n );\n}\n\n// ============================================\n// Block Conversion (Markdown -> DrawingML paragraphs)\n// ============================================\n\nfunction convertBodyBlocks(nodes: MarkdownBlockNode[], ctx: SlideContext): string {\n const parts: string[] = [];\n for (const node of nodes) {\n parts.push(convertBlock(node, ctx, 0));\n }\n return parts.join('');\n}\n\nfunction convertBlock(node: MarkdownBlockNode, ctx: SlideContext, listDepth: number): string {\n switch (node.type) {\n case 'heading':\n return convertHeading(node, ctx);\n case 'paragraph':\n return convertParagraph(node, ctx);\n case 'blockquote':\n return convertBlockquote(node, ctx);\n case 'list':\n return convertList(node, ctx, listDepth);\n case 'code':\n return convertCodeBlock(node, ctx);\n case 'table':\n return convertTable(node, ctx);\n case 'thematicBreak':\n return convertThematicBreak(ctx);\n case 'htmlBlock':\n return convertHtmlBlock(node, ctx);\n case 'math':\n return convertMathBlock(node);\n default:\n return '';\n }\n}\n\nfunction convertHeading(node: MarkdownHeading, ctx: SlideContext): string {\n const size = headingSizeForDepth(node.depth);\n const runs = convertInlines(node.children, ctx, { bold: true });\n return (\n `<a:p>` +\n `<a:pPr>` +\n `<a:spcBef><a:spcPts val=\"600\"/></a:spcBef>` +\n `<a:defRPr sz=\"${size}\" b=\"1\">` +\n `<a:solidFill><a:srgbClr val=\"${ctx.style.titleColor}\"/></a:solidFill>` +\n `<a:latin typeface=\"${escapeXml(ctx.style.titleFont)}\"/>` +\n `</a:defRPr>` +\n `</a:pPr>` +\n runs +\n `</a:p>`\n );\n}\n\nfunction headingSizeForDepth(depth: number): number {\n const sizes: Record<number, number> = { 1: 3200, 2: 2800, 3: 2400, 4: 2000, 5: 1800, 6: 1800 };\n return sizes[depth] ?? 1800;\n}\n\n/**\n * Check if a paragraph contains only a single image (no surrounding text).\n */\nfunction isImageOnlyParagraph(node: MarkdownParagraph): MarkdownImage | null {\n if (node.children.length === 1 && node.children[0].type === 'image') {\n return node.children[0];\n }\n return null;\n}\n\nfunction convertParagraph(node: MarkdownParagraph, ctx: SlideContext): string {\n // If paragraph is just an image and we have the data, embed it as a shape\n const soloImage = isImageOnlyParagraph(node);\n if (soloImage && ctx.images) {\n const data = ctx.images.get(soloImage.url);\n if (data) {\n ctx.addImage(soloImage.url, data, soloImage.alt || '');\n return ''; // Image will be rendered as a p:pic shape, not inline text\n }\n }\n\n const runs = convertInlines(node.children, ctx);\n return `<a:p>${runs}</a:p>`;\n}\n\nfunction convertBlockquote(node: MarkdownBlockquote, ctx: SlideContext): string {\n const parts: string[] = [];\n for (const child of node.children) {\n if (child.type === 'paragraph') {\n const runs = convertInlines(child.children, ctx, { italic: true });\n parts.push(\n `<a:p>` +\n `<a:pPr marL=\"457200\">` +\n `<a:spcBef><a:spcPts val=\"200\"/></a:spcBef>` +\n `</a:pPr>` +\n runs +\n `</a:p>`,\n );\n } else {\n parts.push(convertBlock(child, ctx, 0));\n }\n }\n return parts.join('');\n}\n\nfunction convertList(node: MarkdownList, ctx: SlideContext, depth: number): string {\n const parts: string[] = [];\n for (const item of node.children) {\n parts.push(convertListItem(item, ctx, node.ordered ?? false, depth));\n }\n return parts.join('');\n}\n\nfunction convertListItem(\n item: MarkdownListItem,\n ctx: SlideContext,\n ordered: boolean,\n depth: number,\n): string {\n const parts: string[] = [];\n for (const child of item.children) {\n if (child.type === 'paragraph') {\n const runs = convertInlines(child.children, ctx);\n const bullet = ordered ? `<a:buAutoNum type=\"arabicPeriod\"/>` : `<a:buChar char=\"\\u2022\"/>`;\n const indent = 457200 * (depth + 1);\n parts.push(\n `<a:p>` +\n `<a:pPr lvl=\"${depth}\" marL=\"${indent}\" indent=\"-228600\">` +\n bullet +\n `</a:pPr>` +\n runs +\n `</a:p>`,\n );\n } else if (child.type === 'list') {\n parts.push(convertList(child, ctx, depth + 1));\n } else {\n parts.push(convertBlock(child, ctx, depth));\n }\n }\n return parts.join('');\n}\n\nfunction convertCodeBlock(node: MarkdownCodeBlock, ctx: SlideContext): string {\n const lines = node.value.split('\\n');\n const parts: string[] = [];\n for (const line of lines) {\n parts.push(\n `<a:p>` +\n `<a:r>` +\n `<a:rPr lang=\"en-US\" sz=\"${DEFAULT_CODE_SIZE}\" dirty=\"0\">` +\n `<a:latin typeface=\"${escapeXml(ctx.style.codeFont)}\"/>` +\n `<a:solidFill><a:srgbClr val=\"${ctx.style.codeColor}\"/></a:solidFill>` +\n `</a:rPr>` +\n `<a:t>${escapeXml(line || ' ')}</a:t>` +\n `</a:r>` +\n `</a:p>`,\n );\n }\n return parts.join('');\n}\n\nfunction convertTable(node: MarkdownTable, ctx: SlideContext): string {\n const parts: string[] = [];\n for (let ri = 0; ri < node.children.length; ri++) {\n const row = node.children[ri];\n parts.push(convertTableRow(row, ctx, ri === 0));\n }\n return parts.join('');\n}\n\nfunction convertTableRow(row: MarkdownTableRow, ctx: SlideContext, isHeader: boolean): string {\n const cells: string[] = [];\n for (const cell of row.children) {\n cells.push(extractPlainText(cell.children));\n }\n const text = cells.join(' | ');\n const format: InlineFormat = isHeader ? { bold: true } : {};\n return `<a:p>${makeRun(text, format, ctx.style)}</a:p>`;\n}\n\nfunction convertThematicBreak(ctx: SlideContext): string {\n return `<a:p><a:pPr><a:spcAft><a:spcPts val=\"1200\"/></a:spcAft></a:pPr><a:r><a:rPr lang=\"en-US\" sz=\"400\"><a:solidFill><a:srgbClr val=\"${ctx.style.mutedColor}\"/></a:solidFill></a:rPr><a:t>———</a:t></a:r></a:p>`;\n}\n\nfunction convertHtmlBlock(node: MarkdownHtmlBlock, ctx: SlideContext): string {\n const text = stripHtmlTags(node.rawHtml).trim();\n if (!text) return '';\n return `<a:p>${makeRun(text, {}, ctx.style)}</a:p>`;\n}\n\nfunction convertMathBlock(node: MarkdownMathBlock): string {\n return (\n `<a:p>` +\n `<a:pPr algn=\"ctr\"/>` +\n `<a:r>` +\n `<a:rPr lang=\"en-US\" i=\"1\">` +\n `<a:latin typeface=\"Cambria Math\"/>` +\n `</a:rPr>` +\n `<a:t>${escapeXml(node.value)}</a:t>` +\n `</a:r>` +\n `</a:p>`\n );\n}\n\n// ============================================\n// Inline Conversion (DrawingML runs)\n// ============================================\n\ninterface InlineFormat {\n bold?: boolean;\n italic?: boolean;\n strike?: boolean;\n code?: boolean;\n}\n\nfunction convertInlines(\n nodes: MarkdownInlineNode[],\n ctx: SlideContext,\n format: InlineFormat = {},\n): string {\n const parts: string[] = [];\n for (const node of nodes) {\n parts.push(convertInline(node, ctx, format));\n }\n return parts.join('');\n}\n\nfunction convertInline(node: MarkdownInlineNode, ctx: SlideContext, format: InlineFormat): string {\n switch (node.type) {\n case 'text':\n return makeRun(node.value, format, ctx.style);\n case 'strong':\n return convertInlines(node.children, ctx, { ...format, bold: true });\n case 'emphasis':\n return convertInlines(node.children, ctx, { ...format, italic: true });\n case 'delete':\n return convertInlines(node.children, ctx, { ...format, strike: true });\n case 'inlineCode':\n return makeRun(node.value, { ...format, code: true }, ctx.style);\n case 'link':\n return convertLink(node, ctx, format);\n case 'image':\n return convertImage(node, format, ctx);\n case 'break':\n return `<a:br/>`;\n case 'htmlInline':\n return makeRun(stripHtmlTags(node.rawHtml), format, ctx.style);\n case 'inlineMath':\n return makeRun(node.value, { ...format, code: true }, ctx.style);\n default:\n return '';\n }\n}\n\nfunction makeRun(text: string, format: InlineFormat, style: SlideStyle): string {\n if (!text) return '';\n\n const rPrParts: string[] = [`lang=\"en-US\"`, `dirty=\"0\"`];\n\n if (format.bold) rPrParts.push(`b=\"1\"`);\n if (format.italic) rPrParts.push(`i=\"1\"`);\n if (format.strike) rPrParts.push(`strike=\"sngStrike\"`);\n\n let innerParts = '';\n\n if (format.code) {\n innerParts += `<a:latin typeface=\"${escapeXml(style.codeFont)}\"/>`;\n innerParts += `<a:solidFill><a:srgbClr val=\"${style.codeColor}\"/></a:solidFill>`;\n rPrParts.push(`sz=\"${DEFAULT_CODE_SIZE}\"`);\n } else if (style.hasTheme) {\n innerParts += `<a:solidFill><a:srgbClr val=\"${style.text}\"/></a:solidFill>`;\n }\n\n return (\n `<a:r>` +\n `<a:rPr ${rPrParts.join(' ')}>${innerParts}</a:rPr>` +\n `<a:t>${escapeXml(text)}</a:t>` +\n `</a:r>`\n );\n}\n\nfunction convertLink(node: MarkdownLink, ctx: SlideContext, format: InlineFormat): string {\n const rId = ctx.addHyperlink(node.url);\n const parts: string[] = [];\n\n for (const child of node.children) {\n if (child.type === 'text') {\n parts.push(makeHyperlinkRun(child.value, rId, format));\n } else {\n parts.push(convertInline(child, ctx, format));\n }\n }\n\n return parts.join('');\n}\n\nfunction makeHyperlinkRun(text: string, rId: string, format: InlineFormat): string {\n if (!text) return '';\n\n const rPrParts: string[] = [`lang=\"en-US\"`, `dirty=\"0\"`];\n if (format.bold) rPrParts.push(`b=\"1\"`);\n if (format.italic) rPrParts.push(`i=\"1\"`);\n\n return (\n `<a:r>` +\n `<a:rPr ${rPrParts.join(' ')}>` +\n `<a:solidFill><a:srgbClr val=\"${HYPERLINK_COLOR}\"/></a:solidFill>` +\n `<a:hlinkClick r:id=\"${rId}\"/>` +\n `</a:rPr>` +\n `<a:t>${escapeXml(text)}</a:t>` +\n `</a:r>`\n );\n}\n\nfunction convertImage(node: MarkdownImage, format: InlineFormat, ctx: SlideContext): string {\n // For inline images (not image-only paragraphs), try to embed\n if (ctx.images) {\n const data = ctx.images.get(node.url);\n if (data) {\n // Register for rendering as a shape; return empty text\n ctx.addImage(node.url, data, node.alt || '');\n return '';\n }\n }\n // Fallback: placeholder text\n const alt = node.alt || node.url;\n return makeRun(`[Image: ${alt}]`, { ...format, italic: true }, ctx.style);\n}\n\n// ============================================\n// Package Assembly\n// ============================================\n\nasync function buildPptxPackage(\n slideXmls: string[],\n slideContexts: SlideContext[],\n options: PptxExportOptions,\n): Promise<ArrayBuffer> {\n const pkg = createPackage();\n const slideCount = slideXmls.length;\n\n const slideMasterRelId = 'rId100';\n const themeRelId = 'rId101';\n const slideRelIds: string[] = [];\n\n for (let i = 0; i < slideCount; i++) {\n slideRelIds.push(`rId${i + 1}`);\n }\n\n // --- ppt/presentation.xml ---\n const presentationXml = buildPresentationXml(\n slideCount,\n slideRelIds,\n slideMasterRelId,\n themeRelId,\n );\n pkg.addPart('ppt/presentation.xml', presentationXml, CONTENT_TYPE_PPTX_PRESENTATION);\n\n // --- Slides ---\n for (let i = 0; i < slideCount; i++) {\n const slidePath = `ppt/slides/slide${i + 1}.xml`;\n pkg.addPart(slidePath, slideXmls[i], CONTENT_TYPE_PPTX_SLIDE);\n\n pkg.addRelationship(slidePath, {\n id: 'rId1',\n type: REL_SLIDE_LAYOUT,\n target: '../slideLayouts/slideLayout1.xml',\n });\n\n // Per-slide relationships (hyperlinks + images)\n const ctx = slideContexts[i];\n for (const rel of ctx.relationships) {\n pkg.addRelationship(slidePath, {\n id: rel.id,\n type: rel.type,\n target: rel.target,\n ...(rel.targetMode ? { targetMode: rel.targetMode } : {}),\n });\n }\n\n // Embed image binary parts\n for (const img of ctx.embeddedImages) {\n pkg.addBinaryPart(img.mediaPath, img.data, img.contentType);\n }\n }\n\n // --- Slide layout ---\n const layoutMasterRelId = 'rId1';\n const slideLayoutXml = buildSlideLayoutXml(layoutMasterRelId);\n pkg.addPart('ppt/slideLayouts/slideLayout1.xml', slideLayoutXml, CONTENT_TYPE_PPTX_SLIDE_LAYOUT);\n pkg.addRelationship('ppt/slideLayouts/slideLayout1.xml', {\n id: layoutMasterRelId,\n type: REL_SLIDE_MASTER,\n target: '../slideMasters/slideMaster1.xml',\n });\n\n // --- Slide master ---\n const masterLayoutRelId = 'rId1';\n const masterThemeRelId = 'rId2';\n const slideMasterXml = buildSlideMasterXml(masterLayoutRelId);\n pkg.addPart('ppt/slideMasters/slideMaster1.xml', slideMasterXml, CONTENT_TYPE_PPTX_SLIDE_MASTER);\n pkg.addRelationship('ppt/slideMasters/slideMaster1.xml', {\n id: masterLayoutRelId,\n type: REL_SLIDE_LAYOUT,\n target: '../slideLayouts/slideLayout1.xml',\n });\n pkg.addRelationship('ppt/slideMasters/slideMaster1.xml', {\n id: masterThemeRelId,\n type: REL_THEME,\n target: '../theme/theme1.xml',\n });\n\n // --- Theme ---\n const themeXml = buildThemeXml();\n pkg.addPart('ppt/theme/theme1.xml', themeXml, CONTENT_TYPE_PPTX_THEME);\n\n // --- Root relationship ---\n pkg.addRelationship('', {\n id: 'rId1',\n type: REL_OFFICE_DOCUMENT,\n target: 'ppt/presentation.xml',\n });\n\n // --- Presentation relationships ---\n for (let i = 0; i < slideCount; i++) {\n pkg.addRelationship('ppt/presentation.xml', {\n id: slideRelIds[i],\n type: REL_SLIDE,\n target: `slides/slide${i + 1}.xml`,\n });\n }\n pkg.addRelationship('ppt/presentation.xml', {\n id: slideMasterRelId,\n type: REL_SLIDE_MASTER,\n target: 'slideMasters/slideMaster1.xml',\n });\n pkg.addRelationship('ppt/presentation.xml', {\n id: themeRelId,\n type: REL_THEME,\n target: 'theme/theme1.xml',\n });\n\n // --- Core properties ---\n if (options.title || options.author || options.description) {\n pkg.setCoreProperties({\n title: options.title,\n creator: options.author,\n description: options.description,\n created: new Date().toISOString(),\n modified: new Date().toISOString(),\n });\n }\n\n return pkg.toArrayBuffer();\n}\n\n// ============================================\n// Helpers\n// ============================================\n\nfunction stripHtmlTags(html: string): string {\n return html.replace(/<[^>]*>/g, '');\n}\n\nfunction inferExtension(path: string): string {\n const dot = path.lastIndexOf('.');\n if (dot === -1) return 'png';\n const ext = path\n .substring(dot + 1)\n .toLowerCase()\n .split('?')[0];\n return ext || 'png';\n}\n\nfunction inferMimeType(ext: string): string {\n const mimeTypes: Record<string, string> = {\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n svg: 'image/svg+xml',\n bmp: 'image/bmp',\n avif: 'image/avif',\n };\n return mimeTypes[ext] || 'image/png';\n}\n","/**\n * PPTX Constants & Style Definitions\n *\n * Shared constants for PPTX export: slide dimensions, text box positioning,\n * font sizes, and unit conversion helpers. All dimensions are in EMU\n * (English Metric Units) unless otherwise noted.\n *\n * 1 inch = 914400 EMU\n * 1 point = 12700 EMU\n * Font sizes in PPTX are in hundredths of a point (centi-points).\n */\n\n// ============================================\n// Slide Dimensions (EMU)\n// ============================================\n\n/** Widescreen slide width: 10 inches */\nexport const SLIDE_WIDTH = 9144000;\n\n/** Widescreen slide height: 7.5 inches */\nexport const SLIDE_HEIGHT = 6858000;\n\n// ============================================\n// Title Shape Positioning (EMU)\n// ============================================\n\n/** Title shape left offset: 0.5 inches */\nexport const TITLE_LEFT = 457200;\n\n/** Title shape top offset: 0.3 inches */\nexport const TITLE_TOP = 274638;\n\n/** Title shape width: 9 inches */\nexport const TITLE_WIDTH = 8229600;\n\n/** Title shape height: 1.25 inches */\nexport const TITLE_HEIGHT = 1143000;\n\n// ============================================\n// Body Shape Positioning (EMU)\n// ============================================\n\n/** Body shape left offset: 0.5 inches */\nexport const BODY_LEFT = 457200;\n\n/** Body shape top offset: 1.75 inches */\nexport const BODY_TOP = 1600200;\n\n/** Body shape width: 9 inches */\nexport const BODY_WIDTH = 8229600;\n\n/** Body shape height: 4.95 inches */\nexport const BODY_HEIGHT = 4525963;\n\n// ============================================\n// Default Fonts & Sizes\n// ============================================\n\n/** Default font for body text */\nexport const DEFAULT_FONT = 'Calibri';\n\n/** Default font for titles */\nexport const DEFAULT_TITLE_FONT = 'Calibri Light';\n\n/** Default font for code blocks */\nexport const DEFAULT_CODE_FONT = 'Consolas';\n\n/** Default title font size in centi-points (44pt) */\nexport const DEFAULT_TITLE_SIZE = 4400;\n\n/** Default body font size in centi-points (18pt) */\nexport const DEFAULT_BODY_SIZE = 1800;\n\n/** Default code font size in centi-points (14pt) */\nexport const DEFAULT_CODE_SIZE = 1400;\n\n/** Hyperlink color (standard blue) */\nexport const HYPERLINK_COLOR = '0563C1';\n\n// ============================================\n// Unit Helpers\n// ============================================\n\n/**\n * Convert inches to EMUs.\n */\nexport function inchesToEmu(inches: number): number {\n return Math.round(inches * 914400);\n}\n\n/**\n * Convert points to centi-points (PPTX font size unit).\n */\nexport function pointsToCentiPoints(points: number): number {\n return Math.round(points * 100);\n}\n","/**\n * PPTX Boilerplate Templates\n *\n * Minimal but valid XML templates for the required PPTX support parts:\n * slide master, slide layout, and theme. These are semi-static — they\n * don't change per-document but are required for PowerPoint to open the file.\n */\n\nimport { xmlDeclaration } from '../ooxml/xmlUtils.js';\nimport { NS_PML, NS_DRAWINGML, NS_R } from '../ooxml/namespaces.js';\nimport {\n SLIDE_WIDTH,\n SLIDE_HEIGHT,\n TITLE_LEFT,\n TITLE_TOP,\n TITLE_WIDTH,\n TITLE_HEIGHT,\n BODY_LEFT,\n BODY_TOP,\n BODY_WIDTH,\n BODY_HEIGHT,\n} from './styles.js';\n\n/**\n * Build presentation.xml — the root document listing all slides.\n */\nexport function buildPresentationXml(\n slideCount: number,\n slideRelIds: string[],\n slideMasterRelId: string,\n _themeRelId: string,\n): string {\n const sldIdList: string[] = [];\n for (let i = 0; i < slideCount; i++) {\n // Slide IDs start at 256 (PowerPoint convention)\n sldIdList.push(`<p:sldId id=\"${256 + i}\" r:id=\"${slideRelIds[i]}\"/>`);\n }\n\n return (\n xmlDeclaration() +\n `<p:presentation xmlns:a=\"${NS_DRAWINGML}\" xmlns:r=\"${NS_R}\" xmlns:p=\"${NS_PML}\"` +\n ` saveSubsetFonts=\"1\">` +\n `<p:sldMasterIdLst>` +\n `<p:sldMasterId id=\"2147483648\" r:id=\"${slideMasterRelId}\"/>` +\n `</p:sldMasterIdLst>` +\n `<p:sldIdLst>${sldIdList.join('')}</p:sldIdLst>` +\n `<p:sldSz cx=\"${SLIDE_WIDTH}\" cy=\"${SLIDE_HEIGHT}\" type=\"screen4x3\"/>` +\n `<p:notesSz cx=\"${SLIDE_HEIGHT}\" cy=\"${SLIDE_WIDTH}\"/>` +\n `</p:presentation>`\n );\n}\n\n/**\n * Build a minimal slide master (slideMaster1.xml).\n */\nexport function buildSlideMasterXml(layoutRelId: string): string {\n return (\n xmlDeclaration() +\n `<p:sldMaster xmlns:a=\"${NS_DRAWINGML}\" xmlns:r=\"${NS_R}\" xmlns:p=\"${NS_PML}\">` +\n `<p:cSld>` +\n `<p:bg>` +\n `<p:bgRef idx=\"1001\">` +\n `<a:schemeClr val=\"bg1\"/>` +\n `</p:bgRef>` +\n `</p:bg>` +\n `<p:spTree>` +\n `<p:nvGrpSpPr><p:cNvPr id=\"1\" name=\"\"/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr>` +\n `<p:grpSpPr/>` +\n `</p:spTree>` +\n `</p:cSld>` +\n `<p:clrMap bg1=\"lt1\" tx1=\"dk1\" bg2=\"lt2\" tx2=\"dk2\"` +\n ` accent1=\"accent1\" accent2=\"accent2\" accent3=\"accent3\" accent4=\"accent4\"` +\n ` accent5=\"accent5\" accent6=\"accent6\" hlink=\"hlink\" folHlink=\"folHlink\"/>` +\n `<p:sldLayoutIdLst>` +\n `<p:sldLayoutId id=\"2147483649\" r:id=\"${layoutRelId}\"/>` +\n `</p:sldLayoutIdLst>` +\n `</p:sldMaster>`\n );\n}\n\n/**\n * Build a minimal slide layout (slideLayout1.xml) — title + content.\n */\nexport function buildSlideLayoutXml(_masterRelId: string): string {\n return (\n xmlDeclaration() +\n `<p:sldLayout xmlns:a=\"${NS_DRAWINGML}\" xmlns:r=\"${NS_R}\" xmlns:p=\"${NS_PML}\"` +\n ` type=\"obj\" preserve=\"1\">` +\n `<p:cSld name=\"Title and Content\">` +\n `<p:spTree>` +\n `<p:nvGrpSpPr><p:cNvPr id=\"1\" name=\"\"/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr>` +\n `<p:grpSpPr/>` +\n // Title placeholder\n `<p:sp>` +\n `<p:nvSpPr>` +\n `<p:cNvPr id=\"2\" name=\"Title 1\"/>` +\n `<p:cNvSpPr><a:spLocks noGrp=\"1\"/></p:cNvSpPr>` +\n `<p:nvPr><p:ph type=\"title\"/></p:nvPr>` +\n `</p:nvSpPr>` +\n `<p:spPr>` +\n `<a:xfrm><a:off x=\"${TITLE_LEFT}\" y=\"${TITLE_TOP}\"/>` +\n `<a:ext cx=\"${TITLE_WIDTH}\" cy=\"${TITLE_HEIGHT}\"/></a:xfrm>` +\n `</p:spPr>` +\n `<p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:endParaRPr lang=\"en-US\"/></a:p></p:txBody>` +\n `</p:sp>` +\n // Content placeholder\n `<p:sp>` +\n `<p:nvSpPr>` +\n `<p:cNvPr id=\"3\" name=\"Content 2\"/>` +\n `<p:cNvSpPr><a:spLocks noGrp=\"1\"/></p:cNvSpPr>` +\n `<p:nvPr><p:ph idx=\"1\"/></p:nvPr>` +\n `</p:nvSpPr>` +\n `<p:spPr>` +\n `<a:xfrm><a:off x=\"${BODY_LEFT}\" y=\"${BODY_TOP}\"/>` +\n `<a:ext cx=\"${BODY_WIDTH}\" cy=\"${BODY_HEIGHT}\"/></a:xfrm>` +\n `</p:spPr>` +\n `<p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:endParaRPr lang=\"en-US\"/></a:p></p:txBody>` +\n `</p:sp>` +\n `</p:spTree>` +\n `</p:cSld>` +\n `</p:sldLayout>`\n );\n}\n\n/**\n * Build a minimal DrawingML theme (theme1.xml).\n */\nexport function buildThemeXml(): string {\n return (\n xmlDeclaration() +\n `<a:theme xmlns:a=\"${NS_DRAWINGML}\" name=\"Office Theme\">` +\n `<a:themeElements>` +\n // Color scheme\n `<a:clrScheme name=\"Office\">` +\n `<a:dk1><a:sysClr val=\"windowText\" lastClr=\"000000\"/></a:dk1>` +\n `<a:lt1><a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1>` +\n `<a:dk2><a:srgbClr val=\"44546A\"/></a:dk2>` +\n `<a:lt2><a:srgbClr val=\"E7E6E6\"/></a:lt2>` +\n `<a:accent1><a:srgbClr val=\"4472C4\"/></a:accent1>` +\n `<a:accent2><a:srgbClr val=\"ED7D31\"/></a:accent2>` +\n `<a:accent3><a:srgbClr val=\"A5A5A5\"/></a:accent3>` +\n `<a:accent4><a:srgbClr val=\"FFC000\"/></a:accent4>` +\n `<a:accent5><a:srgbClr val=\"5B9BD5\"/></a:accent5>` +\n `<a:accent6><a:srgbClr val=\"70AD47\"/></a:accent6>` +\n `<a:hlink><a:srgbClr val=\"0563C1\"/></a:hlink>` +\n `<a:folHlink><a:srgbClr val=\"954F72\"/></a:folHlink>` +\n `</a:clrScheme>` +\n // Font scheme\n `<a:fontScheme name=\"Office\">` +\n `<a:majorFont>` +\n `<a:latin typeface=\"Calibri Light\"/>` +\n `<a:ea typeface=\"\"/>` +\n `<a:cs typeface=\"\"/>` +\n `</a:majorFont>` +\n `<a:minorFont>` +\n `<a:latin typeface=\"Calibri\"/>` +\n `<a:ea typeface=\"\"/>` +\n `<a:cs typeface=\"\"/>` +\n `</a:minorFont>` +\n `</a:fontScheme>` +\n // Format scheme (minimal)\n `<a:fmtScheme name=\"Office\">` +\n `<a:fillStyleLst>` +\n `<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>` +\n `<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>` +\n `<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>` +\n `</a:fillStyleLst>` +\n `<a:lnStyleLst>` +\n `<a:ln w=\"6350\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill></a:ln>` +\n `<a:ln w=\"6350\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill></a:ln>` +\n `<a:ln w=\"6350\"><a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill></a:ln>` +\n `</a:lnStyleLst>` +\n `<a:effectStyleLst>` +\n `<a:effectStyle><a:effectLst/></a:effectStyle>` +\n `<a:effectStyle><a:effectLst/></a:effectStyle>` +\n `<a:effectStyle><a:effectLst/></a:effectStyle>` +\n `</a:effectStyleLst>` +\n `<a:bgFillStyleLst>` +\n `<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>` +\n `<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>` +\n `<a:solidFill><a:schemeClr val=\"phClr\"/></a:solidFill>` +\n `</a:bgFillStyleLst>` +\n `</a:fmtScheme>` +\n `</a:themeElements>` +\n `</a:theme>`\n );\n}\n","/**\n * @bendyline/squisq-formats PPTX Module\n *\n * PowerPoint .pptx export support using PresentationML (`<p:presentation>`,\n * `<p:sld>`) via the shared ooxml/ infrastructure.\n *\n * Slide segmentation: each H1/H2 heading starts a new slide by default.\n * Inline formatting (bold, italic, code, links) is preserved as DrawingML runs.\n *\n * Import is not yet implemented.\n *\n * @example\n * ```ts\n * import { markdownDocToPptx } from '@bendyline/squisq-formats/pptx';\n * ```\n */\n\n// Export\nexport { markdownDocToPptx, docToPptx } from './export.js';\nexport type { PptxExportOptions } from './export.js';\n\n// Import (stubs — not yet implemented)\nimport type { MarkdownDocument } from '@bendyline/squisq/markdown';\nimport type { Doc } from '@bendyline/squisq/schemas';\n\n/**\n * Options for PPTX import (placeholder).\n */\nexport interface PptxImportOptions {\n /** Whether to extract embedded images as data URIs */\n extractImages?: boolean;\n}\n\n/**\n * Convert a .pptx file to a MarkdownDocument.\n *\n * @throws Error — PPTX import is not yet implemented\n */\nexport async function pptxToMarkdownDoc(\n _data: ArrayBuffer | Blob,\n _options?: PptxImportOptions,\n): Promise<MarkdownDocument> {\n throw new Error('PPTX import is not yet implemented');\n}\n\n/**\n * Convert a .pptx file to a squisq Doc.\n *\n * @throws Error — PPTX import is not yet implemented\n */\nexport async function pptxToDoc(\n _data: ArrayBuffer | Blob,\n _options?: PptxImportOptions,\n): Promise<Doc> {\n throw new Error('PPTX import is not yet implemented');\n}\n"],"mappings":"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","names":[]}
@@ -1,120 +0,0 @@
1
- import {
2
- NS_CORE_PROPERTIES,
3
- NS_DC,
4
- NS_DCTERMS,
5
- NS_RELATIONSHIPS
6
- } from "./chunk-7DEUGIOO.js";
7
-
8
- // src/ooxml/reader.ts
9
- import JSZip from "jszip";
10
- async function openPackage(data) {
11
- const zip = await JSZip.loadAsync(data);
12
- const contentTypes = await parseContentTypes(zip);
13
- const rootRelationships = await parseRelationships(zip, "");
14
- return { zip, contentTypes, rootRelationships };
15
- }
16
- async function parseContentTypes(zip) {
17
- const overrides = /* @__PURE__ */ new Map();
18
- const defaults = /* @__PURE__ */ new Map();
19
- const file = zip.file("[Content_Types].xml");
20
- if (!file) return { overrides, defaults };
21
- const text = await file.async("text");
22
- const doc = new DOMParser().parseFromString(text, "application/xml");
23
- const defaultEls = doc.getElementsByTagName("Default");
24
- for (let i = 0; i < defaultEls.length; i++) {
25
- const el = defaultEls[i];
26
- const ext = el.getAttribute("Extension");
27
- const ct = el.getAttribute("ContentType");
28
- if (ext && ct) defaults.set(ext, ct);
29
- }
30
- const overrideEls = doc.getElementsByTagName("Override");
31
- for (let i = 0; i < overrideEls.length; i++) {
32
- const el = overrideEls[i];
33
- const partName = el.getAttribute("PartName");
34
- const ct = el.getAttribute("ContentType");
35
- if (partName && ct) {
36
- overrides.set(partName.replace(/^\//, ""), ct);
37
- }
38
- }
39
- return { overrides, defaults };
40
- }
41
- async function getPartRelationships(pkg, partPath) {
42
- return parseRelationships(pkg.zip, partPath);
43
- }
44
- async function parseRelationships(zip, partPath) {
45
- const relsPath = partPath === "" ? "_rels/.rels" : buildRelsPath(partPath);
46
- const file = zip.file(relsPath);
47
- if (!file) return [];
48
- const text = await file.async("text");
49
- const doc = new DOMParser().parseFromString(text, "application/xml");
50
- const result = [];
51
- const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, "Relationship");
52
- const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName("Relationship");
53
- for (let i = 0; i < fallbackEls.length; i++) {
54
- const el = fallbackEls[i];
55
- const id = el.getAttribute("Id");
56
- const type = el.getAttribute("Type");
57
- const target = el.getAttribute("Target");
58
- if (id && type && target) {
59
- const targetMode = el.getAttribute("TargetMode");
60
- result.push({
61
- id,
62
- type,
63
- target,
64
- ...targetMode ? { targetMode } : {}
65
- });
66
- }
67
- }
68
- return result;
69
- }
70
- function buildRelsPath(partPath) {
71
- const lastSlash = partPath.lastIndexOf("/");
72
- if (lastSlash === -1) {
73
- return `_rels/${partPath}.rels`;
74
- }
75
- const dir = partPath.substring(0, lastSlash);
76
- const file = partPath.substring(lastSlash + 1);
77
- return `${dir}/_rels/${file}.rels`;
78
- }
79
- async function getPartXml(pkg, partPath) {
80
- const file = pkg.zip.file(partPath);
81
- if (!file) return null;
82
- const text = await file.async("text");
83
- return new DOMParser().parseFromString(text, "application/xml");
84
- }
85
- async function getPartBinary(pkg, partPath) {
86
- const file = pkg.zip.file(partPath);
87
- if (!file) return null;
88
- return file.async("arraybuffer");
89
- }
90
- async function getCoreProperties(pkg) {
91
- const doc = await getPartXml(pkg, "docProps/core.xml");
92
- if (!doc) return {};
93
- function getText(ns, localName) {
94
- const els = doc.getElementsByTagNameNS(ns, localName);
95
- if (els.length > 0 && els[0].textContent) {
96
- return els[0].textContent;
97
- }
98
- return void 0;
99
- }
100
- return {
101
- title: getText(NS_DC, "title"),
102
- subject: getText(NS_DC, "subject"),
103
- creator: getText(NS_DC, "creator"),
104
- description: getText(NS_DC, "description"),
105
- keywords: getText(NS_CORE_PROPERTIES, "keywords"),
106
- lastModifiedBy: getText(NS_CORE_PROPERTIES, "lastModifiedBy"),
107
- revision: getText(NS_CORE_PROPERTIES, "revision"),
108
- created: getText(NS_DCTERMS, "created"),
109
- modified: getText(NS_DCTERMS, "modified")
110
- };
111
- }
112
-
113
- export {
114
- openPackage,
115
- getPartRelationships,
116
- getPartXml,
117
- getPartBinary,
118
- getCoreProperties
119
- };
120
- //# sourceMappingURL=chunk-YN5HFCEW.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ooxml/reader.ts"],"sourcesContent":["/**\n * OOXML Package Reader\n *\n * Opens OOXML archives (.docx, .pptx, .xlsx) and parses their\n * structural metadata: [Content_Types].xml, relationships, and\n * core properties.\n *\n * Uses JSZip to unzip and the browser's DOMParser to parse XML.\n */\n\nimport JSZip from 'jszip';\nimport type { OoxmlPackage, ContentTypeMap, Relationship, CoreProperties } from './types.js';\nimport { NS_RELATIONSHIPS, NS_DC, NS_DCTERMS, NS_CORE_PROPERTIES } from './namespaces.js';\n\n// ============================================\n// Package Opening\n// ============================================\n\n/**\n * Open an OOXML package from raw data.\n *\n * Parses the ZIP archive, [Content_Types].xml, and root relationships.\n *\n * @param data - The raw .docx/.pptx/.xlsx file as ArrayBuffer or Blob\n * @returns A parsed OoxmlPackage\n */\nexport async function openPackage(data: ArrayBuffer | Blob): Promise<OoxmlPackage> {\n const zip = await JSZip.loadAsync(data);\n const contentTypes = await parseContentTypes(zip);\n const rootRelationships = await parseRelationships(zip, '');\n\n return { zip, contentTypes, rootRelationships };\n}\n\n// ============================================\n// Content Types\n// ============================================\n\n/**\n * Parse [Content_Types].xml from the archive.\n */\nasync function parseContentTypes(zip: JSZip): Promise<ContentTypeMap> {\n const overrides = new Map<string, string>();\n const defaults = new Map<string, string>();\n\n const file = zip.file('[Content_Types].xml');\n if (!file) return { overrides, defaults };\n\n const text = await file.async('text');\n const doc = new DOMParser().parseFromString(text, 'application/xml');\n\n // Parse <Default Extension=\"rels\" ContentType=\"...\" />\n const defaultEls = doc.getElementsByTagName('Default');\n for (let i = 0; i < defaultEls.length; i++) {\n const el = defaultEls[i];\n const ext = el.getAttribute('Extension');\n const ct = el.getAttribute('ContentType');\n if (ext && ct) defaults.set(ext, ct);\n }\n\n // Parse <Override PartName=\"/word/document.xml\" ContentType=\"...\" />\n const overrideEls = doc.getElementsByTagName('Override');\n for (let i = 0; i < overrideEls.length; i++) {\n const el = overrideEls[i];\n const partName = el.getAttribute('PartName');\n const ct = el.getAttribute('ContentType');\n if (partName && ct) {\n // Normalize: strip leading slash\n overrides.set(partName.replace(/^\\//, ''), ct);\n }\n }\n\n return { overrides, defaults };\n}\n\n// ============================================\n// Relationships\n// ============================================\n\n/**\n * Parse relationships for a specific part.\n *\n * @param pkg - The OOXML package (or the zip directly)\n * @param partPath - The part path (e.g., \"word/document.xml\").\n * Use \"\" for root-level relationships (_rels/.rels).\n * @returns Array of relationship entries\n */\nexport async function getPartRelationships(\n pkg: OoxmlPackage,\n partPath: string,\n): Promise<Relationship[]> {\n return parseRelationships(pkg.zip, partPath);\n}\n\n/**\n * Parse a _rels/*.rels file from the ZIP.\n *\n * For root relationships, relsPath = \"_rels/.rels\".\n * For part relationships, relsPath = \"<dir>/_rels/<filename>.rels\".\n */\nasync function parseRelationships(zip: JSZip, partPath: string): Promise<Relationship[]> {\n const relsPath = partPath === '' ? '_rels/.rels' : buildRelsPath(partPath);\n\n const file = zip.file(relsPath);\n if (!file) return [];\n\n const text = await file.async('text');\n const doc = new DOMParser().parseFromString(text, 'application/xml');\n const result: Relationship[] = [];\n\n const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, 'Relationship');\n // Fallback in case namespace isn't used (some generators omit it)\n const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName('Relationship');\n\n for (let i = 0; i < fallbackEls.length; i++) {\n const el = fallbackEls[i];\n const id = el.getAttribute('Id');\n const type = el.getAttribute('Type');\n const target = el.getAttribute('Target');\n if (id && type && target) {\n const targetMode = el.getAttribute('TargetMode') as 'Internal' | 'External' | null;\n result.push({\n id,\n type,\n target,\n ...(targetMode ? { targetMode } : {}),\n });\n }\n }\n\n return result;\n}\n\n/**\n * Build the _rels path for a given part path.\n *\n * \"word/document.xml\" → \"word/_rels/document.xml.rels\"\n * \"xl/workbook.xml\" → \"xl/_rels/workbook.xml.rels\"\n */\nfunction buildRelsPath(partPath: string): string {\n const lastSlash = partPath.lastIndexOf('/');\n if (lastSlash === -1) {\n return `_rels/${partPath}.rels`;\n }\n const dir = partPath.substring(0, lastSlash);\n const file = partPath.substring(lastSlash + 1);\n return `${dir}/_rels/${file}.rels`;\n}\n\n// ============================================\n// Part Access\n// ============================================\n\n/**\n * Extract an XML part from the package and parse it as a DOM Document.\n *\n * @param pkg - The OOXML package\n * @param partPath - Path within the archive (e.g., \"word/document.xml\")\n * @returns Parsed XML Document, or null if the part doesn't exist\n */\nexport async function getPartXml(pkg: OoxmlPackage, partPath: string): Promise<Document | null> {\n const file = pkg.zip.file(partPath);\n if (!file) return null;\n\n const text = await file.async('text');\n return new DOMParser().parseFromString(text, 'application/xml');\n}\n\n/**\n * Extract a binary part from the package (e.g., an image from word/media/).\n *\n * @param pkg - The OOXML package\n * @param partPath - Path within the archive\n * @returns The binary content, or null if the part doesn't exist\n */\nexport async function getPartBinary(\n pkg: OoxmlPackage,\n partPath: string,\n): Promise<ArrayBuffer | null> {\n const file = pkg.zip.file(partPath);\n if (!file) return null;\n return file.async('arraybuffer');\n}\n\n// ============================================\n// Core Properties\n// ============================================\n\n/**\n * Parse core document properties from docProps/core.xml.\n *\n * @param pkg - The OOXML package\n * @returns Parsed core properties (all fields optional)\n */\nexport async function getCoreProperties(pkg: OoxmlPackage): Promise<CoreProperties> {\n const doc = await getPartXml(pkg, 'docProps/core.xml');\n if (!doc) return {};\n\n function getText(ns: string, localName: string): string | undefined {\n const els = doc!.getElementsByTagNameNS(ns, localName);\n if (els.length > 0 && els[0].textContent) {\n return els[0].textContent;\n }\n return undefined;\n }\n\n return {\n title: getText(NS_DC, 'title'),\n subject: getText(NS_DC, 'subject'),\n creator: getText(NS_DC, 'creator'),\n description: getText(NS_DC, 'description'),\n keywords: getText(NS_CORE_PROPERTIES, 'keywords'),\n lastModifiedBy: getText(NS_CORE_PROPERTIES, 'lastModifiedBy'),\n revision: getText(NS_CORE_PROPERTIES, 'revision'),\n created: getText(NS_DCTERMS, 'created'),\n modified: getText(NS_DCTERMS, 'modified'),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/container/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnE;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/E;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,GACvC,OAAO,CAAC,sBAAsB,CAAC,CAgCjC"}