@bendyline/squisq-formats 2.1.0 → 2.2.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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +20 -0
  3. package/README.md +1 -1
  4. package/dist/{chunk-NNHKUXKA.js → chunk-26ISNJ7Y.js} +85 -65
  5. package/dist/{chunk-NKAJPJ4G.js → chunk-2JJ5RFDZ.js} +0 -1
  6. package/dist/{chunk-WQSHGBLN.js → chunk-3NKXBZSR.js} +193 -42
  7. package/dist/{chunk-KURGXM4I.js → chunk-4V3KCHAP.js} +3 -4
  8. package/dist/{chunk-MLX2BOJC.js → chunk-6RQOV3B3.js} +1 -2
  9. package/dist/{chunk-EW54IRRS.js → chunk-6S6GU3ZG.js} +5 -6
  10. package/dist/{chunk-FE6OJV6O.js → chunk-7AWFHP5U.js} +1 -1
  11. package/dist/{chunk-RFAPOKHJ.js → chunk-AD2WT564.js} +59 -9
  12. package/dist/{chunk-O3GVVND4.js → chunk-AONELFLA.js} +0 -1
  13. package/dist/{chunk-SC67HYQJ.js → chunk-EJTNGKEA.js} +5 -8
  14. package/dist/chunk-GX7RAUME.js +121 -0
  15. package/dist/{chunk-SSUPBUF5.js → chunk-IIQYS2YH.js} +0 -1
  16. package/dist/{chunk-RLU7UFYU.js → chunk-IPN56VLW.js} +83 -58
  17. package/dist/{chunk-DTDF6QDP.js → chunk-JE6LSIHE.js} +81 -20
  18. package/dist/{chunk-U4MRIFKL.js → chunk-JU2RHXUB.js} +0 -1
  19. package/dist/{chunk-4VUWTSGM.js → chunk-K6XRMVPW.js} +64 -31
  20. package/dist/{chunk-ODL3SSPT.js → chunk-KXOZMWBS.js} +0 -1
  21. package/dist/chunk-OGS5VCGJ.js +446 -0
  22. package/dist/{chunk-GVS2XXV6.js → chunk-PJXJI2LY.js} +449 -57
  23. package/dist/{chunk-74GO3FVS.js → chunk-PU7REGWV.js} +5 -8
  24. package/dist/{chunk-PN52A5AA.js → chunk-SBUW7NHR.js} +0 -1
  25. package/dist/{chunk-QFLDYKCR.js → chunk-TAAENIRB.js} +5 -8
  26. package/dist/{chunk-7ARKUCQT.js → chunk-X2DEAXNK.js} +54 -2
  27. package/dist/container/index.js +1 -2
  28. package/dist/csv/index.d.ts +27 -2
  29. package/dist/csv/index.js +1 -2
  30. package/dist/docx/index.d.ts +5 -1
  31. package/dist/docx/index.js +9 -11
  32. package/dist/epub/index.d.ts +2 -0
  33. package/dist/epub/index.js +5 -6
  34. package/dist/{export-D2NkylDT.d.ts → export-D9msROJS.d.ts} +18 -6
  35. package/dist/extract-MN7LA3NL.js +13 -0
  36. package/dist/html/index.d.ts +11 -4
  37. package/dist/html/index.js +3 -4
  38. package/dist/images-ESPQKVTW.js +6 -0
  39. package/dist/{import-K8mfc0fz.d.ts → import-C3htUTss.d.ts} +5 -1
  40. package/dist/{import-DTkDxHmZ.d.ts → import-C8whCC7_.d.ts} +6 -0
  41. package/dist/index.d.ts +7 -7
  42. package/dist/index.js +28 -26
  43. package/dist/infer/index.d.ts +3 -3
  44. package/dist/infer/index.js +7 -9
  45. package/dist/{layouts-BHrgZ5FS.d.ts → layouts-CTdPlB-u.d.ts} +1 -1
  46. package/dist/layouts-DRWZGSPD.js +10 -0
  47. package/dist/{mapTheme-IR27S6IV.js → mapTheme-4TWH25FT.js} +1 -2
  48. package/dist/ooxml/index.d.ts +3 -3
  49. package/dist/ooxml/index.js +14 -13
  50. package/dist/pdf/index.d.ts +18 -0
  51. package/dist/pdf/index.js +2 -3
  52. package/dist/pptx/index.d.ts +4 -4
  53. package/dist/pptx/index.js +11 -13
  54. package/dist/{reader-B9L8Ucbj.d.ts → reader-B_m1aKZC.d.ts} +30 -1
  55. package/dist/registry/index.d.ts +21 -5
  56. package/dist/registry/index.js +9 -6
  57. package/dist/{themeReader-DJKErl_j.d.ts → themeReader-DCtwC83Q.d.ts} +1 -1
  58. package/dist/xlsx/index.d.ts +3 -3
  59. package/dist/xlsx/index.js +6 -7
  60. package/package.json +6 -3
  61. package/dist/chunk-4VUWTSGM.js.map +0 -1
  62. package/dist/chunk-6M7Z25LA.js +0 -46
  63. package/dist/chunk-6M7Z25LA.js.map +0 -1
  64. package/dist/chunk-74GO3FVS.js.map +0 -1
  65. package/dist/chunk-7ARKUCQT.js.map +0 -1
  66. package/dist/chunk-DTDF6QDP.js.map +0 -1
  67. package/dist/chunk-EW54IRRS.js.map +0 -1
  68. package/dist/chunk-FE6OJV6O.js.map +0 -1
  69. package/dist/chunk-GVS2XXV6.js.map +0 -1
  70. package/dist/chunk-KURGXM4I.js.map +0 -1
  71. package/dist/chunk-MLX2BOJC.js.map +0 -1
  72. package/dist/chunk-NKAJPJ4G.js.map +0 -1
  73. package/dist/chunk-NNHKUXKA.js.map +0 -1
  74. package/dist/chunk-O3GVVND4.js.map +0 -1
  75. package/dist/chunk-ODL3SSPT.js.map +0 -1
  76. package/dist/chunk-PN52A5AA.js.map +0 -1
  77. package/dist/chunk-QFLDYKCR.js.map +0 -1
  78. package/dist/chunk-RFAPOKHJ.js.map +0 -1
  79. package/dist/chunk-RLU7UFYU.js.map +0 -1
  80. package/dist/chunk-SC67HYQJ.js.map +0 -1
  81. package/dist/chunk-SSUPBUF5.js.map +0 -1
  82. package/dist/chunk-U4MRIFKL.js.map +0 -1
  83. package/dist/chunk-UGYF5AZE.js +0 -275
  84. package/dist/chunk-UGYF5AZE.js.map +0 -1
  85. package/dist/chunk-WQSHGBLN.js.map +0 -1
  86. package/dist/chunk-YRT7GQ5Y.js +0 -28
  87. package/dist/chunk-YRT7GQ5Y.js.map +0 -1
  88. package/dist/container/index.js.map +0 -1
  89. package/dist/csv/index.js.map +0 -1
  90. package/dist/docx/index.js.map +0 -1
  91. package/dist/epub/index.js.map +0 -1
  92. package/dist/extract-OJ7ZQV6P.js +0 -15
  93. package/dist/extract-OJ7ZQV6P.js.map +0 -1
  94. package/dist/html/index.js.map +0 -1
  95. package/dist/images-7FBWPKE3.js +0 -7
  96. package/dist/images-7FBWPKE3.js.map +0 -1
  97. package/dist/index.js.map +0 -1
  98. package/dist/infer/index.js.map +0 -1
  99. package/dist/layouts-5VDIRPIJ.js +0 -12
  100. package/dist/layouts-5VDIRPIJ.js.map +0 -1
  101. package/dist/mapTheme-IR27S6IV.js.map +0 -1
  102. package/dist/ooxml/index.js.map +0 -1
  103. package/dist/pdf/index.js.map +0 -1
  104. package/dist/pptx/index.js.map +0 -1
  105. package/dist/registry/index.js.map +0 -1
  106. package/dist/xlsx/index.js.map +0 -1
  107. package/src/__tests__/container.test.ts +0 -230
  108. package/src/__tests__/convert.test.ts +0 -495
  109. package/src/__tests__/csvImport.test.ts +0 -84
  110. package/src/__tests__/docxExport.test.ts +0 -491
  111. package/src/__tests__/docxImport.test.ts +0 -531
  112. package/src/__tests__/epub.test.ts +0 -649
  113. package/src/__tests__/exportThemeReconciliation.test.ts +0 -87
  114. package/src/__tests__/formatRegistry.test.ts +0 -174
  115. package/src/__tests__/html.test.ts +0 -439
  116. package/src/__tests__/htmlImport.test.ts +0 -57
  117. package/src/__tests__/inferTheme.test.ts +0 -135
  118. package/src/__tests__/lossyWarnings.test.ts +0 -146
  119. package/src/__tests__/ooxml.test.ts +0 -271
  120. package/src/__tests__/ooxmlCancellation.test.ts +0 -113
  121. package/src/__tests__/ooxmlThemeReader.test.ts +0 -92
  122. package/src/__tests__/pdfExport.test.ts +0 -322
  123. package/src/__tests__/pdfImport.test.ts +0 -384
  124. package/src/__tests__/plainHtml.test.ts +0 -417
  125. package/src/__tests__/plainHtmlBundle.test.ts +0 -253
  126. package/src/__tests__/pptxExport.test.ts +0 -138
  127. package/src/__tests__/pptxImport.test.ts +0 -145
  128. package/src/__tests__/pptxInferFixtures.ts +0 -314
  129. package/src/__tests__/pptxLayoutInfer.test.ts +0 -395
  130. package/src/__tests__/roundTrip.test.ts +0 -201
  131. package/src/__tests__/roundTripAssets.test.ts +0 -50
  132. package/src/__tests__/roundTripMatrix.fixtures.ts +0 -86
  133. package/src/__tests__/roundTripMatrix.helpers.ts +0 -154
  134. package/src/__tests__/roundTripMatrix.test.ts +0 -142
  135. package/src/__tests__/sharedContainer.test.ts +0 -41
  136. package/src/__tests__/sharedImages.test.ts +0 -61
  137. package/src/__tests__/xlsxExport.test.ts +0 -164
  138. package/src/__tests__/xlsxImport.test.ts +0 -80
  139. package/src/__tests__/zipSafety.test.ts +0 -317
  140. package/src/container/index.ts +0 -94
  141. package/src/csv/index.ts +0 -188
  142. package/src/docx/export.ts +0 -1375
  143. package/src/docx/import.ts +0 -1250
  144. package/src/docx/index.ts +0 -26
  145. package/src/docx/styles.ts +0 -145
  146. package/src/epub/export.ts +0 -968
  147. package/src/epub/index.ts +0 -20
  148. package/src/html/docsHtmlBundle.ts +0 -373
  149. package/src/html/htmlTemplate.ts +0 -385
  150. package/src/html/imageUtils.ts +0 -61
  151. package/src/html/import.ts +0 -297
  152. package/src/html/index.ts +0 -212
  153. package/src/html/plainHtml.ts +0 -790
  154. package/src/html/plainHtmlBundle.ts +0 -421
  155. package/src/index.ts +0 -109
  156. package/src/infer/extract.ts +0 -127
  157. package/src/infer/index.ts +0 -199
  158. package/src/infer/mapTheme.ts +0 -176
  159. package/src/infer/types.ts +0 -27
  160. package/src/ooxml/index.ts +0 -111
  161. package/src/ooxml/namespaces.ts +0 -217
  162. package/src/ooxml/readUtils.ts +0 -44
  163. package/src/ooxml/reader.ts +0 -318
  164. package/src/ooxml/themeReader.ts +0 -197
  165. package/src/ooxml/types.ts +0 -103
  166. package/src/ooxml/writer.ts +0 -339
  167. package/src/ooxml/xmlUtils.ts +0 -123
  168. package/src/pdf/export.ts +0 -1084
  169. package/src/pdf/import.ts +0 -1164
  170. package/src/pdf/index.ts +0 -29
  171. package/src/pdf/styles.ts +0 -180
  172. package/src/pptx/export.ts +0 -1184
  173. package/src/pptx/import.ts +0 -455
  174. package/src/pptx/index.ts +0 -52
  175. package/src/pptx/layouts.ts +0 -1222
  176. package/src/pptx/styles.ts +0 -96
  177. package/src/pptx/templates.ts +0 -187
  178. package/src/registry/convert.ts +0 -433
  179. package/src/registry/defaultFormats.ts +0 -413
  180. package/src/registry/errors.ts +0 -46
  181. package/src/registry/index.ts +0 -43
  182. package/src/registry/registry.ts +0 -48
  183. package/src/registry/types.ts +0 -170
  184. package/src/shared/boundedZipArchive.ts +0 -383
  185. package/src/shared/container.ts +0 -28
  186. package/src/shared/fidelity.ts +0 -130
  187. package/src/shared/images.ts +0 -44
  188. package/src/shared/inlineRuns.ts +0 -99
  189. package/src/shared/text.ts +0 -41
  190. package/src/shared/zipEntryCount.ts +0 -151
  191. package/src/shared/zipLimits.ts +0 -296
  192. package/src/shared/zipSafety.ts +0 -19
  193. package/src/xlsx/export.ts +0 -253
  194. package/src/xlsx/import.ts +0 -160
  195. package/src/xlsx/index.ts +0 -35
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pptx/export.ts","../src/pptx/styles.ts","../src/pptx/templates.ts","../src/pptx/index.ts","../src/pptx/import.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, Transition, TransitionDirection } from '@bendyline/squisq/schemas';\nimport { resolveFontFamily } from '@bendyline/squisq/schemas';\nimport type { Theme, ThemeRegistry } from '@bendyline/squisq/schemas';\nimport { docToMarkdown, resolveThemeForDoc } 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 { inferMimeType } from '../html/imageUtils.js';\nimport { stripHtmlTags, extractPlainText } from '../shared/text.js';\nimport {\n inlineNodesToRuns,\n inlineNodeToRuns,\n type InlineRunHandlers,\n} from '../shared/inlineRuns.js';\nimport {\n NS_PML,\n NS_PML_2010,\n NS_DRAWINGML,\n NS_MC,\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 /** Explicit caller-owned registry for non-document custom themes. */\n themeRegistry?: ThemeRegistry;\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, doc);\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(\n themeId: string | undefined,\n options: PptxExportOptions,\n doc: MarkdownDocument,\n): 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 = resolveThemeForDoc(doc, themeId, options.themeRegistry);\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 transition?: Transition;\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 transition: node.attributes?.blockMeta?.transition,\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\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 const transitionXml = buildTransitionXml(slide.transition);\n const extensionAttrs = transitionXml.includes('p14:')\n ? ` xmlns:mc=\"${NS_MC}\" xmlns:p14=\"${NS_PML_2010}\" mc:Ignorable=\"p14\"`\n : '';\n\n return (\n xmlDeclaration() +\n `<p:sld xmlns:a=\"${NS_DRAWINGML}\" xmlns:r=\"${NS_R}\" xmlns:p=\"${NS_PML}\"${extensionAttrs}>` +\n `<p:cSld>` +\n bgXml +\n `<p:spTree>` +\n shapes.join('') +\n `</p:spTree>` +\n `</p:cSld>` +\n transitionXml +\n `</p:sld>`\n );\n}\n\ninterface TransitionXml {\n xml: string;\n}\n\nfunction buildTransitionXml(transition: Transition | undefined): string {\n if (!transition || transition.type === 'cut') return '';\n\n const child = buildTransitionChildXml(transition);\n const spd = pptxSpeedForDuration(transition.duration);\n return `<p:transition spd=\"${spd}\">${child.xml}</p:transition>`;\n}\n\nfunction buildTransitionChildXml(transition: Transition): TransitionXml {\n const type = transition.type;\n switch (type) {\n case 'fade':\n case 'morph':\n return p('fade');\n case 'dissolve':\n return p('dissolve');\n case 'push':\n return p('push', ` dir=\"${sideDir(transition.direction, 'left')}\"`);\n case 'slideLeft':\n return p('push', ` dir=\"l\"`);\n case 'slideRight':\n return p('push', ` dir=\"r\"`);\n case 'slideUp':\n return p('push', ` dir=\"u\"`);\n case 'slideDown':\n return p('push', ` dir=\"d\"`);\n case 'wipe':\n return p('wipe', ` dir=\"${sideDir(transition.direction, 'left')}\"`);\n case 'split':\n return p('split', ` orient=\"${orientation(transition.direction)}\" dir=\"out\"`);\n case 'randomBars':\n case 'randomBar':\n return p('randomBar', ` dir=\"${orientation(transition.direction)}\"`);\n case 'shape':\n case 'circle':\n return p('circle');\n case 'diamond':\n return p('diamond');\n case 'plus':\n return p('plus');\n case 'uncover':\n case 'pull':\n return p('pull', ` dir=\"${sideDir(transition.direction, 'left')}\"`);\n case 'cover':\n return p('cover', ` dir=\"${sideDir(transition.direction, 'left')}\"`);\n case 'checkerboard':\n case 'checker':\n return p('checker', ` dir=\"${orientation(transition.direction)}\"`);\n case 'blinds':\n return p('blinds', ` dir=\"${orientation(transition.direction)}\"`);\n case 'comb':\n return p('comb', ` dir=\"${orientation(transition.direction)}\"`);\n case 'clock':\n case 'wheel':\n return p('wheel', ` spokes=\"4\"`);\n case 'wheelReverse':\n return p14('wheelReverse');\n case 'newsflash':\n return p('newsflash');\n case 'random':\n return p('random');\n case 'strips':\n return p('strips', ` dir=\"${cornerDir(transition.direction)}\"`);\n case 'wedge':\n return p('wedge');\n case 'zoom':\n case 'box':\n return p('zoom', ` dir=\"${inOutDir(transition.direction, 'in')}\"`);\n case 'flash':\n return p14('flash');\n case 'vortex':\n case 'orbit':\n case 'rotate':\n return p14('vortex');\n case 'switch':\n case 'cube':\n return p14('switch');\n case 'flip':\n case 'fallOver':\n return p14('flip');\n case 'ripple':\n return p14('ripple');\n case 'glitter':\n case 'prestige':\n return p14('glitter');\n case 'honeycomb':\n return p14('honeycomb');\n case 'prism':\n return p14('prism');\n case 'doors':\n case 'drape':\n case 'curtains':\n return p14('doors');\n case 'window':\n return p14('window');\n case 'shred':\n case 'fracture':\n case 'crush':\n return p14('shred');\n case 'ferris':\n case 'ferrisWheel':\n return p14('ferris');\n case 'flythrough':\n case 'flyThrough':\n case 'airplane':\n case 'origami':\n return p14('flythrough');\n case 'warp':\n case 'pageCurl':\n case 'pageCurlDouble':\n case 'pageCurlSingle':\n case 'peelOff':\n return p14('warp');\n case 'gallery':\n return p14('gallery');\n case 'conveyor':\n return p14('conveyor');\n case 'pan':\n case 'wind':\n return p14('pan');\n case 'reveal':\n return p14('reveal');\n default:\n return p('fade');\n }\n}\n\nfunction p(tag: string, attrs: string = ''): TransitionXml {\n return { xml: `<p:${tag}${attrs}/>` };\n}\n\nfunction p14(tag: string, attrs: string = ''): TransitionXml {\n return { xml: `<p14:${tag}${attrs}/>` };\n}\n\nfunction pptxSpeedForDuration(duration: number | undefined): 'fast' | 'med' | 'slow' {\n if (duration != null && duration <= 0.5) return 'fast';\n if (duration != null && duration >= 1.2) return 'slow';\n return 'med';\n}\n\nfunction sideDir(\n direction: TransitionDirection | undefined,\n fallback: TransitionDirection,\n): string {\n switch (direction ?? fallback) {\n case 'right':\n return 'r';\n case 'up':\n return 'u';\n case 'down':\n return 'd';\n case 'left':\n default:\n return 'l';\n }\n}\n\nfunction cornerDir(direction: TransitionDirection | undefined): string {\n switch (direction) {\n case 'right':\n case 'down':\n return 'rd';\n case 'up':\n return 'lu';\n case 'left':\n default:\n return 'ld';\n }\n}\n\nfunction orientation(direction: TransitionDirection | undefined): string {\n return direction === 'vertical' || direction === 'up' || direction === 'down' ? 'vert' : 'horz';\n}\n\nfunction inOutDir(direction: TransitionDirection | undefined, fallback: 'in' | 'out'): string {\n return direction === 'out' ? 'out' : direction === 'in' ? 'in' : fallback;\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\n/**\n * PPTX leaf handlers for the shared run-based inline walker. The traversal\n * (format threading) lives in `shared/inlineRuns.ts`; these emit DrawingML.\n */\nfunction pptxRunHandlers(ctx: SlideContext): InlineRunHandlers {\n return {\n run: (text, format) => makeRun(text, format, ctx.style),\n link: (node, format) => convertLink(node, ctx, format),\n image: (node, format) => convertImage(node, format, ctx),\n lineBreak: () => `<a:br/>`,\n };\n}\n\nfunction convertInlines(\n nodes: MarkdownInlineNode[],\n ctx: SlideContext,\n format: InlineFormat = {},\n): string {\n return inlineNodesToRuns(nodes, pptxRunHandlers(ctx), format);\n}\n\nfunction convertInline(node: MarkdownInlineNode, ctx: SlideContext, format: InlineFormat): string {\n return inlineNodeToRuns(node, pptxRunHandlers(ctx), format);\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 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","/**\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 * Includes both export and import paths.\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\nimport { markdownToDoc } from '@bendyline/squisq/doc';\nimport type { Doc } from '@bendyline/squisq/schemas';\nimport { type PptxImportOptions, pptxToMarkdownDoc } from './import.js';\n\nexport type { PptxImportOptions } from './import.js';\nexport { pptxToMarkdownDoc, pptxToContainer } from './import.js';\n\n// Layout inference (used by the PPTX importer and the theme dialog)\nexport { analyzePptxLayouts, inspectPptxLayouts } from './layouts.js';\nexport type {\n AnalyzedLayout,\n AnalyzePptxLayoutsOptions,\n ExtractedPlaceholder,\n ExtractedSlideLayout,\n InspectPptxLayoutsOptions,\n LayoutVerdict,\n PptxColorHints,\n PptxLayoutInference,\n PptxLayoutSummary,\n} from './layouts.js';\n\n/**\n * Convert a .pptx file to a squisq Doc (via the markdown model).\n */\nexport async function pptxToDoc(\n data: ArrayBuffer | Blob,\n options?: PptxImportOptions,\n): Promise<Doc> {\n return markdownToDoc(await pptxToMarkdownDoc(data, options));\n}\n","/**\n * PPTX import — PresentationML (.pptx) → MarkdownDocument.\n *\n * Reuses the shared ooxml/ reader. Reads slide order from\n * `ppt/presentation.xml` (`<p:sldIdLst>`), resolves each slide part via\n * relationships, and converts each slide to: an H2 of the title placeholder\n * (or \"Slide N\"), the remaining text as a bullet list, and any slide tables\n * (`<a:tbl>`) as markdown tables. Text lives in the DrawingML namespace\n * (`a:p` / `a:r` / `a:t`) inside PresentationML shapes (`p:sp`).\n *\n * Theme + layout inference (default ON): the deck's theme part is compiled\n * into a Squisq custom theme and carried in the returned document's\n * frontmatter (`squisq-custom-themes` + `squisq-theme`); slide layouts are\n * classified against the built-in template set, distinctive ones become\n * `squisq-custom-templates` definitions, and each slide's heading is\n * annotated (`{[templateName …]}`) per its layout's verdict. Pass\n * `inferTheme: false` / `inferLayouts: false` for legacy plain imports.\n * Inference never fails an import — extraction errors degrade to plain\n * output with a console warning.\n */\n\nimport type {\n HeadingTemplateAnnotation,\n MarkdownBlockNode,\n MarkdownDocument,\n MarkdownImage,\n MarkdownListItem,\n MarkdownTable,\n MarkdownTableCell,\n MarkdownTableRow,\n} from '@bendyline/squisq/markdown';\nimport { stringifyMarkdown } from '@bendyline/squisq/markdown';\nimport type { CustomTemplateDefinition, Theme } from '@bendyline/squisq/schemas';\nimport { getPartBinary, getPartRelationships, getPartXml, openPackage } from '../ooxml/reader.js';\nimport type { OoxmlOpenOptions } from '../ooxml/reader.js';\nimport type { OoxmlPackage } from '../ooxml/types.js';\nimport { NS_DRAWINGML, NS_PML, NS_R } from '../ooxml/namespaces.js';\nimport { attrNS, baseDirOf, resolveTarget } from '../ooxml/readUtils.js';\nimport type { ContentContainer } from '@bendyline/squisq/storage';\nimport { buildContainer } from '../shared/container.js';\nimport { extToMime } from '../shared/images.js';\nimport type { ExtractedFileTheme } from '../infer/types.js';\nimport type { AnalyzedLayout, PptxLayoutInference } from './layouts.js';\n\nexport interface PptxImportOptions extends OoxmlOpenOptions {\n /**\n * Whether to extract embedded slide images into the document as image nodes\n * (referencing `images/imageN.ext`). When false, pictures are ignored so the\n * markdown never carries dangling image references with no backing container.\n * `pptxToContainer` forces this on. Default: false.\n */\n extractImages?: boolean;\n /**\n * Infer a Squisq theme from the deck's theme part (colors + fonts) and\n * carry it in the returned document's frontmatter (`squisq-custom-themes`\n * + `squisq-theme`). Default: true — pass false for a legacy import with\n * no frontmatter.\n */\n inferTheme?: boolean;\n /**\n * Derive custom layout templates from the deck's slide layouts/masters\n * (`squisq-custom-templates` frontmatter) and annotate slide headings\n * with matching built-in or generated templates. Default: true.\n */\n inferLayouts?: boolean;\n}\n\n/**\n * Per-import mutable state used to collect embedded images across slides.\n * Mirrors the docx import context's `extractedImages` / `imageCounter`.\n */\ninterface ImportContext {\n pkg: OoxmlPackage;\n extractImages: boolean;\n /** Collected image files: `images/imageN.ext` → { data, mimeType } */\n extractedImages: Map<string, { data: ArrayBuffer; mimeType: string }>;\n imageCounter: number;\n /** Layout analysis when `inferLayouts` is on. */\n inference?: PptxLayoutInference;\n /** Generated custom templates actually referenced by ≥1 slide annotation. */\n usedCustomTemplates: Map<string, CustomTemplateDefinition>;\n}\n\nasync function orderedSlidePaths(pkg: OoxmlPackage): Promise<string[]> {\n const pres = await getPartXml(pkg, 'ppt/presentation.xml');\n if (!pres) return [];\n const rels = await getPartRelationships(pkg, 'ppt/presentation.xml');\n const relById = new Map(rels.map((r) => [r.id, r.target]));\n const out: string[] = [];\n const ids = pres.getElementsByTagNameNS(NS_PML, 'sldId');\n for (let i = 0; i < ids.length; i++) {\n const rid = attrNS(ids[i]!, NS_R, 'id', 'r:id');\n const target = rid ? relById.get(rid) : undefined;\n if (target) out.push(resolveTarget('ppt', target));\n }\n return out;\n}\n\n/** Concatenate the DrawingML text runs (`a:t`) inside a paragraph element. */\nfunction paragraphText(para: Element): string {\n const ts = para.getElementsByTagNameNS(NS_DRAWINGML, 't');\n let s = '';\n for (let i = 0; i < ts.length; i++) s += ts[i]!.textContent ?? '';\n return s.trim();\n}\n\nfunction isTitleShape(sp: Element): boolean {\n const ph = sp.getElementsByTagNameNS(NS_PML, 'ph');\n if (!ph.length) return false;\n const type = ph[0]!.getAttribute('type');\n return type === 'title' || type === 'ctrTitle';\n}\n\nfunction tableToMarkdown(tbl: Element): MarkdownTable {\n const rows: MarkdownTableRow[] = [];\n const trs = tbl.getElementsByTagNameNS(NS_DRAWINGML, 'tr');\n for (let r = 0; r < trs.length; r++) {\n const tcs = trs[r]!.getElementsByTagNameNS(NS_DRAWINGML, 'tc');\n const cells: MarkdownTableCell[] = [];\n for (let c = 0; c < tcs.length; c++) {\n const paras = tcs[c]!.getElementsByTagNameNS(NS_DRAWINGML, 'p');\n const text = Array.from({ length: paras.length }, (_, i) => paragraphText(paras[i]!))\n .filter(Boolean)\n .join(' ');\n cells.push({\n type: 'tableCell',\n ...(r === 0 ? { isHeader: true } : {}),\n children: text ? [{ type: 'text', value: text }] : [],\n });\n }\n rows.push({ type: 'tableRow', children: cells });\n }\n return { type: 'table', children: rows };\n}\n\n/**\n * Extract every `<p:pic>` picture in a slide as an image node, reading the\n * `<a:blip r:embed>` relationship, resolving it to the media part, and copying\n * the bytes into `ctx.extractedImages` under `images/imageN.ext`.\n */\nasync function extractSlideImages(\n doc: Document,\n slidePath: string,\n ctx: ImportContext,\n): Promise<MarkdownImage[]> {\n const rels = await getPartRelationships(ctx.pkg, slidePath);\n const relById = new Map(rels.map((r) => [r.id, r.target]));\n const baseDir = baseDirOf(slidePath);\n\n const images: MarkdownImage[] = [];\n const pics = doc.getElementsByTagNameNS(NS_PML, 'pic');\n for (let i = 0; i < pics.length; i++) {\n const pic = pics[i]!;\n const blips = pic.getElementsByTagNameNS(NS_DRAWINGML, 'blip');\n if (!blips.length) continue;\n const embed = attrNS(blips[0]!, NS_R, 'embed', 'r:embed');\n if (!embed) continue;\n const target = relById.get(embed);\n if (!target) continue;\n\n const mediaPath = resolveTarget(baseDir, target);\n const data = await getPartBinary(ctx.pkg, mediaPath);\n if (!data) continue;\n\n const dot = mediaPath.lastIndexOf('.');\n const ext = dot !== -1 ? mediaPath.slice(dot).toLowerCase() : '.png';\n const mimeType = extToMime(ext);\n\n ctx.imageCounter++;\n const imagePath = `images/image${ctx.imageCounter}${ext}`;\n ctx.extractedImages.set(imagePath, { data, mimeType });\n\n // Alt text from the picture's non-visual properties (descr, then name).\n const cNvPrs = pic.getElementsByTagNameNS(NS_PML, 'cNvPr');\n const alt =\n (cNvPrs.length ? cNvPrs[0]!.getAttribute('descr') || cNvPrs[0]!.getAttribute('name') : '') ||\n 'Image';\n\n images.push({ type: 'image', url: imagePath, alt });\n }\n return images;\n}\n\n// ── Layout-verdict annotation building ───────────────────────────────\n\n/** One non-title text shape on a slide, with its placeholder identity. */\ninterface SlideTextEntry {\n rawType: string;\n idx: number;\n texts: string[];\n}\n\n/** Annotation params live on a single heading line — flatten whitespace. */\nfunction cleanParamText(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Turn a slide's layout verdict into a heading annotation, downgrading to\n * plain when the slide lacks the content the template needs (a bare\n * annotation without its essential params renders an empty card in the\n * player path, which never derives inputs for annotated blocks).\n */\nfunction buildSlideAnnotation(\n analyzed: AnalyzedLayout | undefined,\n entries: SlideTextEntry[],\n images: MarkdownImage[],\n ctx: ImportContext,\n): { annotation?: HeadingTemplateAnnotation; omitted: Set<SlideTextEntry> } {\n const omitted = new Set<SlideTextEntry>();\n if (!analyzed) return { omitted };\n const verdict = analyzed.verdict;\n\n if (verdict.kind === 'custom') {\n ctx.usedCustomTemplates.set(verdict.def.name, verdict.def);\n return { annotation: { template: verdict.def.name }, omitted };\n }\n if (verdict.kind !== 'builtin') return { omitted };\n\n switch (verdict.paramSpec) {\n case 'titleSubtitle': {\n const sub = entries.find((e) => e.rawType === 'subTitle');\n const subtitle = sub ? cleanParamText(sub.texts.join(' ')) : '';\n // The subtitle moves into the card; keep it out of the bullets.\n if (sub && subtitle) omitted.add(sub);\n return {\n annotation: {\n template: verdict.template,\n ...(subtitle ? { params: { subtitle } } : {}),\n },\n omitted,\n };\n }\n case 'comparisonPairs': {\n if (!verdict.columns) return { omitted };\n const textAt = (idx: number | undefined): string[] =>\n idx === undefined ? [] : (entries.find((e) => e.idx === idx)?.texts ?? []);\n const side = (idxs: number[]): string => {\n const header = cleanParamText(textAt(idxs[0])[0] ?? '');\n const body = cleanParamText(textAt(idxs[1])[0] ?? '');\n return header ? (body ? `${header}|${body}` : header) : '';\n };\n const left = side(verdict.columns.left);\n const right = side(verdict.columns.right);\n // twoColumn requires both labels — a bare annotation renders nothing.\n if (!left || !right) return { omitted };\n return { annotation: { template: 'twoColumn', params: { left, right } }, omitted };\n }\n case 'featureImage': {\n const image = images[0];\n if (!image) return { omitted };\n const params: Record<string, string> = { imageSrc: image.url };\n if (image.alt && image.alt !== 'Image') params.imageAlt = cleanParamText(image.alt);\n return { annotation: { template: verdict.template, params }, omitted };\n }\n case 'photoGridGate': {\n if (images.length < 2) return { omitted };\n return {\n annotation: {\n template: 'photoGrid',\n params: { images: images.map((i) => i.url).join(',') },\n },\n omitted,\n };\n }\n default:\n return { annotation: { template: verdict.template }, omitted };\n }\n}\n\nasync function convertSlide(\n path: string,\n index: number,\n ctx: ImportContext,\n): Promise<MarkdownBlockNode[]> {\n const pkg = ctx.pkg;\n const doc = await getPartXml(pkg, path);\n if (!doc) return [];\n const out: MarkdownBlockNode[] = [];\n\n let title = '';\n const entries: SlideTextEntry[] = [];\n const shapes = doc.getElementsByTagNameNS(NS_PML, 'sp');\n for (let s = 0; s < shapes.length; s++) {\n const sp = shapes[s]!;\n const txBody = sp.getElementsByTagNameNS(NS_PML, 'txBody');\n if (!txBody.length) continue;\n const paras = txBody[0]!.getElementsByTagNameNS(NS_DRAWINGML, 'p');\n const texts: string[] = [];\n for (let p = 0; p < paras.length; p++) {\n const t = paragraphText(paras[p]!);\n if (t) texts.push(t);\n }\n if (texts.length === 0) continue;\n if (isTitleShape(sp) && !title) {\n title = texts.join(' ');\n continue;\n }\n const phs = sp.getElementsByTagNameNS(NS_PML, 'ph');\n const rawType = phs.length ? (phs[0]!.getAttribute('type') ?? '') : '';\n const idxRaw = phs.length ? phs[0]!.getAttribute('idx') : null;\n const idx = idxRaw ? parseInt(idxRaw, 10) || 0 : 0;\n entries.push({ rawType, idx, texts });\n }\n\n // Images are extracted before annotation building so feature/photoGrid\n // params can reference their container paths; they still land after the\n // bullet list in the output, unchanged.\n const images = ctx.extractImages ? await extractSlideImages(doc, path, ctx) : [];\n\n const layoutPath = ctx.inference?.layoutPathBySlide.get(path);\n const analyzed = layoutPath ? ctx.inference?.byLayoutPath.get(layoutPath) : undefined;\n const { annotation, omitted } = buildSlideAnnotation(analyzed, entries, images, ctx);\n\n out.push({\n type: 'heading',\n depth: 2,\n children: [{ type: 'text', value: title || `Slide ${index + 1}` }],\n ...(annotation ? { templateAnnotation: annotation } : {}),\n });\n\n const bullets = entries.filter((e) => !omitted.has(e)).flatMap((e) => e.texts);\n if (bullets.length > 0) {\n const items: MarkdownListItem[] = bullets.map((text) => ({\n type: 'listItem',\n children: [{ type: 'paragraph', children: [{ type: 'text', value: text }] }],\n }));\n out.push({ type: 'list', ordered: false, children: items });\n }\n\n // Embedded pictures land after the bullet list and before any tables.\n for (const image of images) {\n out.push({ type: 'paragraph', children: [image] });\n }\n\n const tbls = doc.getElementsByTagNameNS(NS_DRAWINGML, 'tbl');\n for (let t = 0; t < tbls.length; t++) out.push(tableToMarkdown(tbls[t]!));\n\n return out;\n}\n\nfunction warnInferenceFailure(step: string, err: unknown): void {\n const message = err instanceof Error ? err.message : String(err);\n console.warn(`pptx import: ${step} failed; importing without it — ${message}`);\n}\n\nasync function importDocument(\n pkg: OoxmlPackage,\n options: PptxImportOptions,\n): Promise<{ doc: MarkdownDocument; ctx: ImportContext }> {\n const ctx: ImportContext = {\n pkg,\n extractImages: options.extractImages ?? false,\n extractedImages: new Map(),\n imageCounter: 0,\n usedCustomTemplates: new Map(),\n };\n\n const inferTheme = options.inferTheme !== false;\n const inferLayouts = options.inferLayouts !== false;\n\n // All inference modules load lazily so a plain import stays light, and\n // every inference step degrades to a warning rather than failing the import.\n let extraction: ExtractedFileTheme | null = null;\n if (inferTheme || inferLayouts) {\n try {\n const { extractPptxTheme } = await import('../infer/extract.js');\n extraction = await extractPptxTheme(pkg);\n } catch (err: unknown) {\n warnInferenceFailure('theme extraction', err);\n }\n }\n\n let theme: Theme | undefined;\n if (inferTheme && extraction) {\n try {\n const { compileExtractedTheme } = await import('../infer/mapTheme.js');\n theme = compileExtractedTheme(extraction).theme;\n } catch (err: unknown) {\n warnInferenceFailure('theme compilation', err);\n }\n }\n\n if (inferLayouts) {\n try {\n const { analyzePptxLayouts } = await import('./layouts.js');\n const { colorHintsFromExtraction } = await import('../infer/mapTheme.js');\n ctx.inference = await analyzePptxLayouts(pkg, {\n colors: extraction ? colorHintsFromExtraction(extraction) : {},\n });\n } catch (err: unknown) {\n warnInferenceFailure('layout inference', err);\n }\n }\n\n const paths = await orderedSlidePaths(pkg);\n const children: MarkdownBlockNode[] = [];\n for (let i = 0; i < paths.length; i++) {\n children.push(...(await convertSlide(paths[i]!, i, ctx)));\n }\n const doc: MarkdownDocument = { type: 'document', children };\n\n const frontmatter: Record<string, unknown> = {};\n if (theme || ctx.usedCustomTemplates.size > 0) {\n const {\n writeCustomThemesToFrontmatter,\n writeCustomTemplatesToFrontmatter,\n FRONTMATTER_CUSTOM_THEMES_KEY,\n FRONTMATTER_CUSTOM_TEMPLATES_KEY,\n } = await import('@bendyline/squisq/doc');\n if (theme) {\n const payload = writeCustomThemesToFrontmatter([theme]);\n if (payload) {\n frontmatter[FRONTMATTER_CUSTOM_THEMES_KEY] = payload;\n // The doc-level selector `resolveThemeForDoc` reads — activates the\n // inferred theme without any global registration.\n frontmatter['squisq-theme'] = theme.id;\n }\n }\n if (ctx.usedCustomTemplates.size > 0) {\n const payload = writeCustomTemplatesToFrontmatter([...ctx.usedCustomTemplates.values()]);\n if (payload) frontmatter[FRONTMATTER_CUSTOM_TEMPLATES_KEY] = payload;\n }\n }\n if (Object.keys(frontmatter).length > 0) doc.frontmatter = frontmatter;\n\n return { doc, ctx };\n}\n\nexport async function pptxToMarkdownDoc(\n data: ArrayBuffer | Blob,\n options: PptxImportOptions = {},\n): Promise<MarkdownDocument> {\n const pkg = await openPackage(data, options);\n const { doc } = await importDocument(pkg, options);\n return doc;\n}\n\n/**\n * Convert a .pptx file to a ContentContainer with markdown + extracted images.\n *\n * The container holds the primary markdown document plus every embedded slide\n * image under `images/` (e.g. `images/image1.png`). Image extraction is always\n * forced on here so the markdown's image references resolve inside the\n * container. Mirrors `docxToContainer`.\n */\nexport async function pptxToContainer(\n data: ArrayBuffer | Blob,\n options: PptxImportOptions = {},\n): Promise<ContentContainer> {\n const pkg = await openPackage(data, options);\n const { doc, ctx } = await importDocument(pkg, { ...options, extractImages: true });\n\n return buildContainer(stringifyMarkdown(doc), ctx.extractedImages);\n}\n"],"mappings":"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","names":["p","analyzePptxLayouts"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ooxml/themeReader.ts"],"sourcesContent":["/**\n * OOXML theme reader — parses a `theme1.xml` part (DrawingML `a:theme`)\n * into normalized color and font schemes.\n *\n * Shared by DOCX/PPTX/XLSX theme inference: all three formats carry the same\n * theme part shape, differing only in where the part hangs (document/master/\n * workbook relationships). This module never fails hard — unreadable slots\n * degrade to fallbacks or absence, with a warning per degradation.\n */\n\nimport type { OoxmlPackage } from './types.js';\nimport { getPartRelationships, getPartXml } from './reader.js';\nimport { NS_DRAWINGML, REL_THEME } from './namespaces.js';\nimport { baseDirOf, findRelByType, resolveTarget } from './readUtils.js';\n\n/**\n * The clrScheme slots as normalized `#rrggbb` strings. The four surface/text\n * slots always resolve (falling back to black/white when degraded); accent and\n * hyperlink slots are omitted when unresolvable.\n */\nexport interface OoxmlColorScheme {\n dk1: string;\n lt1: string;\n dk2: string;\n lt2: string;\n accent1?: string;\n accent2?: string;\n accent3?: string;\n accent4?: string;\n accent5?: string;\n accent6?: string;\n hlink?: string;\n folHlink?: string;\n}\n\nexport interface OoxmlFontScheme {\n /** `a:fontScheme > a:majorFont > a:latin@typeface` (headings). */\n majorLatin?: string;\n /** `a:fontScheme > a:minorFont > a:latin@typeface` (body). */\n minorLatin?: string;\n}\n\nexport interface OoxmlTheme {\n /** `a:theme@name` (e.g. \"Office Theme\", \"Ion\"). */\n name?: string;\n /** Absent when the theme carries no parseable `a:clrScheme`. */\n colors?: OoxmlColorScheme;\n /** Absent when the theme carries no `a:fontScheme` latin typefaces. */\n fonts?: OoxmlFontScheme;\n warnings: string[];\n}\n\nconst HEX6_RE = /^[0-9a-fA-F]{6}$/;\n\n/** Well-known sysClr values that resolve without a `lastClr` hint. */\nconst SYS_COLOR_DEFAULTS: Record<string, string> = {\n windowText: '000000',\n window: 'ffffff',\n};\n\n/**\n * Resolve one clrScheme slot element to a `#rrggbb` string, or null.\n * Only the base color matters for theming — trailing transform children\n * (`a:lumMod`, `a:tint`, …) are ignored.\n */\nfunction resolveSchemeColor(slot: Element): string | null {\n for (let i = 0; i < slot.childNodes.length; i++) {\n const child = slot.childNodes[i];\n if (!child || child.nodeType !== 1) continue;\n const el = child as Element;\n if (el.localName === 'srgbClr') {\n const val = el.getAttribute('val');\n return val && HEX6_RE.test(val) ? `#${val.toLowerCase()}` : null;\n }\n if (el.localName === 'sysClr') {\n const lastClr = el.getAttribute('lastClr');\n if (lastClr && HEX6_RE.test(lastClr)) return `#${lastClr.toLowerCase()}`;\n const val = el.getAttribute('val');\n const known = val ? SYS_COLOR_DEFAULTS[val] : undefined;\n return known ? `#${known}` : null;\n }\n // Any other color form (schemeClr self-reference, prstClr, …) is\n // unresolvable without a full DrawingML color pipeline.\n return null;\n }\n return null;\n}\n\nfunction firstNS(parent: Element | Document, local: string): Element | null {\n const els = parent.getElementsByTagNameNS(NS_DRAWINGML, local);\n return els.length > 0 ? els[0]! : null;\n}\n\nfunction parseColorScheme(clrScheme: Element, warnings: string[]): OoxmlColorScheme {\n const resolve = (slotName: string): string | null => {\n const slot = firstNS(clrScheme, slotName);\n if (!slot) return null;\n return resolveSchemeColor(slot);\n };\n\n const dk1 = resolve('dk1');\n const lt1 = resolve('lt1');\n if (!dk1) warnings.push('theme: dk1 color could not be resolved; using #000000');\n if (!lt1) warnings.push('theme: lt1 color could not be resolved; using #ffffff');\n\n const dk2 = resolve('dk2');\n const lt2 = resolve('lt2');\n\n const colors: OoxmlColorScheme = {\n dk1: dk1 ?? '#000000',\n lt1: lt1 ?? '#ffffff',\n dk2: dk2 ?? dk1 ?? '#000000',\n lt2: lt2 ?? lt1 ?? '#ffffff',\n };\n\n for (const slot of ['accent1', 'accent2', 'accent3', 'accent4', 'accent5', 'accent6'] as const) {\n const hex = resolve(slot);\n if (hex) colors[slot] = hex;\n else warnings.push(`theme: ${slot} color could not be resolved; dropped`);\n }\n for (const slot of ['hlink', 'folHlink'] as const) {\n const hex = resolve(slot);\n if (hex) colors[slot] = hex;\n }\n return colors;\n}\n\nfunction parseFontScheme(fontScheme: Element, warnings: string[]): OoxmlFontScheme | undefined {\n const readLatin = (fontName: 'majorFont' | 'minorFont'): string | undefined => {\n const font = firstNS(fontScheme, fontName);\n if (!font) return undefined;\n const latin = firstNS(font, 'latin');\n const typeface = latin?.getAttribute('typeface')?.trim();\n if (!typeface) {\n warnings.push(`theme: ${fontName} has no latin typeface`);\n return undefined;\n }\n return typeface;\n };\n\n const majorLatin = readLatin('majorFont');\n const minorLatin = readLatin('minorFont');\n if (!majorLatin && !minorLatin) return undefined;\n return {\n ...(majorLatin ? { majorLatin } : {}),\n ...(minorLatin ? { minorLatin } : {}),\n };\n}\n\n/** Parse an already-loaded theme part Document. */\nexport function parseThemeXml(themeDoc: Document): OoxmlTheme {\n const warnings: string[] = [];\n\n const root = firstNS(themeDoc, 'theme');\n const name = root?.getAttribute('name')?.trim() || undefined;\n\n const clrScheme = firstNS(themeDoc, 'clrScheme');\n let colors: OoxmlColorScheme | undefined;\n if (clrScheme) {\n colors = parseColorScheme(clrScheme, warnings);\n } else {\n warnings.push('theme: no clrScheme found');\n }\n\n const fontScheme = firstNS(themeDoc, 'fontScheme');\n let fonts: OoxmlFontScheme | undefined;\n if (fontScheme) {\n fonts = parseFontScheme(fontScheme, warnings);\n } else {\n warnings.push('theme: no fontScheme found');\n }\n\n return {\n ...(name ? { name } : {}),\n ...(colors ? { colors } : {}),\n ...(fonts ? { fonts } : {}),\n warnings,\n };\n}\n\n/**\n * Resolve the theme part related from `fromPartPath` (via `REL_THEME`) and\n * parse it. Returns null when the part has no theme relationship or the\n * target part is missing — callers decide whether that's an error.\n */\nexport async function readThemePart(\n pkg: OoxmlPackage,\n fromPartPath: string,\n): Promise<OoxmlTheme | null> {\n const rels = await getPartRelationships(pkg, fromPartPath);\n const rel = findRelByType(rels, REL_THEME);\n if (!rel) return null;\n const themePath = resolveTarget(baseDirOf(fromPartPath), rel.target);\n const doc = await getPartXml(pkg, themePath);\n if (!doc) return null;\n return parseThemeXml(doc);\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/container.ts"],"sourcesContent":["/**\n * Shared tail for the container-producing importers.\n *\n * `docxToContainer`, `pptxToContainer`, and `pdfToContainer` all end the same\n * way: create a `MemoryContentContainer`, write the primary markdown document,\n * then write each extracted image under its path with its MIME type. This\n * factors that identical epilogue into one place.\n */\n\nimport { MemoryContentContainer } from '@bendyline/squisq/storage';\nimport type { ContentContainer } from '@bendyline/squisq/storage';\n\n/**\n * Assemble a {@link ContentContainer} from a markdown document plus a set of\n * media files. `images` is any iterable of `[path, { data, mimeType }]` pairs\n * (a `Map` from the importers' extraction context satisfies this directly).\n */\nexport async function buildContainer(\n markdown: string,\n images: Iterable<readonly [string, { data: ArrayBuffer; mimeType: string }]>,\n): Promise<ContentContainer> {\n const container = new MemoryContentContainer();\n await container.writeDocument(markdown);\n for (const [path, { data, mimeType }] of images) {\n await container.writeFile(path, new Uint8Array(data), mimeType);\n }\n return container;\n}\n"],"mappings":";AASA,SAAS,8BAA8B;AAQvC,eAAsB,eACpB,UACA,QAC2B;AAC3B,QAAM,YAAY,IAAI,uBAAuB;AAC7C,QAAM,UAAU,cAAc,QAAQ;AACtC,aAAW,CAAC,MAAM,EAAE,MAAM,SAAS,CAAC,KAAK,QAAQ;AAC/C,UAAM,UAAU,UAAU,MAAM,IAAI,WAAW,IAAI,GAAG,QAAQ;AAAA,EAChE;AACA,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ooxml/xmlUtils.ts"],"sourcesContent":["/**\n * XML Utility Functions\n *\n * Lightweight helpers for generating well-formed XML strings.\n * Used by all OOXML writers (DOCX, PPTX, XLSX) to construct\n * part content without a heavy DOM library.\n */\n\n/**\n * XML declaration for the start of every OOXML part.\n */\nexport function xmlDeclaration(): string {\n return '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>';\n}\n\n/**\n * Escape a string for safe inclusion in XML text content or attribute values.\n *\n * Handles the five predefined XML entities:\n * - & → &amp;\n * - < → &lt;\n * - > → &gt;\n * - \" → &quot;\n * - ' → &apos;\n */\nexport function escapeXml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Build an XML attribute string from a key-value record.\n * Only includes entries where the value is defined and non-empty.\n *\n * @example\n * ```ts\n * attrString({ 'w:val': 'Heading1', 'w:eastAsia': undefined })\n * // ' w:val=\"Heading1\"'\n * ```\n */\nexport function attrString(attrs?: Record<string, string | undefined>): string {\n if (!attrs) return '';\n const parts: string[] = [];\n for (const [key, value] of Object.entries(attrs)) {\n if (value !== undefined && value !== '') {\n parts.push(` ${key}=\"${escapeXml(value)}\"`);\n }\n }\n return parts.join('');\n}\n\n/**\n * Build a self-closing XML element: `<tag attr=\"val\"/>`.\n *\n * @example\n * ```ts\n * selfClosingElement('w:b')\n * // '<w:b/>'\n *\n * selfClosingElement('w:pStyle', { 'w:val': 'Heading1' })\n * // '<w:pStyle w:val=\"Heading1\"/>'\n * ```\n */\nexport function selfClosingElement(\n tag: string,\n attrs?: Record<string, string | undefined>,\n): string {\n return `<${tag}${attrString(attrs)}/>`;\n}\n\n/**\n * Build an XML element with children: `<tag attr=\"val\">...children...</tag>`.\n * Children are concatenated directly (no extra whitespace).\n *\n * @example\n * ```ts\n * xmlElement('w:p', {},\n * xmlElement('w:r', {},\n * xmlElement('w:t', {}, 'Hello')\n * )\n * )\n * // '<w:p><w:r><w:t>Hello</w:t></w:r></w:p>'\n * ```\n */\nexport function xmlElement(\n tag: string,\n attrs?: Record<string, string | undefined>,\n ...children: string[]\n): string {\n const content = children.join('');\n if (content === '') {\n return selfClosingElement(tag, attrs);\n }\n return `<${tag}${attrString(attrs)}>${content}</${tag}>`;\n}\n\n/**\n * Build an XML text element: `<tag attr=\"val\">escaped text</tag>`.\n * The text value is XML-escaped automatically.\n *\n * This is a convenience for the common pattern of wrapping text in an element,\n * where you want automatic escaping (unlike `xmlElement` which takes raw children).\n *\n * @example\n * ```ts\n * textElement('w:t', { 'xml:space': 'preserve' }, 'Hello & world')\n * // '<w:t xml:space=\"preserve\">Hello &amp; world</w:t>'\n * ```\n */\nexport function textElement(\n tag: string,\n attrs?: Record<string, string | undefined>,\n text?: string,\n): string {\n if (text === undefined || text === '') {\n return selfClosingElement(tag, attrs);\n }\n return `<${tag}${attrString(attrs)}>${escapeXml(text)}</${tag}>`;\n}\n"],"mappings":";AAWO,SAAS,iBAAyB;AACvC,SAAO;AACT;AAYO,SAAS,UAAU,MAAsB;AAC9C,SAAO,KACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AAC3B;AAYO,SAAS,WAAW,OAAoD;AAC7E,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,UAAU,UAAa,UAAU,IAAI;AACvC,YAAM,KAAK,IAAI,GAAG,KAAK,UAAU,KAAK,CAAC,GAAG;AAAA,IAC5C;AAAA,EACF;AACA,SAAO,MAAM,KAAK,EAAE;AACtB;AAcO,SAAS,mBACd,KACA,OACQ;AACR,SAAO,IAAI,GAAG,GAAG,WAAW,KAAK,CAAC;AACpC;AAgBO,SAAS,WACd,KACA,UACG,UACK;AACR,QAAM,UAAU,SAAS,KAAK,EAAE;AAChC,MAAI,YAAY,IAAI;AAClB,WAAO,mBAAmB,KAAK,KAAK;AAAA,EACtC;AACA,SAAO,IAAI,GAAG,GAAG,WAAW,KAAK,CAAC,IAAI,OAAO,KAAK,GAAG;AACvD;AAeO,SAAS,YACd,KACA,OACA,MACQ;AACR,MAAI,SAAS,UAAa,SAAS,IAAI;AACrC,WAAO,mBAAmB,KAAK,KAAK;AAAA,EACtC;AACA,SAAO,IAAI,GAAG,GAAG,WAAW,KAAK,CAAC,IAAI,UAAU,IAAI,CAAC,KAAK,GAAG;AAC/D;","names":[]}
@@ -1,275 +0,0 @@
1
- import {
2
- extractPlainText
3
- } from "./chunk-PN52A5AA.js";
4
- import {
5
- createPackage
6
- } from "./chunk-KURGXM4I.js";
7
- import {
8
- escapeXml,
9
- xmlDeclaration
10
- } from "./chunk-U4MRIFKL.js";
11
- import {
12
- CONTENT_TYPE_XLSX_STYLES,
13
- CONTENT_TYPE_XLSX_WORKBOOK,
14
- CONTENT_TYPE_XLSX_WORKSHEET,
15
- NS_R,
16
- NS_SML,
17
- REL_OFFICE_DOCUMENT,
18
- REL_STYLES,
19
- REL_WORKSHEET,
20
- getPartRelationships,
21
- getPartXml,
22
- openPackage
23
- } from "./chunk-7ARKUCQT.js";
24
-
25
- // src/xlsx/index.ts
26
- import { markdownToDoc } from "@bendyline/squisq/doc";
27
-
28
- // src/xlsx/import.ts
29
- function attrNS(el, ns, local, fallback) {
30
- return el.getAttributeNS(ns, local) ?? el.getAttribute(fallback);
31
- }
32
- function resolveTarget(baseDir, target) {
33
- if (target.startsWith("/")) return target.replace(/^\//, "");
34
- const stack = baseDir ? baseDir.split("/") : [];
35
- for (const seg of target.split("/")) {
36
- if (seg === "..") stack.pop();
37
- else if (seg !== ".") stack.push(seg);
38
- }
39
- return stack.join("/");
40
- }
41
- async function readSheets(pkg) {
42
- const wb = await getPartXml(pkg, "xl/workbook.xml");
43
- if (!wb) return [];
44
- const rels = await getPartRelationships(pkg, "xl/workbook.xml");
45
- const relById = new Map(rels.map((r) => [r.id, r.target]));
46
- const out = [];
47
- const sheetEls = wb.getElementsByTagNameNS(NS_SML, "sheet");
48
- for (let i = 0; i < sheetEls.length; i++) {
49
- const el = sheetEls[i];
50
- const name = el.getAttribute("name") ?? `Sheet${i + 1}`;
51
- const rid = attrNS(el, NS_R, "id", "r:id");
52
- const target = rid ? relById.get(rid) : void 0;
53
- if (target) out.push({ name, path: resolveTarget("xl", target) });
54
- }
55
- return out;
56
- }
57
- async function readSharedStrings(pkg) {
58
- const doc = await getPartXml(pkg, "xl/sharedStrings.xml");
59
- if (!doc) return [];
60
- const siEls = doc.getElementsByTagNameNS(NS_SML, "si");
61
- const out = [];
62
- for (let i = 0; i < siEls.length; i++) out.push(siEls[i].textContent ?? "");
63
- return out;
64
- }
65
- function colIndex(ref) {
66
- const m = /^([A-Za-z]+)/.exec(ref);
67
- if (!m) return 0;
68
- let n = 0;
69
- for (const ch of m[1].toUpperCase()) n = n * 26 + (ch.charCodeAt(0) - 64);
70
- return n - 1;
71
- }
72
- function cellText(cell, shared) {
73
- const t = cell.getAttribute("t");
74
- if (t === "inlineStr") {
75
- const is = cell.getElementsByTagNameNS(NS_SML, "t");
76
- return is.length ? is[0].textContent ?? "" : "";
77
- }
78
- const vEls = cell.getElementsByTagNameNS(NS_SML, "v");
79
- const v = vEls.length ? vEls[0].textContent ?? "" : "";
80
- if (t === "s") return shared[Number.parseInt(v, 10)] ?? "";
81
- if (t === "b") return v === "1" ? "TRUE" : "FALSE";
82
- return v;
83
- }
84
- async function sheetToGrid(pkg, path, shared) {
85
- const doc = await getPartXml(pkg, path);
86
- if (!doc) return [];
87
- const rowEls = doc.getElementsByTagNameNS(NS_SML, "row");
88
- const grid = [];
89
- for (let r = 0; r < rowEls.length; r++) {
90
- const cells = rowEls[r].getElementsByTagNameNS(NS_SML, "c");
91
- const rowArr = [];
92
- for (let c = 0; c < cells.length; c++) {
93
- const cell = cells[c];
94
- const ref = cell.getAttribute("r");
95
- const idx = ref ? colIndex(ref) : rowArr.length;
96
- while (rowArr.length < idx) rowArr.push("");
97
- rowArr[idx] = cellText(cell, shared);
98
- }
99
- grid.push(rowArr);
100
- }
101
- return grid;
102
- }
103
- function gridToTable(grid) {
104
- const maxCols = grid.reduce((m, r) => Math.max(m, r.length), 1);
105
- const rows = grid.map((cells, rowIdx) => {
106
- const children = [];
107
- for (let c = 0; c < maxCols; c++) {
108
- const value = cells[c] ?? "";
109
- children.push({
110
- type: "tableCell",
111
- ...rowIdx === 0 ? { isHeader: true } : {},
112
- children: value ? [{ type: "text", value }] : []
113
- });
114
- }
115
- return { type: "tableRow", children };
116
- });
117
- return { type: "table", children: rows };
118
- }
119
- async function xlsxToMarkdownDoc(data, options = {}) {
120
- const pkg = await openPackage(data, options);
121
- const sheets = await readSheets(pkg);
122
- const shared = await readSharedStrings(pkg);
123
- let selected = sheets;
124
- if (options.sheet !== void 0) {
125
- const picked = typeof options.sheet === "number" ? sheets[options.sheet] : sheets.find((s) => s.name === options.sheet);
126
- selected = picked ? [picked] : [];
127
- }
128
- const children = [];
129
- const single = selected.length === 1 && options.sheet !== void 0;
130
- for (const sheet of selected) {
131
- const grid = await sheetToGrid(pkg, sheet.path, shared);
132
- if (!single) {
133
- children.push({ type: "heading", depth: 1, children: [{ type: "text", value: sheet.name }] });
134
- }
135
- if (grid.length > 0) children.push(gridToTable(grid));
136
- }
137
- return { type: "document", children };
138
- }
139
-
140
- // src/xlsx/export.ts
141
- import { docToMarkdown } from "@bendyline/squisq/doc";
142
- var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
143
- function sanitizeSheetName(raw, used, fallback) {
144
- let name = raw.replace(/[[\]:*?/\\]/g, "").trim();
145
- if (name.length === 0) name = fallback;
146
- name = name.slice(0, 31);
147
- if (!used.has(name)) {
148
- used.add(name);
149
- return name;
150
- }
151
- for (let n = 2; ; n++) {
152
- const suffix = String(n);
153
- const base = name.slice(0, 31 - suffix.length);
154
- const candidate = `${base}${suffix}`;
155
- if (!used.has(candidate)) {
156
- used.add(candidate);
157
- return candidate;
158
- }
159
- }
160
- }
161
- function tableToGrid(table) {
162
- return table.children.map(
163
- (row) => row.children.map((cell) => extractPlainText(cell.children))
164
- );
165
- }
166
- function collectSheets(doc, prefix) {
167
- const used = /* @__PURE__ */ new Set();
168
- const sheets = [];
169
- let pendingHeading = null;
170
- const visit = (nodes) => {
171
- for (const node of nodes) {
172
- if (node.type === "heading") {
173
- pendingHeading = extractPlainText(node.children);
174
- } else if (node.type === "table") {
175
- const fallback = `${prefix}${sheets.length + 1}`;
176
- const name = sanitizeSheetName(pendingHeading ?? fallback, used, fallback);
177
- sheets.push({ name, grid: tableToGrid(node) });
178
- pendingHeading = null;
179
- }
180
- }
181
- };
182
- visit(doc.children);
183
- return sheets;
184
- }
185
- function columnLetter(index) {
186
- let n = index + 1;
187
- let letters = "";
188
- while (n > 0) {
189
- const rem = (n - 1) % 26;
190
- letters = String.fromCharCode(65 + rem) + letters;
191
- n = Math.floor((n - 1) / 26);
192
- }
193
- return letters;
194
- }
195
- function cellXml(value, ref) {
196
- if (NUMERIC_RE.test(value)) {
197
- return `<c r="${ref}"><v>${escapeXml(value)}</v></c>`;
198
- }
199
- return `<c r="${ref}" t="inlineStr"><is><t xml:space="preserve">${escapeXml(value)}</t></is></c>`;
200
- }
201
- function worksheetXml(grid) {
202
- const rows = [];
203
- for (let r = 0; r < grid.length; r++) {
204
- const cells = grid[r];
205
- const cellsXml = cells.map((value, c) => cellXml(value, `${columnLetter(c)}${r + 1}`)).join("");
206
- rows.push(`<row r="${r + 1}">${cellsXml}</row>`);
207
- }
208
- return `${xmlDeclaration()}
209
- <worksheet xmlns="${NS_SML}" xmlns:r="${NS_R}"><sheetData>${rows.join("")}</sheetData></worksheet>`;
210
- }
211
- function workbookXml(sheets) {
212
- const sheetEls = sheets.map(
213
- (sheet, i) => `<sheet name="${escapeXml(sheet.name)}" sheetId="${i + 1}" r:id="rId${i + 1}"/>`
214
- ).join("");
215
- return `${xmlDeclaration()}
216
- <workbook xmlns="${NS_SML}" xmlns:r="${NS_R}"><sheets>${sheetEls}</sheets></workbook>`;
217
- }
218
- function stylesXml() {
219
- return `${xmlDeclaration()}
220
- <styleSheet xmlns="${NS_SML}"><fonts count="1"><font><sz val="11"/><name val="Calibri"/></font></fonts><fills count="1"><fill><patternFill patternType="none"/></fill></fills><borders count="1"><border/></borders><cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/></cellXfs></styleSheet>`;
221
- }
222
- async function markdownDocToXlsx(doc, options = {}) {
223
- const prefix = options.sheetNamePrefix ?? "Sheet";
224
- let sheets = collectSheets(doc, prefix);
225
- if (sheets.length === 0) {
226
- sheets = [{ name: `${prefix}1`, grid: [] }];
227
- }
228
- const pkg = createPackage();
229
- sheets.forEach((sheet, i) => {
230
- const sheetPath = `xl/worksheets/sheet${i + 1}.xml`;
231
- pkg.addPart(sheetPath, worksheetXml(sheet.grid), CONTENT_TYPE_XLSX_WORKSHEET);
232
- pkg.addRelationship("xl/workbook.xml", {
233
- id: `rId${i + 1}`,
234
- type: REL_WORKSHEET,
235
- target: `worksheets/sheet${i + 1}.xml`
236
- });
237
- });
238
- pkg.addPart("xl/styles.xml", stylesXml(), CONTENT_TYPE_XLSX_STYLES);
239
- pkg.addRelationship("xl/workbook.xml", {
240
- id: `rId${sheets.length + 1}`,
241
- type: REL_STYLES,
242
- target: "styles.xml"
243
- });
244
- pkg.addPart("xl/workbook.xml", workbookXml(sheets), CONTENT_TYPE_XLSX_WORKBOOK);
245
- pkg.addRelationship("", {
246
- id: "rId1",
247
- type: REL_OFFICE_DOCUMENT,
248
- target: "xl/workbook.xml"
249
- });
250
- if (options.title || options.author) {
251
- pkg.setCoreProperties({
252
- title: options.title,
253
- creator: options.author,
254
- created: (/* @__PURE__ */ new Date()).toISOString(),
255
- modified: (/* @__PURE__ */ new Date()).toISOString()
256
- });
257
- }
258
- return pkg.toArrayBuffer();
259
- }
260
- async function docToXlsx(doc, options) {
261
- return markdownDocToXlsx(docToMarkdown(doc), options);
262
- }
263
-
264
- // src/xlsx/index.ts
265
- async function xlsxToDoc(data, options) {
266
- return markdownToDoc(await xlsxToMarkdownDoc(data, options));
267
- }
268
-
269
- export {
270
- xlsxToMarkdownDoc,
271
- markdownDocToXlsx,
272
- docToXlsx,
273
- xlsxToDoc
274
- };
275
- //# sourceMappingURL=chunk-UGYF5AZE.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/xlsx/index.ts","../src/xlsx/import.ts","../src/xlsx/export.ts"],"sourcesContent":["/**\n * @bendyline/squisq-formats XLSX Module\n *\n * Excel .xlsx support via SpreadsheetML and the shared ooxml/ infrastructure.\n * Both directions are implemented: import (`xlsxToMarkdownDoc` / `xlsxToDoc`)\n * turns each worksheet grid into a markdown table; export (`markdownDocToXlsx`\n * / `docToXlsx`) turns each markdown table into a worksheet. Export is\n * tables-only fidelity — non-table content is dropped (headings only survive\n * as sheet names). See export.ts for details.\n *\n * @example\n * ```ts\n * import { xlsxToMarkdownDoc, markdownDocToXlsx } from '@bendyline/squisq-formats/xlsx';\n * ```\n */\n\nimport { markdownToDoc } from '@bendyline/squisq/doc';\nimport type { Doc } from '@bendyline/squisq/schemas';\nimport { type XlsxImportOptions, xlsxToMarkdownDoc } from './import.js';\n\nexport type { XlsxImportOptions } from './import.js';\nexport { xlsxToMarkdownDoc } from './import.js';\n\nexport type { XlsxExportOptions } from './export.js';\nexport { markdownDocToXlsx, docToXlsx } from './export.js';\n\n/**\n * Convert a .xlsx file to a squisq Doc (via the markdown table model).\n */\nexport async function xlsxToDoc(\n data: ArrayBuffer | Blob,\n options?: XlsxImportOptions,\n): Promise<Doc> {\n return markdownToDoc(await xlsxToMarkdownDoc(data, options));\n}\n","/**\n * XLSX import — SpreadsheetML (.xlsx) → MarkdownDocument.\n *\n * Reuses the shared ooxml/ reader (zip + DOMParser). Reads the workbook's\n * sheet list, resolves each sheet part via relationships, pulls shared strings,\n * and turns each worksheet's cell grid into a markdown table (first row treated\n * as the header). By default every sheet is imported, each preceded by an H1 of\n * the sheet name; pass `options.sheet` (index or name) to import just one.\n */\n\nimport type {\n MarkdownBlockNode,\n MarkdownDocument,\n MarkdownTable,\n MarkdownTableCell,\n MarkdownTableRow,\n} from '@bendyline/squisq/markdown';\nimport { getPartXml, getPartRelationships, openPackage } from '../ooxml/reader.js';\nimport type { OoxmlOpenOptions } from '../ooxml/reader.js';\nimport type { OoxmlPackage } from '../ooxml/types.js';\nimport { NS_R, NS_SML } from '../ooxml/namespaces.js';\n\nexport interface XlsxImportOptions extends OoxmlOpenOptions {\n /** Which sheet to import (0-based index or sheet name). Default: all sheets. */\n sheet?: number | string;\n}\n\ninterface SheetRef {\n name: string;\n path: string;\n}\n\nfunction attrNS(el: Element, ns: string, local: string, fallback: string): string | null {\n return el.getAttributeNS(ns, local) ?? el.getAttribute(fallback);\n}\n\n/** Resolve a relationship target (relative to its part's dir) to a zip path. */\nfunction resolveTarget(baseDir: string, target: string): string {\n if (target.startsWith('/')) return target.replace(/^\\//, '');\n const stack = baseDir ? baseDir.split('/') : [];\n for (const seg of target.split('/')) {\n if (seg === '..') stack.pop();\n else if (seg !== '.') stack.push(seg);\n }\n return stack.join('/');\n}\n\nasync function readSheets(pkg: OoxmlPackage): Promise<SheetRef[]> {\n const wb = await getPartXml(pkg, 'xl/workbook.xml');\n if (!wb) return [];\n const rels = await getPartRelationships(pkg, 'xl/workbook.xml');\n const relById = new Map(rels.map((r) => [r.id, r.target]));\n const out: SheetRef[] = [];\n const sheetEls = wb.getElementsByTagNameNS(NS_SML, 'sheet');\n for (let i = 0; i < sheetEls.length; i++) {\n const el = sheetEls[i]!;\n const name = el.getAttribute('name') ?? `Sheet${i + 1}`;\n const rid = attrNS(el, NS_R, 'id', 'r:id');\n const target = rid ? relById.get(rid) : undefined;\n if (target) out.push({ name, path: resolveTarget('xl', target) });\n }\n return out;\n}\n\nasync function readSharedStrings(pkg: OoxmlPackage): Promise<string[]> {\n const doc = await getPartXml(pkg, 'xl/sharedStrings.xml');\n if (!doc) return [];\n const siEls = doc.getElementsByTagNameNS(NS_SML, 'si');\n const out: string[] = [];\n for (let i = 0; i < siEls.length; i++) out.push(siEls[i]!.textContent ?? '');\n return out;\n}\n\n/** Column letters of a cell ref (\"B7\" → 1, \"AA1\" → 26). */\nfunction colIndex(ref: string): number {\n const m = /^([A-Za-z]+)/.exec(ref);\n if (!m) return 0;\n let n = 0;\n for (const ch of m[1]!.toUpperCase()) n = n * 26 + (ch.charCodeAt(0) - 64);\n return n - 1;\n}\n\nfunction cellText(cell: Element, shared: string[]): string {\n const t = cell.getAttribute('t');\n if (t === 'inlineStr') {\n const is = cell.getElementsByTagNameNS(NS_SML, 't');\n return is.length ? (is[0]!.textContent ?? '') : '';\n }\n const vEls = cell.getElementsByTagNameNS(NS_SML, 'v');\n const v = vEls.length ? (vEls[0]!.textContent ?? '') : '';\n if (t === 's') return shared[Number.parseInt(v, 10)] ?? '';\n if (t === 'b') return v === '1' ? 'TRUE' : 'FALSE';\n return v;\n}\n\nasync function sheetToGrid(pkg: OoxmlPackage, path: string, shared: string[]): Promise<string[][]> {\n const doc = await getPartXml(pkg, path);\n if (!doc) return [];\n const rowEls = doc.getElementsByTagNameNS(NS_SML, 'row');\n const grid: string[][] = [];\n for (let r = 0; r < rowEls.length; r++) {\n const cells = rowEls[r]!.getElementsByTagNameNS(NS_SML, 'c');\n const rowArr: string[] = [];\n for (let c = 0; c < cells.length; c++) {\n const cell = cells[c]!;\n const ref = cell.getAttribute('r');\n const idx = ref ? colIndex(ref) : rowArr.length;\n while (rowArr.length < idx) rowArr.push('');\n rowArr[idx] = cellText(cell, shared);\n }\n grid.push(rowArr);\n }\n return grid;\n}\n\nfunction gridToTable(grid: string[][]): MarkdownTable {\n const maxCols = grid.reduce((m, r) => Math.max(m, r.length), 1);\n const rows: MarkdownTableRow[] = grid.map((cells, rowIdx) => {\n const children: MarkdownTableCell[] = [];\n for (let c = 0; c < maxCols; c++) {\n const value = cells[c] ?? '';\n children.push({\n type: 'tableCell',\n ...(rowIdx === 0 ? { isHeader: true } : {}),\n children: value ? [{ type: 'text', value }] : [],\n });\n }\n return { type: 'tableRow', children };\n });\n return { type: 'table', children: rows };\n}\n\nexport async function xlsxToMarkdownDoc(\n data: ArrayBuffer | Blob,\n options: XlsxImportOptions = {},\n): Promise<MarkdownDocument> {\n const pkg = await openPackage(data, options);\n const sheets = await readSheets(pkg);\n const shared = await readSharedStrings(pkg);\n\n let selected = sheets;\n if (options.sheet !== undefined) {\n const picked =\n typeof options.sheet === 'number'\n ? sheets[options.sheet]\n : sheets.find((s) => s.name === options.sheet);\n selected = picked ? [picked] : [];\n }\n\n const children: MarkdownBlockNode[] = [];\n const single = selected.length === 1 && options.sheet !== undefined;\n for (const sheet of selected) {\n const grid = await sheetToGrid(pkg, sheet.path, shared);\n if (!single) {\n children.push({ type: 'heading', depth: 1, children: [{ type: 'text', value: sheet.name }] });\n }\n if (grid.length > 0) children.push(gridToTable(grid));\n }\n return { type: 'document', children };\n}\n","/**\n * XLSX export — MarkdownDocument → SpreadsheetML (.xlsx).\n *\n * Tables-only fidelity (honestly documented): every `table` node in the\n * markdown AST becomes one worksheet; all other content (headings, prose,\n * lists, images, …) is dropped except that the nearest preceding heading is\n * used to name the sheet. This mirrors the import side (`xlsxToMarkdownDoc`),\n * which turns each worksheet grid back into a markdown table.\n *\n * Cells are emitted as inline strings (`t=\"inlineStr\"`) so no sharedStrings\n * part is needed, except values matching a plain-number pattern, which are\n * emitted as numeric cells. The package is assembled with the shared ooxml/\n * writer (auto-generates `[Content_Types].xml` + `_rels`), so only the\n * SpreadsheetML-specific parts (workbook, worksheets, styles) are written here.\n *\n * @example\n * ```ts\n * import { parseMarkdown } from '@bendyline/squisq/markdown';\n * import { markdownDocToXlsx } from '@bendyline/squisq-formats/xlsx';\n *\n * const md = parseMarkdown('# Metrics\\n\\n| A | B |\\n| - | - |\\n| 1 | 2 |');\n * const buffer = await markdownDocToXlsx(md);\n * ```\n */\n\nimport type { Doc } from '@bendyline/squisq/schemas';\nimport { docToMarkdown } from '@bendyline/squisq/doc';\nimport type {\n MarkdownDocument,\n MarkdownBlockNode,\n MarkdownTable,\n MarkdownTableRow,\n} from '@bendyline/squisq/markdown';\n\nimport { createPackage } from '../ooxml/writer.js';\nimport { xmlDeclaration, escapeXml } from '../ooxml/xmlUtils.js';\nimport { extractPlainText } from '../shared/text.js';\nimport {\n NS_SML,\n NS_R,\n REL_OFFICE_DOCUMENT,\n REL_STYLES,\n REL_WORKSHEET,\n CONTENT_TYPE_XLSX_WORKBOOK,\n CONTENT_TYPE_XLSX_WORKSHEET,\n CONTENT_TYPE_XLSX_STYLES,\n} from '../ooxml/namespaces.js';\n\n/**\n * Options for XLSX export.\n */\nexport interface XlsxExportOptions {\n /** Workbook title (written to core properties). */\n title?: string;\n /** Workbook author (written to core properties). */\n author?: string;\n /** Prefix used for auto-named sheets when no heading precedes a table. Default: \"Sheet\". */\n sheetNamePrefix?: string;\n}\n\ninterface SheetData {\n name: string;\n /** Grid of cell text: first row is the header. */\n grid: string[][];\n}\n\n/** A plain integer or decimal (optionally negative) — emitted as a numeric cell. */\nconst NUMERIC_RE = /^-?\\d+(\\.\\d+)?$/;\n\n/**\n * Sanitize a candidate name into a valid, unique Excel sheet name.\n * Strips characters Excel forbids (`[]:*?/\\`), caps at 31 chars, and\n * de-duplicates against already-used names by appending 2, 3, …\n */\nfunction sanitizeSheetName(raw: string, used: Set<string>, fallback: string): string {\n let name = raw.replace(/[[\\]:*?/\\\\]/g, '').trim();\n if (name.length === 0) name = fallback;\n name = name.slice(0, 31);\n\n if (!used.has(name)) {\n used.add(name);\n return name;\n }\n // Dedupe: \"Name\", \"Name2\", \"Name3\", … keeping within the 31-char cap.\n for (let n = 2; ; n++) {\n const suffix = String(n);\n const base = name.slice(0, 31 - suffix.length);\n const candidate = `${base}${suffix}`;\n if (!used.has(candidate)) {\n used.add(candidate);\n return candidate;\n }\n }\n}\n\n/** Convert a table node into a grid of plain-text cells. */\nfunction tableToGrid(table: MarkdownTable): string[][] {\n return table.children.map((row: MarkdownTableRow) =>\n row.children.map((cell) => extractPlainText(cell.children)),\n );\n}\n\n/** Walk the document, pairing each table with the nearest preceding heading. */\nfunction collectSheets(doc: MarkdownDocument, prefix: string): SheetData[] {\n const used = new Set<string>();\n const sheets: SheetData[] = [];\n let pendingHeading: string | null = null;\n\n const visit = (nodes: MarkdownBlockNode[]): void => {\n for (const node of nodes) {\n if (node.type === 'heading') {\n pendingHeading = extractPlainText(node.children);\n } else if (node.type === 'table') {\n const fallback = `${prefix}${sheets.length + 1}`;\n const name = sanitizeSheetName(pendingHeading ?? fallback, used, fallback);\n sheets.push({ name, grid: tableToGrid(node) });\n pendingHeading = null;\n }\n }\n };\n\n visit(doc.children);\n return sheets;\n}\n\n/** Column letters for a zero-based index (0 → \"A\", 26 → \"AA\"). */\nfunction columnLetter(index: number): string {\n let n = index + 1;\n let letters = '';\n while (n > 0) {\n const rem = (n - 1) % 26;\n letters = String.fromCharCode(65 + rem) + letters;\n n = Math.floor((n - 1) / 26);\n }\n return letters;\n}\n\nfunction cellXml(value: string, ref: string): string {\n if (NUMERIC_RE.test(value)) {\n return `<c r=\"${ref}\"><v>${escapeXml(value)}</v></c>`;\n }\n return `<c r=\"${ref}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(value)}</t></is></c>`;\n}\n\nfunction worksheetXml(grid: string[][]): string {\n const rows: string[] = [];\n for (let r = 0; r < grid.length; r++) {\n const cells = grid[r]!;\n const cellsXml = cells.map((value, c) => cellXml(value, `${columnLetter(c)}${r + 1}`)).join('');\n rows.push(`<row r=\"${r + 1}\">${cellsXml}</row>`);\n }\n return (\n `${xmlDeclaration()}\\n` +\n `<worksheet xmlns=\"${NS_SML}\" xmlns:r=\"${NS_R}\">` +\n `<sheetData>${rows.join('')}</sheetData>` +\n `</worksheet>`\n );\n}\n\nfunction workbookXml(sheets: SheetData[]): string {\n const sheetEls = sheets\n .map(\n (sheet, i) =>\n `<sheet name=\"${escapeXml(sheet.name)}\" sheetId=\"${i + 1}\" r:id=\"rId${i + 1}\"/>`,\n )\n .join('');\n return (\n `${xmlDeclaration()}\\n` +\n `<workbook xmlns=\"${NS_SML}\" xmlns:r=\"${NS_R}\">` +\n `<sheets>${sheetEls}</sheets>` +\n `</workbook>`\n );\n}\n\n/** Minimal but valid styles part (Excel expects the referenced collections to exist). */\nfunction stylesXml(): string {\n return (\n `${xmlDeclaration()}\\n` +\n `<styleSheet xmlns=\"${NS_SML}\">` +\n `<fonts count=\"1\"><font><sz val=\"11\"/><name val=\"Calibri\"/></font></fonts>` +\n `<fills count=\"1\"><fill><patternFill patternType=\"none\"/></fill></fills>` +\n `<borders count=\"1\"><border/></borders>` +\n `<cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs>` +\n `<cellXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/></cellXfs>` +\n `</styleSheet>`\n );\n}\n\n/**\n * Convert a MarkdownDocument to a .xlsx file (tables-only fidelity).\n *\n * Each markdown `table` becomes one worksheet; a document with no tables\n * yields a single empty sheet (a valid, openable file — never throws).\n */\nexport async function markdownDocToXlsx(\n doc: MarkdownDocument,\n options: XlsxExportOptions = {},\n): Promise<ArrayBuffer> {\n const prefix = options.sheetNamePrefix ?? 'Sheet';\n let sheets = collectSheets(doc, prefix);\n\n // Zero tables → one empty sheet so the file is still valid.\n if (sheets.length === 0) {\n sheets = [{ name: `${prefix}1`, grid: [] }];\n }\n\n const pkg = createPackage();\n\n // Worksheets + workbook→worksheet relationships.\n sheets.forEach((sheet, i) => {\n const sheetPath = `xl/worksheets/sheet${i + 1}.xml`;\n pkg.addPart(sheetPath, worksheetXml(sheet.grid), CONTENT_TYPE_XLSX_WORKSHEET);\n pkg.addRelationship('xl/workbook.xml', {\n id: `rId${i + 1}`,\n type: REL_WORKSHEET,\n target: `worksheets/sheet${i + 1}.xml`,\n });\n });\n\n // Styles part (referenced after the sheet relationships).\n pkg.addPart('xl/styles.xml', stylesXml(), CONTENT_TYPE_XLSX_STYLES);\n pkg.addRelationship('xl/workbook.xml', {\n id: `rId${sheets.length + 1}`,\n type: REL_STYLES,\n target: 'styles.xml',\n });\n\n // Workbook + root relationship.\n pkg.addPart('xl/workbook.xml', workbookXml(sheets), CONTENT_TYPE_XLSX_WORKBOOK);\n pkg.addRelationship('', {\n id: 'rId1',\n type: REL_OFFICE_DOCUMENT,\n target: 'xl/workbook.xml',\n });\n\n if (options.title || options.author) {\n pkg.setCoreProperties({\n title: options.title,\n creator: options.author,\n created: new Date().toISOString(),\n modified: new Date().toISOString(),\n });\n }\n\n return pkg.toArrayBuffer();\n}\n\n/**\n * Convert a squisq Doc to a .xlsx file (via the markdown table model).\n */\nexport async function docToXlsx(doc: Doc, options?: XlsxExportOptions): Promise<ArrayBuffer> {\n return markdownDocToXlsx(docToMarkdown(doc), options);\n}\n"],"mappings":"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","names":[]}