@bendyline/squisq-formats 1.1.0 → 1.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 (89) hide show
  1. package/README.md +23 -10
  2. package/dist/{chunk-ULLIPBEJ.js → chunk-743COJWQ.js} +6 -2
  3. package/dist/chunk-743COJWQ.js.map +1 -0
  4. package/dist/{chunk-KAK4V57E.js → chunk-BHHEDPRB.js} +16 -112
  5. package/dist/chunk-BHHEDPRB.js.map +1 -0
  6. package/dist/{chunk-MQHCXI56.js → chunk-CLGUOVYR.js} +193 -23
  7. package/dist/chunk-CLGUOVYR.js.map +1 -0
  8. package/dist/chunk-FIFCQN3W.js +630 -0
  9. package/dist/chunk-FIFCQN3W.js.map +1 -0
  10. package/dist/chunk-KJ4NS4DX.js +120 -0
  11. package/dist/chunk-KJ4NS4DX.js.map +1 -0
  12. package/dist/{chunk-TBPD5PCU.js → chunk-S3Y7H2BK.js} +161 -11
  13. package/dist/chunk-S3Y7H2BK.js.map +1 -0
  14. package/dist/docx/export.d.ts +15 -0
  15. package/dist/docx/export.d.ts.map +1 -1
  16. package/dist/docx/export.js +144 -19
  17. package/dist/docx/export.js.map +1 -1
  18. package/dist/docx/import.d.ts +13 -0
  19. package/dist/docx/import.d.ts.map +1 -1
  20. package/dist/docx/import.js +102 -10
  21. package/dist/docx/import.js.map +1 -1
  22. package/dist/docx/index.d.ts +1 -1
  23. package/dist/docx/index.d.ts.map +1 -1
  24. package/dist/docx/index.js +1 -1
  25. package/dist/docx/index.js.map +1 -1
  26. package/dist/html/htmlTemplate.d.ts +6 -0
  27. package/dist/html/htmlTemplate.d.ts.map +1 -1
  28. package/dist/html/htmlTemplate.js +5 -1
  29. package/dist/html/htmlTemplate.js.map +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +2 -2
  32. package/dist/index.js.map +1 -1
  33. package/dist/ooxml/index.d.ts +1 -1
  34. package/dist/ooxml/index.d.ts.map +1 -1
  35. package/dist/ooxml/index.js +1 -1
  36. package/dist/ooxml/index.js.map +1 -1
  37. package/dist/ooxml/namespaces.d.ts +10 -0
  38. package/dist/ooxml/namespaces.d.ts.map +1 -1
  39. package/dist/ooxml/namespaces.js +10 -0
  40. package/dist/ooxml/namespaces.js.map +1 -1
  41. package/dist/pdf/export.d.ts +6 -0
  42. package/dist/pdf/export.d.ts.map +1 -1
  43. package/dist/pdf/export.js +37 -9
  44. package/dist/pdf/export.js.map +1 -1
  45. package/dist/pdf/import.d.ts +16 -0
  46. package/dist/pdf/import.d.ts.map +1 -1
  47. package/dist/pdf/import.js +177 -0
  48. package/dist/pdf/import.js.map +1 -1
  49. package/dist/pdf/index.d.ts +1 -1
  50. package/dist/pdf/index.d.ts.map +1 -1
  51. package/dist/pdf/index.js +1 -1
  52. package/dist/pdf/index.js.map +1 -1
  53. package/dist/pptx/export.d.ts +75 -0
  54. package/dist/pptx/export.d.ts.map +1 -0
  55. package/dist/pptx/export.js +722 -0
  56. package/dist/pptx/export.js.map +1 -0
  57. package/dist/pptx/index.d.ts +12 -27
  58. package/dist/pptx/index.d.ts.map +1 -1
  59. package/dist/pptx/index.js +12 -22
  60. package/dist/pptx/index.js.map +1 -1
  61. package/dist/pptx/styles.d.ts +54 -0
  62. package/dist/pptx/styles.d.ts.map +1 -0
  63. package/dist/pptx/styles.js +73 -0
  64. package/dist/pptx/styles.js.map +1 -0
  65. package/dist/pptx/templates.d.ts +24 -0
  66. package/dist/pptx/templates.d.ts.map +1 -0
  67. package/dist/pptx/templates.js +158 -0
  68. package/dist/pptx/templates.js.map +1 -0
  69. package/package.json +2 -2
  70. package/src/docx/export.ts +183 -20
  71. package/src/docx/import.ts +127 -10
  72. package/src/docx/index.ts +1 -1
  73. package/src/html/htmlTemplate.ts +13 -0
  74. package/src/index.ts +2 -2
  75. package/src/ooxml/index.ts +7 -0
  76. package/src/ooxml/namespaces.ts +23 -0
  77. package/src/pdf/export.ts +57 -9
  78. package/src/pdf/import.ts +228 -0
  79. package/src/pdf/index.ts +1 -1
  80. package/src/pptx/export.ts +1041 -0
  81. package/src/pptx/index.ts +15 -37
  82. package/src/pptx/styles.ts +96 -0
  83. package/src/pptx/templates.ts +187 -0
  84. package/dist/chunk-532L4D5D.js +0 -21
  85. package/dist/chunk-532L4D5D.js.map +0 -1
  86. package/dist/chunk-KAK4V57E.js.map +0 -1
  87. package/dist/chunk-MQHCXI56.js.map +0 -1
  88. package/dist/chunk-TBPD5PCU.js.map +0 -1
  89. package/dist/chunk-ULLIPBEJ.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @bendyline/squisq-formats
2
2
 
3
- Document format converters for Squisq. Import and export between Squisq's Markdown-based document model and common file formats — DOCX, PDF, and HTML. All converters run entirely in the browser with no server or native binaries required.
3
+ Document format converters for Squisq. Import and export between Squisq's Markdown-based document model and common file formats — DOCX, PPTX, PDF, and HTML. All converters run entirely in the browser with no server or native binaries required.
4
4
 
5
5
  Part of the [Squisq](https://github.com/bendyline/squisq) monorepo.
6
6
 
@@ -15,13 +15,15 @@ npm install @bendyline/squisq-formats @bendyline/squisq
15
15
 
16
16
  ## Supported Formats
17
17
 
18
- | Format | Import | Export | Subpath |
19
- | --------------------- | ------- | ------- | -------------------------------- |
20
- | **DOCX** (Word) | ✅ | ✅ | `@bendyline/squisq-formats/docx` |
21
- | **PDF** | ✅ | ✅ | `@bendyline/squisq-formats/pdf` |
22
- | **HTML** | — | ✅ | `@bendyline/squisq-formats/html` |
23
- | **PPTX** (PowerPoint) | planned | planned | `@bendyline/squisq-formats/pptx` |
24
- | **XLSX** (Excel) | planned | planned | `@bendyline/squisq-formats/xlsx` |
18
+ | Format | Import | Export | Theme | Subpath |
19
+ | --------------------- | ------- | ------- | ----- | -------------------------------- |
20
+ | **DOCX** (Word) | ✅ | ✅ | ✅ | `@bendyline/squisq-formats/docx` |
21
+ | **PDF** | ✅ | ✅ | ✅ | `@bendyline/squisq-formats/pdf` |
22
+ | **HTML** | — | ✅ | ✅ | `@bendyline/squisq-formats/html` |
23
+ | **PPTX** (PowerPoint) | planned | ✅ | | `@bendyline/squisq-formats/pptx` |
24
+ | **XLSX** (Excel) | planned | planned | — | `@bendyline/squisq-formats/xlsx` |
25
+
26
+ All export formats accept an optional `themeId` to apply Squisq theme colors and typography.
25
27
 
26
28
  ## Quick Examples
27
29
 
@@ -68,6 +70,16 @@ const html = docToHtml(doc);
68
70
  const zipBytes = await docToHtmlZip(doc);
69
71
  ```
70
72
 
73
+ ### PPTX
74
+
75
+ ```ts
76
+ import { markdownDocToPptx } from '@bendyline/squisq-formats/pptx';
77
+
78
+ // Export: MarkdownDocument → PPTX (ArrayBuffer)
79
+ // Each H1/H2 heading starts a new slide
80
+ const pptxBytes = await markdownDocToPptx(markdownDoc);
81
+ ```
82
+
71
83
  ### Doc-level Convenience Functions
72
84
 
73
85
  Each format also exports `Doc`-level wrappers that handle the Markdown↔Doc conversion internally:
@@ -75,6 +87,7 @@ Each format also exports `Doc`-level wrappers that handle the Markdown↔Doc con
75
87
  ```ts
76
88
  import { docToDocx, docxToDoc } from '@bendyline/squisq-formats/docx';
77
89
  import { docToPdf, pdfToDoc } from '@bendyline/squisq-formats/pdf';
90
+ import { docToPptx } from '@bendyline/squisq-formats/pptx';
78
91
  ```
79
92
 
80
93
  ## Subpath Exports
@@ -85,12 +98,12 @@ import { docToPdf, pdfToDoc } from '@bendyline/squisq-formats/pdf';
85
98
  | `@bendyline/squisq-formats/pdf` | PDF import/export + worker config |
86
99
  | `@bendyline/squisq-formats/html` | HTML export |
87
100
  | `@bendyline/squisq-formats/ooxml` | Shared OOXML infrastructure (ZIP reader/writer, XML utilities) |
88
- | `@bendyline/squisq-formats/pptx` | PPTX stubs (not yet implemented) |
101
+ | `@bendyline/squisq-formats/pptx` | PPTX export (import planned) |
89
102
  | `@bendyline/squisq-formats/xlsx` | XLSX stubs (not yet implemented) |
90
103
 
91
104
  ## Architecture
92
105
 
93
- All converters use Squisq's `MarkdownDocument` AST as the pivot format. Importing a file parses it into a `MarkdownDocument`; exporting serializes from one. The OOXML subpath provides shared infrastructure for reading and writing Office Open XML packages (used by DOCX, and eventually PPTX/XLSX).
106
+ All converters use Squisq's `MarkdownDocument` AST as the pivot format. Importing a file parses it into a `MarkdownDocument`; exporting serializes from one. The OOXML subpath provides shared infrastructure for reading and writing Office Open XML packages (used by DOCX and PPTX, and eventually XLSX).
94
107
 
95
108
  ## Related Packages
96
109
 
@@ -126,8 +126,12 @@ function generateInlineHtml(doc, options) {
126
126
  images,
127
127
  mode = "slideshow",
128
128
  title = "Squisq Document",
129
- autoPlay = false
129
+ autoPlay = false,
130
+ themeId
130
131
  } = options;
132
+ if (themeId) {
133
+ doc = { ...doc, themeId };
134
+ }
131
135
  const imageMap = {};
132
136
  if (images) {
133
137
  for (const [path, buffer] of images.entries()) {
@@ -268,4 +272,4 @@ export {
268
272
  docToHtml,
269
273
  docToHtmlZip
270
274
  };
271
- //# sourceMappingURL=chunk-ULLIPBEJ.js.map
275
+ //# sourceMappingURL=chunk-743COJWQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/html/index.ts","../src/html/imageUtils.ts","../src/html/htmlTemplate.ts"],"sourcesContent":["/**\n * HTML Export Module — @bendyline/squisq-formats/html\n *\n * Exports squisq documents as self-contained HTML files or ZIP archives.\n *\n * Two export modes:\n *\n * 1. **Single HTML** (`docToHtml`) — Everything embedded in one file:\n * - SquisqPlayer IIFE bundle inlined in `<script>`\n * - Images base64-encoded as data URIs\n * - Timer-based playback (no audio — too large for inline)\n *\n * 2. **ZIP Archive** (`docToHtmlZip`) — Multi-file package:\n * - `index.html` referencing external `squisq-player.js`\n * - `squisq-player.js` — the IIFE bundle\n * - `images/` — extracted image files\n * - `audio/` — optional audio segment files (enables full playback)\n *\n * @example\n * ```ts\n * import { PLAYER_BUNDLE } from '@bendyline/squisq-react/standalone-source';\n * import { docToHtml, docToHtmlZip } from '@bendyline/squisq-formats/html';\n *\n * // Single HTML file\n * const html = docToHtml(doc, { playerScript: PLAYER_BUNDLE, images });\n *\n * // ZIP archive\n * const zipBlob = await docToHtmlZip(doc, { playerScript: PLAYER_BUNDLE, images, audio });\n * ```\n */\n\nimport type { Doc } from '@bendyline/squisq/schemas';\nimport JSZip from 'jszip';\nimport {\n generateInlineHtml,\n generateExternalHtml,\n type HtmlExportOptions,\n} from './htmlTemplate.js';\nimport { extractFilename } from './imageUtils.js';\n\n// ── Public Types ───────────────────────────────────────────────────\n\nexport type { HtmlExportOptions };\n\nexport interface HtmlZipExportOptions extends HtmlExportOptions {\n /**\n * Map of audio segment identifiers to binary audio data.\n * Keys should match the audio segment `name` or `url` fields in the Doc.\n * When provided, audio files are included in the ZIP and full playback is enabled.\n */\n audio?: Map<string, ArrayBuffer>;\n}\n\n// ── Single HTML Export ─────────────────────────────────────────────\n\n/**\n * Export a Doc as a single, self-contained HTML file.\n *\n * The player JS is embedded inline, images are base64-encoded as data URIs,\n * and playback uses a timer (no audio) for compact file size.\n *\n * @param doc - The Doc to export\n * @param options - Export options (must include `playerScript`)\n * @returns Complete HTML document as a string\n *\n * @example\n * ```ts\n * const html = docToHtml(myDoc, {\n * playerScript: PLAYER_BUNDLE,\n * images: imageMap,\n * title: 'My Document',\n * mode: 'slideshow',\n * });\n * const blob = new Blob([html], { type: 'text/html' });\n * ```\n */\nexport function docToHtml(doc: Doc, options: HtmlExportOptions): string {\n return generateInlineHtml(doc, options);\n}\n\n// ── ZIP Archive Export ─────────────────────────────────────────────\n\n/**\n * Export a Doc as a ZIP archive containing HTML, JS, images, and optionally audio.\n *\n * The archive structure:\n * ```\n * document.zip\n * ├── index.html # HTML page referencing squisq-player.js\n * ├── squisq-player.js # Standalone IIFE bundle\n * ├── images/ # Extracted image files\n * │ ├── hero.jpg\n * │ └── ...\n * └── audio/ # Optional audio segment files\n * ├── intro.mp3\n * └── ...\n * ```\n *\n * @param doc - The Doc to export\n * @param options - Export options (must include `playerScript`)\n * @returns A Promise resolving to a ZIP Blob\n *\n * @example\n * ```ts\n * const blob = await docToHtmlZip(myDoc, {\n * playerScript: PLAYER_BUNDLE,\n * images: imageMap,\n * audio: audioMap,\n * });\n * // Trigger browser download\n * const url = URL.createObjectURL(blob);\n * ```\n */\nexport async function docToHtmlZip(doc: Doc, options: HtmlZipExportOptions): Promise<Blob> {\n const { playerScript, images, audio, mode = 'slideshow', title, autoPlay } = options;\n\n const zip = new JSZip();\n\n // 1. Add player JS as a separate file\n zip.file('squisq-player.js', playerScript);\n\n // 2. Add images to images/ folder and build path mapping\n const imagePathMap: Record<string, string> = {};\n if (images) {\n for (const [originalPath, buffer] of images.entries()) {\n const filename = extractFilename(originalPath);\n const zipPath = `images/${filename}`;\n zip.file(zipPath, buffer);\n imagePathMap[originalPath] = zipPath;\n }\n }\n\n // 3. Add audio to audio/ folder and build path mapping\n const audioPathMap: Record<string, string> = {};\n if (audio) {\n for (const [segmentKey, buffer] of audio.entries()) {\n const filename = extractFilename(segmentKey);\n // Ensure .mp3 extension\n const finalName = filename.includes('.') ? filename : `${filename}.mp3`;\n const zipPath = `audio/${finalName}`;\n zip.file(zipPath, buffer);\n audioPathMap[segmentKey] = zipPath;\n }\n }\n\n // 4. Generate HTML that references external files\n const html = generateExternalHtml(doc, {\n playerScriptPath: 'squisq-player.js',\n imagePathMap: Object.keys(imagePathMap).length > 0 ? imagePathMap : undefined,\n audioPathMap: Object.keys(audioPathMap).length > 0 ? audioPathMap : undefined,\n mode,\n title,\n autoPlay,\n });\n zip.file('index.html', html);\n\n // 5. Generate ZIP blob\n return zip.generateAsync({\n type: 'blob',\n compression: 'DEFLATE',\n compressionOptions: { level: 6 },\n });\n}\n\n// ── Re-exports ─────────────────────────────────────────────────────\n\nexport { collectImagePaths } from './htmlTemplate.js';\nexport { inferMimeType, arrayBufferToBase64DataUrl, extractFilename } from './imageUtils.js';\n","/**\n * Image Utilities for HTML Export\n *\n * Browser-compatible helpers for converting image data to base64 data URIs\n * and inferring MIME types from filenames.\n */\n\n/** Map of file extensions to MIME types */\nconst MIME_MAP: Record<string, string> = {\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n png: 'image/png',\n gif: 'image/gif',\n webp: 'image/webp',\n svg: 'image/svg+xml',\n ico: 'image/x-icon',\n bmp: 'image/bmp',\n avif: 'image/avif',\n mp3: 'audio/mpeg',\n wav: 'audio/wav',\n ogg: 'audio/ogg',\n mp4: 'video/mp4',\n webm: 'video/webm',\n};\n\n/**\n * Infer a MIME type from a filename's extension.\n * Returns 'application/octet-stream' for unknown types.\n */\nexport function inferMimeType(filename: string): string {\n const ext = filename.split('.').pop()?.toLowerCase() ?? '';\n return MIME_MAP[ext] ?? 'application/octet-stream';\n}\n\n/**\n * Convert an ArrayBuffer to a base64-encoded data URI string.\n *\n * @param buffer - The binary image data\n * @param mimeType - MIME type (e.g., 'image/jpeg'). If not provided, defaults to\n * 'application/octet-stream'.\n * @returns A `data:` URI string\n */\nexport function arrayBufferToBase64DataUrl(buffer: ArrayBuffer, mimeType: string): string {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n const base64 = btoa(binary);\n return `data:${mimeType};base64,${base64}`;\n}\n\n/**\n * Extract the filename from a path or URL (strips directory and query).\n *\n * @example\n * extractFilename('images/hero.jpg') // 'hero.jpg'\n * extractFilename('https://example.com/photo.png?v=2') // 'photo.png'\n */\nexport function extractFilename(path: string): string {\n // Strip query/hash\n const clean = path.split('?')[0].split('#')[0];\n // Get last segment\n const parts = clean.split('/');\n return parts[parts.length - 1] || path;\n}\n","/**\n * HTML Template Generation for SquisqPlayer Exports\n *\n * Generates complete, self-contained HTML documents that load the SquisqPlayer\n * IIFE bundle and render a Doc as either an interactive slideshow or a static\n * scrollable document.\n *\n * Two variants:\n * 1. **Inline** — All JS, CSS, and images are embedded in the HTML (single file).\n * 2. **External** — JS is referenced via `<script src>`, images via relative paths.\n */\n\nimport type { Doc, Layer, Block } from '@bendyline/squisq/schemas';\nimport { arrayBufferToBase64DataUrl, inferMimeType } from './imageUtils.js';\n\n// ── Types ──────────────────────────────────────────────────────────\n\nexport interface HtmlExportOptions {\n /** The IIFE player bundle source code (from @bendyline/squisq-react/standalone-source) */\n playerScript: string;\n\n /**\n * Map of relative image paths (as they appear in the Doc) to binary image data.\n * For inline HTML export, these are converted to base64 data URIs.\n * For ZIP export, these are written as separate files.\n */\n images?: Map<string, ArrayBuffer>;\n\n /**\n * Map of audio segment identifiers to binary audio data.\n * Keys should match the audio segment `name` or `url` fields in the Doc.\n * Only used in ZIP exports — single HTML uses timer-based playback.\n */\n audio?: Map<string, ArrayBuffer>;\n\n /** Rendering mode: 'slideshow' (interactive, default) or 'static' (scrollable) */\n mode?: 'slideshow' | 'static';\n\n /** HTML page title (default: 'Squisq Document') */\n title?: string;\n\n /** Auto-play slideshow on load (default: false) */\n autoPlay?: boolean;\n\n /**\n * Squisq theme ID to apply (e.g., 'documentary', 'cinematic').\n * When set, the theme is assigned to the Doc before rendering,\n * so the SquisqPlayer renders with that theme's colors and typography.\n */\n themeId?: string;\n}\n\n// ── Image Path Collection ──────────────────────────────────────────\n\n/**\n * Collect all relative image paths referenced in a Doc's layers and template blocks.\n * Returns a Set of unique relative paths that need to be resolved.\n */\nexport function collectImagePaths(doc: Doc): Set<string> {\n const paths = new Set<string>();\n\n function addIfRelative(src: string | undefined) {\n if (\n !src ||\n src.startsWith('data:') ||\n src.startsWith('blob:') ||\n src.startsWith('http://') ||\n src.startsWith('https://')\n ) {\n return;\n }\n paths.add(src);\n }\n\n function scanLayers(layers: Layer[] | undefined) {\n if (!layers) return;\n for (const layer of layers) {\n if (layer.type === 'image') addIfRelative(layer.content.src);\n if (layer.type === 'video') {\n addIfRelative(layer.content.src);\n addIfRelative(layer.content.posterSrc);\n }\n if (layer.type === 'map') addIfRelative(layer.content.staticSrc);\n }\n }\n\n function scanBlock(block: Block) {\n scanLayers(block.layers);\n if (block.children) block.children.forEach(scanBlock);\n }\n\n // Scan all blocks\n doc.blocks.forEach(scanBlock);\n\n // Scan start block hero\n if (doc.startBlock?.heroSrc) addIfRelative(doc.startBlock.heroSrc);\n\n // Scan persistent layers\n if (doc.persistentLayers) {\n for (const pl of doc.persistentLayers.bottomLayers ?? []) {\n if ('src' in pl && typeof pl.src === 'string') addIfRelative(pl.src);\n }\n for (const pl of doc.persistentLayers.topLayers ?? []) {\n if ('src' in pl && typeof pl.src === 'string') addIfRelative(pl.src);\n }\n }\n\n // Scan template block fields that reference images\n for (const block of doc.blocks) {\n scanTemplateImageFields(block as unknown as Record<string, unknown>, paths);\n }\n\n return paths;\n}\n\n/**\n * Recursively scan any object for known image-bearing field names.\n */\nfunction scanTemplateImageFields(obj: Record<string, unknown>, paths: Set<string>): void {\n if (!obj || typeof obj !== 'object') return;\n\n const imageFieldNames = [\n 'imageSrc',\n 'src',\n 'heroSrc',\n 'backgroundImage',\n 'posterSrc',\n 'staticSrc',\n 'videoSrc',\n 'thumbnailSrc',\n ];\n\n for (const key of imageFieldNames) {\n const val = obj[key];\n if (typeof val === 'string' && val && !val.startsWith('data:') && !val.startsWith('http')) {\n paths.add(val);\n }\n // Handle nested objects like { src: '...' }\n if (val && typeof val === 'object' && !Array.isArray(val)) {\n scanTemplateImageFields(val as Record<string, unknown>, paths);\n }\n }\n\n // Handle arrays (e.g., images: [{ src: '...' }])\n if (Array.isArray(obj)) {\n for (const item of obj) {\n if (item && typeof item === 'object') {\n scanTemplateImageFields(item as Record<string, unknown>, paths);\n }\n }\n }\n\n // Recurse into known array/object fields\n for (const key of ['images', 'accentImage', 'backgroundVideo', 'children', 'blocks']) {\n const val = obj[key];\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item && typeof item === 'object') {\n scanTemplateImageFields(item as Record<string, unknown>, paths);\n }\n }\n } else if (val && typeof val === 'object') {\n scanTemplateImageFields(val as Record<string, unknown>, paths);\n }\n }\n}\n\n// ── HTML Generation ────────────────────────────────────────────────\n\n/**\n * Escape a string for safe embedding in a `<script>` tag.\n * Prevents `</script>` from closing the tag prematurely.\n */\nfunction escapeForScript(str: string): string {\n return str.replace(/<\\/(script)/gi, '<\\\\/$1');\n}\n\n/**\n * Generate a complete inline HTML document with all JS and images embedded.\n *\n * @param doc - The Doc to render\n * @param options - Export options\n * @returns Complete HTML string\n */\nexport function generateInlineHtml(doc: Doc, options: HtmlExportOptions): string {\n const {\n playerScript,\n images,\n mode = 'slideshow',\n title = 'Squisq Document',\n autoPlay = false,\n themeId,\n } = options;\n\n // Apply theme to doc if specified (the SquisqPlayer respects doc.themeId at render time)\n if (themeId) {\n doc = { ...doc, themeId };\n }\n\n // Build base64 image map\n const imageMap: Record<string, string> = {};\n if (images) {\n for (const [path, buffer] of images.entries()) {\n const mimeType = inferMimeType(path);\n imageMap[path] = arrayBufferToBase64DataUrl(buffer, mimeType);\n }\n }\n\n const docJson = escapeForScript(JSON.stringify(doc));\n const imageMapJson = escapeForScript(JSON.stringify(imageMap));\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>${escapeHtml(title)}</title>\n<style>\n*,*::before,*::after{box-sizing:border-box}\nhtml,body{margin:0;padding:0;height:100%;background:#1a1a2e;color:#e0e0e0;font-family:system-ui,-apple-system,sans-serif}\n#squisq-root{width:100%;height:100%;display:flex;align-items:center;justify-content:center}\n${mode === 'static' ? '#squisq-root{align-items:flex-start;overflow-y:auto;background:#fff;color:#1f2937}' : ''}\n</style>\n</head>\n<body>\n<div id=\"squisq-root\"></div>\n<script>${escapeForScript(playerScript)}</script>\n<script>\n(function(){\n var doc = JSON.parse(${JSON.stringify(docJson)});\n var images = JSON.parse(${JSON.stringify(imageMapJson)});\n SquisqPlayer.mount(document.getElementById(\"squisq-root\"), doc, {\n mode: ${JSON.stringify(mode)},\n images: images,\n autoPlay: ${JSON.stringify(autoPlay)},\n basePath: \".\"\n });\n})();\n</script>\n</body>\n</html>`;\n}\n\n/**\n * Generate an HTML document that references external JS and image files.\n * Used for ZIP exports where files sit alongside the HTML.\n *\n * @param doc - The Doc to render (image/audio paths should already be rewritten to relative)\n * @param options - Export options (playerScript is not embedded, referenced via src)\n * @returns Complete HTML string\n */\nexport function generateExternalHtml(\n doc: Doc,\n options: Pick<HtmlExportOptions, 'mode' | 'title' | 'autoPlay'> & {\n /** Relative path to the player JS file (e.g., 'squisq-player.js') */\n playerScriptPath: string;\n /** Map of original image paths to their rewritten relative paths in the ZIP */\n imagePathMap?: Record<string, string>;\n /** Map of audio segment IDs to their rewritten relative paths in the ZIP */\n audioPathMap?: Record<string, string>;\n },\n): string {\n const {\n playerScriptPath,\n imagePathMap,\n audioPathMap,\n mode = 'slideshow',\n title = 'Squisq Document',\n autoPlay = false,\n } = options;\n\n const docJson = escapeForScript(JSON.stringify(doc));\n const imageMapJson = imagePathMap ? escapeForScript(JSON.stringify(imagePathMap)) : '{}';\n const audioMapJson = audioPathMap ? escapeForScript(JSON.stringify(audioPathMap)) : 'null';\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>${escapeHtml(title)}</title>\n<style>\n*,*::before,*::after{box-sizing:border-box}\nhtml,body{margin:0;padding:0;height:100%;background:#1a1a2e;color:#e0e0e0;font-family:system-ui,-apple-system,sans-serif}\n#squisq-root{width:100%;height:100%;display:flex;align-items:center;justify-content:center}\n${mode === 'static' ? '#squisq-root{align-items:flex-start;overflow-y:auto;background:#fff;color:#1f2937}' : ''}\n</style>\n</head>\n<body>\n<div id=\"squisq-root\"></div>\n<script src=\"${escapeHtml(playerScriptPath)}\"></script>\n<script>\n(function(){\n var doc = JSON.parse(${JSON.stringify(docJson)});\n var images = JSON.parse(${JSON.stringify(imageMapJson)});\n var audio = ${audioMapJson};\n SquisqPlayer.mount(document.getElementById(\"squisq-root\"), doc, {\n mode: ${JSON.stringify(mode)},\n images: images,\n audio: audio,\n autoPlay: ${JSON.stringify(autoPlay)},\n basePath: \".\"\n });\n})();\n</script>\n</body>\n</html>`;\n}\n\n/**\n * Escape HTML special characters to prevent injection.\n */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n"],"mappings":"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","names":[]}
@@ -33,6 +33,13 @@ var CONTENT_TYPE_DOCX_SETTINGS = "application/vnd.openxmlformats-officedocument.
33
33
  var CONTENT_TYPE_DOCX_FONT_TABLE = "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml";
34
34
  var CONTENT_TYPE_DOCX_FOOTNOTES = "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml";
35
35
  var CONTENT_TYPE_PPTX_PRESENTATION = "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml";
36
+ var CONTENT_TYPE_PPTX_SLIDE = "application/vnd.openxmlformats-officedocument.presentationml.slide+xml";
37
+ var CONTENT_TYPE_PPTX_SLIDE_LAYOUT = "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml";
38
+ var CONTENT_TYPE_PPTX_SLIDE_MASTER = "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml";
39
+ var CONTENT_TYPE_PPTX_THEME = "application/vnd.openxmlformats-officedocument.theme+xml";
40
+ var REL_SLIDE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide";
41
+ var REL_SLIDE_LAYOUT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout";
42
+ var REL_SLIDE_MASTER = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster";
36
43
  var CONTENT_TYPE_XLSX_WORKBOOK = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
37
44
 
38
45
  // src/ooxml/xmlUtils.ts
@@ -230,111 +237,6 @@ function groupRelationshipsBySource(pending) {
230
237
  return grouped;
231
238
  }
232
239
 
233
- // src/ooxml/reader.ts
234
- import JSZip2 from "jszip";
235
- async function openPackage(data) {
236
- const zip = await JSZip2.loadAsync(data);
237
- const contentTypes = await parseContentTypes(zip);
238
- const rootRelationships = await parseRelationships(zip, "");
239
- return { zip, contentTypes, rootRelationships };
240
- }
241
- async function parseContentTypes(zip) {
242
- const overrides = /* @__PURE__ */ new Map();
243
- const defaults = /* @__PURE__ */ new Map();
244
- const file = zip.file("[Content_Types].xml");
245
- if (!file) return { overrides, defaults };
246
- const text = await file.async("text");
247
- const doc = new DOMParser().parseFromString(text, "application/xml");
248
- const defaultEls = doc.getElementsByTagName("Default");
249
- for (let i = 0; i < defaultEls.length; i++) {
250
- const el = defaultEls[i];
251
- const ext = el.getAttribute("Extension");
252
- const ct = el.getAttribute("ContentType");
253
- if (ext && ct) defaults.set(ext, ct);
254
- }
255
- const overrideEls = doc.getElementsByTagName("Override");
256
- for (let i = 0; i < overrideEls.length; i++) {
257
- const el = overrideEls[i];
258
- const partName = el.getAttribute("PartName");
259
- const ct = el.getAttribute("ContentType");
260
- if (partName && ct) {
261
- overrides.set(partName.replace(/^\//, ""), ct);
262
- }
263
- }
264
- return { overrides, defaults };
265
- }
266
- async function getPartRelationships(pkg, partPath) {
267
- return parseRelationships(pkg.zip, partPath);
268
- }
269
- async function parseRelationships(zip, partPath) {
270
- const relsPath = partPath === "" ? "_rels/.rels" : buildRelsPath2(partPath);
271
- const file = zip.file(relsPath);
272
- if (!file) return [];
273
- const text = await file.async("text");
274
- const doc = new DOMParser().parseFromString(text, "application/xml");
275
- const result = [];
276
- const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, "Relationship");
277
- const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName("Relationship");
278
- for (let i = 0; i < fallbackEls.length; i++) {
279
- const el = fallbackEls[i];
280
- const id = el.getAttribute("Id");
281
- const type = el.getAttribute("Type");
282
- const target = el.getAttribute("Target");
283
- if (id && type && target) {
284
- const targetMode = el.getAttribute("TargetMode");
285
- result.push({
286
- id,
287
- type,
288
- target,
289
- ...targetMode ? { targetMode } : {}
290
- });
291
- }
292
- }
293
- return result;
294
- }
295
- function buildRelsPath2(partPath) {
296
- const lastSlash = partPath.lastIndexOf("/");
297
- if (lastSlash === -1) {
298
- return `_rels/${partPath}.rels`;
299
- }
300
- const dir = partPath.substring(0, lastSlash);
301
- const file = partPath.substring(lastSlash + 1);
302
- return `${dir}/_rels/${file}.rels`;
303
- }
304
- async function getPartXml(pkg, partPath) {
305
- const file = pkg.zip.file(partPath);
306
- if (!file) return null;
307
- const text = await file.async("text");
308
- return new DOMParser().parseFromString(text, "application/xml");
309
- }
310
- async function getPartBinary(pkg, partPath) {
311
- const file = pkg.zip.file(partPath);
312
- if (!file) return null;
313
- return file.async("arraybuffer");
314
- }
315
- async function getCoreProperties(pkg) {
316
- const doc = await getPartXml(pkg, "docProps/core.xml");
317
- if (!doc) return {};
318
- function getText(ns, localName) {
319
- const els = doc.getElementsByTagNameNS(ns, localName);
320
- if (els.length > 0 && els[0].textContent) {
321
- return els[0].textContent;
322
- }
323
- return void 0;
324
- }
325
- return {
326
- title: getText(NS_DC, "title"),
327
- subject: getText(NS_DC, "subject"),
328
- creator: getText(NS_DC, "creator"),
329
- description: getText(NS_DC, "description"),
330
- keywords: getText(NS_CORE_PROPERTIES, "keywords"),
331
- lastModifiedBy: getText(NS_CORE_PROPERTIES, "lastModifiedBy"),
332
- revision: getText(NS_CORE_PROPERTIES, "revision"),
333
- created: getText(NS_DCTERMS, "created"),
334
- modified: getText(NS_DCTERMS, "modified")
335
- };
336
- }
337
-
338
240
  export {
339
241
  NS_RELATIONSHIPS,
340
242
  NS_CONTENT_TYPES,
@@ -370,6 +272,13 @@ export {
370
272
  CONTENT_TYPE_DOCX_FONT_TABLE,
371
273
  CONTENT_TYPE_DOCX_FOOTNOTES,
372
274
  CONTENT_TYPE_PPTX_PRESENTATION,
275
+ CONTENT_TYPE_PPTX_SLIDE,
276
+ CONTENT_TYPE_PPTX_SLIDE_LAYOUT,
277
+ CONTENT_TYPE_PPTX_SLIDE_MASTER,
278
+ CONTENT_TYPE_PPTX_THEME,
279
+ REL_SLIDE,
280
+ REL_SLIDE_LAYOUT,
281
+ REL_SLIDE_MASTER,
373
282
  CONTENT_TYPE_XLSX_WORKBOOK,
374
283
  xmlDeclaration,
375
284
  escapeXml,
@@ -377,11 +286,6 @@ export {
377
286
  selfClosingElement,
378
287
  xmlElement,
379
288
  textElement,
380
- createPackage,
381
- openPackage,
382
- getPartRelationships,
383
- getPartXml,
384
- getPartBinary,
385
- getCoreProperties
289
+ createPackage
386
290
  };
387
- //# sourceMappingURL=chunk-KAK4V57E.js.map
291
+ //# sourceMappingURL=chunk-BHHEDPRB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ooxml/namespaces.ts","../src/ooxml/xmlUtils.ts","../src/ooxml/writer.ts"],"sourcesContent":["/**\n * OOXML Namespace Constants\n *\n * All Office Open XML namespace URIs used across DOCX, PPTX, and XLSX.\n * Organized by category for easy reference.\n */\n\n// ============================================\n// Package-level namespaces (shared by all formats)\n// ============================================\n\n/** Relationships namespace (used in _rels/*.rels files) */\nexport const NS_RELATIONSHIPS = 'http://schemas.openxmlformats.org/package/2006/relationships';\n\n/** Content Types namespace ([Content_Types].xml) */\nexport const NS_CONTENT_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types';\n\n// ============================================\n// Relationship type URIs\n// ============================================\n\n/** Relationship type: Office document (main part) */\nexport const REL_OFFICE_DOCUMENT =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';\n\n/** Relationship type: Core properties */\nexport const REL_CORE_PROPERTIES =\n 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';\n\n/** Relationship type: Extended properties (app.xml) */\nexport const REL_EXTENDED_PROPERTIES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';\n\n/** Relationship type: Styles */\nexport const REL_STYLES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';\n\n/** Relationship type: Numbering */\nexport const REL_NUMBERING =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering';\n\n/** Relationship type: Font table */\nexport const REL_FONT_TABLE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable';\n\n/** Relationship type: Settings */\nexport const REL_SETTINGS =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings';\n\n/** Relationship type: Hyperlink */\nexport const REL_HYPERLINK =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink';\n\n/** Relationship type: Image */\nexport const REL_IMAGE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';\n\n/** Relationship type: Footnotes */\nexport const REL_FOOTNOTES =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes';\n\n/** Relationship type: Theme */\nexport const REL_THEME =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme';\n\n// ============================================\n// WordprocessingML (DOCX)\n// ============================================\n\n/** WordprocessingML main namespace (w:) */\nexport const NS_WML = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';\n\n// ============================================\n// PresentationML (PPTX)\n// ============================================\n\n/** PresentationML main namespace (p:) */\nexport const NS_PML = 'http://schemas.openxmlformats.org/presentationml/2006/main';\n\n// ============================================\n// SpreadsheetML (XLSX)\n// ============================================\n\n/** SpreadsheetML main namespace */\nexport const NS_SML = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';\n\n// ============================================\n// DrawingML (shared across formats)\n// ============================================\n\n/** DrawingML main namespace (a:) */\nexport const NS_DRAWINGML = 'http://schemas.openxmlformats.org/drawingml/2006/main';\n\n/** DrawingML WordprocessingML drawing namespace (wp:) */\nexport const NS_WP_DRAWING =\n 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing';\n\n/** DrawingML picture namespace (pic:) */\nexport const NS_PICTURE = 'http://schemas.openxmlformats.org/drawingml/2006/picture';\n\n// ============================================\n// Dublin Core / Core Properties\n// ============================================\n\n/** Dublin Core elements namespace */\nexport const NS_DC = 'http://purl.org/dc/elements/1.1/';\n\n/** Dublin Core terms namespace */\nexport const NS_DCTERMS = 'http://purl.org/dc/terms/';\n\n/** Core properties namespace */\nexport const NS_CORE_PROPERTIES =\n 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties';\n\n/** XML Schema Instance namespace */\nexport const NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance';\n\n// ============================================\n// Markup Compatibility\n// ============================================\n\n/** Markup Compatibility namespace (mc:) */\nexport const NS_MC = 'http://schemas.openxmlformats.org/markup-compatibility/2006';\n\n/** Office relationships namespace (r:) */\nexport const NS_R = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';\n\n// ============================================\n// Content type strings\n// ============================================\n\nexport const CONTENT_TYPE_RELATIONSHIPS =\n 'application/vnd.openxmlformats-package.relationships+xml';\n\nexport const CONTENT_TYPE_CORE_PROPERTIES =\n 'application/vnd.openxmlformats-package.core-properties+xml';\n\nexport const CONTENT_TYPE_DOCX_DOCUMENT =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml';\n\nexport const CONTENT_TYPE_DOCX_STYLES =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml';\n\nexport const CONTENT_TYPE_DOCX_NUMBERING =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml';\n\nexport const CONTENT_TYPE_DOCX_SETTINGS =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml';\n\nexport const CONTENT_TYPE_DOCX_FONT_TABLE =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml';\n\nexport const CONTENT_TYPE_DOCX_FOOTNOTES =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml';\n\nexport const CONTENT_TYPE_PPTX_PRESENTATION =\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE =\n 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE_LAYOUT =\n 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml';\n\nexport const CONTENT_TYPE_PPTX_SLIDE_MASTER =\n 'application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml';\n\nexport const CONTENT_TYPE_PPTX_THEME = 'application/vnd.openxmlformats-officedocument.theme+xml';\n\n/** Relationship type: Slide */\nexport const REL_SLIDE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide';\n\n/** Relationship type: Slide layout */\nexport const REL_SLIDE_LAYOUT =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout';\n\n/** Relationship type: Slide master */\nexport const REL_SLIDE_MASTER =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster';\n\nexport const CONTENT_TYPE_XLSX_WORKBOOK =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml';\n","/**\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","/**\n * OOXML Package Writer\n *\n * Builds OOXML archives (.docx, .pptx, .xlsx) from parts.\n * Handles automatic generation of [Content_Types].xml and\n * _rels/*.rels files from the registered parts and relationships.\n */\n\nimport JSZip from 'jszip';\nimport type { CoreProperties, PackagePart, PendingRelationship, Relationship } from './types.js';\nimport {\n NS_CONTENT_TYPES,\n NS_RELATIONSHIPS,\n NS_CORE_PROPERTIES,\n NS_DC,\n NS_DCTERMS,\n NS_XSI,\n CONTENT_TYPE_RELATIONSHIPS,\n CONTENT_TYPE_CORE_PROPERTIES,\n REL_CORE_PROPERTIES,\n} from './namespaces.js';\nimport { xmlDeclaration, escapeXml } from './xmlUtils.js';\n\n// ============================================\n// Package Builder\n// ============================================\n\n/**\n * Mutable builder for constructing an OOXML package.\n *\n * Add parts, relationships, and core properties, then call `toBlob()`\n * or `toArrayBuffer()` to produce the final ZIP archive.\n *\n * @example\n * ```ts\n * const builder = createPackage();\n * builder.addPart('word/document.xml', documentXml, CONTENT_TYPE_DOCX_DOCUMENT);\n * builder.addRelationship('', {\n * id: 'rId1',\n * type: REL_OFFICE_DOCUMENT,\n * target: 'word/document.xml',\n * });\n * const blob = await builder.toBlob();\n * ```\n */\nexport interface OoxmlPackageBuilder {\n /**\n * Add an XML or text part to the package.\n *\n * @param path - Path within the archive (e.g., \"word/document.xml\")\n * @param content - XML string content\n * @param contentType - MIME content type for [Content_Types].xml\n */\n addPart(path: string, content: string, contentType: string): void;\n\n /**\n * Add a binary part to the package (e.g., an image).\n *\n * @param path - Path within the archive (e.g., \"word/media/image1.png\")\n * @param data - Binary content\n * @param contentType - MIME content type (e.g., \"image/png\")\n */\n addBinaryPart(path: string, data: ArrayBuffer | Uint8Array, contentType: string): void;\n\n /**\n * Register a relationship.\n *\n * @param sourcePart - The part this relationship belongs to (e.g., \"word/document.xml\").\n * Use \"\" (empty string) for root-level relationships (_rels/.rels).\n * @param rel - The relationship entry\n */\n addRelationship(sourcePart: string, rel: Relationship): void;\n\n /**\n * Set core document properties (docProps/core.xml).\n * Calling this multiple times overwrites previous values.\n */\n setCoreProperties(props: CoreProperties): void;\n\n /**\n * Assemble the final OOXML package as a Blob.\n * Generates [Content_Types].xml and all _rels/*.rels files automatically.\n */\n toBlob(): Promise<Blob>;\n\n /**\n * Assemble the final OOXML package as an ArrayBuffer.\n */\n toArrayBuffer(): Promise<ArrayBuffer>;\n}\n\n/**\n * Create a new OOXML package builder.\n */\nexport function createPackage(): OoxmlPackageBuilder {\n const parts: PackagePart[] = [];\n const relationships: PendingRelationship[] = [];\n let coreProps: CoreProperties | undefined;\n\n return {\n addPart(path, content, contentType) {\n parts.push({ path, content, contentType });\n },\n\n addBinaryPart(path, data, contentType) {\n parts.push({ path, binaryContent: data, contentType });\n },\n\n addRelationship(sourcePart, rel) {\n relationships.push({ sourcePart, relationship: rel });\n },\n\n setCoreProperties(props) {\n coreProps = props;\n },\n\n async toBlob() {\n const zip = assemble(parts, relationships, coreProps);\n return zip.generateAsync({ type: 'blob' });\n },\n\n async toArrayBuffer() {\n const zip = assemble(parts, relationships, coreProps);\n return zip.generateAsync({ type: 'arraybuffer' });\n },\n };\n}\n\n// ============================================\n// Assembly\n// ============================================\n\n/**\n * Assemble a JSZip archive from parts, relationships, and core properties.\n */\nfunction assemble(\n parts: PackagePart[],\n relationships: PendingRelationship[],\n coreProps?: CoreProperties,\n): JSZip {\n const zip = new JSZip();\n\n // Write content parts\n for (const part of parts) {\n if (part.content !== undefined) {\n zip.file(part.path, part.content);\n } else if (part.binaryContent !== undefined) {\n zip.file(part.path, part.binaryContent);\n }\n }\n\n // Add core properties if set\n if (coreProps) {\n const coreXml = buildCorePropertiesXml(coreProps);\n zip.file('docProps/core.xml', coreXml);\n\n // Add relationship to core properties\n relationships.push({\n sourcePart: '',\n relationship: {\n id: `rId${relationships.length + 100}`,\n type: REL_CORE_PROPERTIES,\n target: 'docProps/core.xml',\n },\n });\n }\n\n // Build and write [Content_Types].xml\n zip.file('[Content_Types].xml', buildContentTypesXml(parts, coreProps));\n\n // Build and write _rels/*.rels files\n const relsBySource = groupRelationshipsBySource(relationships);\n for (const [sourcePart, rels] of relsBySource) {\n const relsPath = sourcePart === '' ? '_rels/.rels' : buildRelsPath(sourcePart);\n zip.file(relsPath, buildRelationshipsXml(rels));\n }\n\n return zip;\n}\n\n// ============================================\n// [Content_Types].xml\n// ============================================\n\nfunction buildContentTypesXml(parts: PackagePart[], coreProps?: CoreProperties): string {\n const lines: string[] = [xmlDeclaration()];\n lines.push(`<Types xmlns=\"${NS_CONTENT_TYPES}\">`);\n\n // Default extension types\n const extensionTypes = new Map<string, string>();\n extensionTypes.set('rels', CONTENT_TYPE_RELATIONSHIPS);\n extensionTypes.set('xml', 'application/xml');\n\n // Collect extensions from binary parts (e.g., png, jpeg)\n for (const part of parts) {\n if (part.binaryContent !== undefined) {\n const ext = getExtension(part.path);\n if (ext && !extensionTypes.has(ext)) {\n extensionTypes.set(ext, part.contentType);\n }\n }\n }\n\n for (const [ext, ct] of extensionTypes) {\n lines.push(` <Default Extension=\"${escapeXml(ext)}\" ContentType=\"${escapeXml(ct)}\"/>`);\n }\n\n // Override entries for each XML part\n for (const part of parts) {\n if (part.content !== undefined) {\n lines.push(\n ` <Override PartName=\"/${escapeXml(part.path)}\" ContentType=\"${escapeXml(part.contentType)}\"/>`,\n );\n }\n }\n\n // Core properties override\n if (coreProps) {\n lines.push(\n ` <Override PartName=\"/docProps/core.xml\" ContentType=\"${CONTENT_TYPE_CORE_PROPERTIES}\"/>`,\n );\n }\n\n lines.push('</Types>');\n return lines.join('\\n');\n}\n\n// ============================================\n// Relationships XML\n// ============================================\n\nfunction buildRelationshipsXml(rels: Relationship[]): string {\n const lines: string[] = [xmlDeclaration()];\n lines.push(`<Relationships xmlns=\"${NS_RELATIONSHIPS}\">`);\n\n for (const rel of rels) {\n const attrs: string[] = [\n `Id=\"${escapeXml(rel.id)}\"`,\n `Type=\"${escapeXml(rel.type)}\"`,\n `Target=\"${escapeXml(rel.target)}\"`,\n ];\n if (rel.targetMode) {\n attrs.push(`TargetMode=\"${escapeXml(rel.targetMode)}\"`);\n }\n lines.push(` <Relationship ${attrs.join(' ')}/>`);\n }\n\n lines.push('</Relationships>');\n return lines.join('\\n');\n}\n\n// ============================================\n// Core Properties XML\n// ============================================\n\nfunction buildCorePropertiesXml(props: CoreProperties): string {\n const lines: string[] = [xmlDeclaration()];\n lines.push(\n `<cp:coreProperties` +\n ` xmlns:cp=\"${NS_CORE_PROPERTIES}\"` +\n ` xmlns:dc=\"${NS_DC}\"` +\n ` xmlns:dcterms=\"${NS_DCTERMS}\"` +\n ` xmlns:xsi=\"${NS_XSI}\">`,\n );\n\n if (props.title) lines.push(` <dc:title>${escapeXml(props.title)}</dc:title>`);\n if (props.subject) lines.push(` <dc:subject>${escapeXml(props.subject)}</dc:subject>`);\n if (props.creator) lines.push(` <dc:creator>${escapeXml(props.creator)}</dc:creator>`);\n if (props.description)\n lines.push(` <dc:description>${escapeXml(props.description)}</dc:description>`);\n if (props.keywords) lines.push(` <cp:keywords>${escapeXml(props.keywords)}</cp:keywords>`);\n if (props.lastModifiedBy)\n lines.push(` <cp:lastModifiedBy>${escapeXml(props.lastModifiedBy)}</cp:lastModifiedBy>`);\n if (props.revision) lines.push(` <cp:revision>${escapeXml(props.revision)}</cp:revision>`);\n if (props.created) {\n lines.push(\n ` <dcterms:created xsi:type=\"dcterms:W3CDTF\">${escapeXml(props.created)}</dcterms:created>`,\n );\n }\n if (props.modified) {\n lines.push(\n ` <dcterms:modified xsi:type=\"dcterms:W3CDTF\">${escapeXml(props.modified)}</dcterms:modified>`,\n );\n }\n\n lines.push('</cp:coreProperties>');\n return lines.join('\\n');\n}\n\n// ============================================\n// Helpers\n// ============================================\n\nfunction getExtension(path: string): string | undefined {\n const dot = path.lastIndexOf('.');\n if (dot === -1) return undefined;\n return path.substring(dot + 1).toLowerCase();\n}\n\nfunction buildRelsPath(partPath: string): string {\n const lastSlash = partPath.lastIndexOf('/');\n if (lastSlash === -1) {\n return `_rels/${partPath}.rels`;\n }\n const dir = partPath.substring(0, lastSlash);\n const file = partPath.substring(lastSlash + 1);\n return `${dir}/_rels/${file}.rels`;\n}\n\nfunction groupRelationshipsBySource(pending: PendingRelationship[]): Map<string, Relationship[]> {\n const grouped = new Map<string, Relationship[]>();\n for (const { sourcePart, relationship } of pending) {\n let list = grouped.get(sourcePart);\n if (!list) {\n list = [];\n grouped.set(sourcePart, list);\n }\n list.push(relationship);\n }\n return grouped;\n}\n"],"mappings":"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","names":[]}