@bendyline/squisq-formats 1.3.1 → 1.4.1

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 (107) hide show
  1. package/README.md +180 -43
  2. package/dist/{chunk-33YRFXZZ.js → chunk-46FMDOWZ.js} +260 -14
  3. package/dist/chunk-46FMDOWZ.js.map +1 -0
  4. package/dist/{chunk-ERZ627GR.js → chunk-5LSSWZPU.js} +12 -27
  5. package/dist/chunk-5LSSWZPU.js.map +1 -0
  6. package/dist/chunk-6M7Z25LA.js +46 -0
  7. package/dist/chunk-6M7Z25LA.js.map +1 -0
  8. package/dist/{chunk-S3Y7H2BK.js → chunk-D7IFPWNZ.js} +95 -50
  9. package/dist/chunk-D7IFPWNZ.js.map +1 -0
  10. package/dist/chunk-DQAZR57U.js +33 -0
  11. package/dist/chunk-DQAZR57U.js.map +1 -0
  12. package/dist/chunk-EHLGMSTE.js +273 -0
  13. package/dist/chunk-EHLGMSTE.js.map +1 -0
  14. package/dist/{chunk-A3FHLTY5.js → chunk-MJGRI6XR.js} +6 -19
  15. package/dist/chunk-MJGRI6XR.js.map +1 -0
  16. package/dist/chunk-PN52A5AA.js +32 -0
  17. package/dist/chunk-PN52A5AA.js.map +1 -0
  18. package/dist/chunk-RFAPOKHJ.js +123 -0
  19. package/dist/chunk-RFAPOKHJ.js.map +1 -0
  20. package/dist/chunk-RTS5XBZ7.js +526 -0
  21. package/dist/chunk-RTS5XBZ7.js.map +1 -0
  22. package/dist/{chunk-7DEUGIOO.js → chunk-SHLPSADL.js} +120 -2
  23. package/dist/chunk-SHLPSADL.js.map +1 -0
  24. package/dist/chunk-SSUPBUF5.js +15 -0
  25. package/dist/chunk-SSUPBUF5.js.map +1 -0
  26. package/dist/{chunk-UDS45KUJ.js → chunk-WWBIKRNP.js} +40 -80
  27. package/dist/chunk-WWBIKRNP.js.map +1 -0
  28. package/dist/{chunk-VN2KEOYB.js → chunk-YESS7VY3.js} +379 -87
  29. package/dist/chunk-YESS7VY3.js.map +1 -0
  30. package/dist/csv/index.d.ts +50 -0
  31. package/dist/csv/index.js +13 -0
  32. package/dist/csv/index.js.map +1 -0
  33. package/dist/docx/index.js +6 -3
  34. package/dist/epub/index.js +4 -2
  35. package/dist/html/index.d.ts +42 -2
  36. package/dist/html/index.js +9 -2
  37. package/dist/index.d.ts +3 -1
  38. package/dist/index.js +47 -14
  39. package/dist/ooxml/index.d.ts +5 -1
  40. package/dist/ooxml/index.js +13 -9
  41. package/dist/pdf/index.js +2 -1
  42. package/dist/pptx/index.d.ts +36 -19
  43. package/dist/pptx/index.js +9 -2
  44. package/dist/registry/index.d.ts +167 -0
  45. package/dist/registry/index.js +17 -0
  46. package/dist/registry/index.js.map +1 -0
  47. package/dist/xlsx/index.d.ts +60 -29
  48. package/dist/xlsx/index.js +4 -1
  49. package/package.json +12 -2
  50. package/src/__tests__/convert.test.ts +186 -0
  51. package/src/__tests__/csvImport.test.ts +84 -0
  52. package/src/__tests__/exportThemeReconciliation.test.ts +87 -0
  53. package/src/__tests__/formatRegistry.test.ts +174 -0
  54. package/src/__tests__/htmlImport.test.ts +57 -0
  55. package/src/__tests__/lossyWarnings.test.ts +105 -0
  56. package/src/__tests__/pdfImport.test.ts +95 -1
  57. package/src/__tests__/plainHtml.test.ts +31 -0
  58. package/src/__tests__/pptxExport.test.ts +138 -0
  59. package/src/__tests__/pptxImport.test.ts +115 -0
  60. package/src/__tests__/roundTripAssets.test.ts +50 -0
  61. package/src/__tests__/roundTripMatrix.fixtures.ts +86 -0
  62. package/src/__tests__/roundTripMatrix.helpers.ts +154 -0
  63. package/src/__tests__/roundTripMatrix.test.ts +142 -0
  64. package/src/__tests__/sharedContainer.test.ts +41 -0
  65. package/src/__tests__/sharedImages.test.ts +61 -0
  66. package/src/__tests__/xlsxExport.test.ts +164 -0
  67. package/src/__tests__/xlsxImport.test.ts +80 -0
  68. package/src/csv/index.ts +188 -0
  69. package/src/docx/export.ts +27 -44
  70. package/src/docx/import.ts +7 -39
  71. package/src/epub/export.ts +10 -27
  72. package/src/html/imageUtils.ts +5 -19
  73. package/src/html/import.ts +297 -0
  74. package/src/html/index.ts +4 -0
  75. package/src/html/plainHtml.ts +66 -16
  76. package/src/index.ts +36 -5
  77. package/src/ooxml/index.ts +3 -0
  78. package/src/ooxml/namespaces.ts +13 -0
  79. package/src/pdf/export.ts +10 -5
  80. package/src/pdf/import.ts +146 -51
  81. package/src/pptx/export.ts +225 -85
  82. package/src/pptx/import.ts +273 -0
  83. package/src/pptx/index.ts +10 -28
  84. package/src/registry/convert.ts +318 -0
  85. package/src/registry/defaultFormats.ts +323 -0
  86. package/src/registry/errors.ts +46 -0
  87. package/src/registry/index.ts +38 -0
  88. package/src/registry/registry.ts +48 -0
  89. package/src/registry/types.ts +107 -0
  90. package/src/shared/container.ts +28 -0
  91. package/src/shared/images.ts +44 -0
  92. package/src/shared/inlineRuns.ts +99 -0
  93. package/src/shared/text.ts +41 -0
  94. package/src/xlsx/export.ts +253 -0
  95. package/src/xlsx/import.ts +159 -0
  96. package/src/xlsx/index.ts +18 -61
  97. package/dist/chunk-33YRFXZZ.js.map +0 -1
  98. package/dist/chunk-67KIJHV2.js +0 -21
  99. package/dist/chunk-67KIJHV2.js.map +0 -1
  100. package/dist/chunk-7DEUGIOO.js.map +0 -1
  101. package/dist/chunk-A3FHLTY5.js.map +0 -1
  102. package/dist/chunk-ERZ627GR.js.map +0 -1
  103. package/dist/chunk-S3Y7H2BK.js.map +0 -1
  104. package/dist/chunk-UDS45KUJ.js.map +0 -1
  105. package/dist/chunk-VN2KEOYB.js.map +0 -1
  106. package/dist/chunk-YN5HFCEW.js +0 -120
  107. package/dist/chunk-YN5HFCEW.js.map +0 -1
@@ -19,6 +19,7 @@ var REL_FOOTNOTES = "http://schemas.openxmlformats.org/officeDocument/2006/relat
19
19
  var REL_THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
20
20
  var NS_WML = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
21
21
  var NS_PML = "http://schemas.openxmlformats.org/presentationml/2006/main";
22
+ var NS_PML_2010 = "http://schemas.microsoft.com/office/powerpoint/2010/main";
22
23
  var NS_SML = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
23
24
  var NS_DRAWINGML = "http://schemas.openxmlformats.org/drawingml/2006/main";
24
25
  var NS_WP_DRAWING = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
@@ -46,6 +47,9 @@ var REL_SLIDE = "http://schemas.openxmlformats.org/officeDocument/2006/relations
46
47
  var REL_SLIDE_LAYOUT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout";
47
48
  var REL_SLIDE_MASTER = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster";
48
49
  var CONTENT_TYPE_XLSX_WORKBOOK = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
50
+ var CONTENT_TYPE_XLSX_WORKSHEET = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
51
+ var CONTENT_TYPE_XLSX_STYLES = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml";
52
+ var REL_WORKSHEET = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
49
53
 
50
54
  // src/ooxml/writer.ts
51
55
  import JSZip from "jszip";
@@ -208,6 +212,111 @@ function groupRelationshipsBySource(pending) {
208
212
  return grouped;
209
213
  }
210
214
 
215
+ // src/ooxml/reader.ts
216
+ import JSZip2 from "jszip";
217
+ async function openPackage(data) {
218
+ const zip = await JSZip2.loadAsync(data);
219
+ const contentTypes = await parseContentTypes(zip);
220
+ const rootRelationships = await parseRelationships(zip, "");
221
+ return { zip, contentTypes, rootRelationships };
222
+ }
223
+ async function parseContentTypes(zip) {
224
+ const overrides = /* @__PURE__ */ new Map();
225
+ const defaults = /* @__PURE__ */ new Map();
226
+ const file = zip.file("[Content_Types].xml");
227
+ if (!file) return { overrides, defaults };
228
+ const text = await file.async("text");
229
+ const doc = new DOMParser().parseFromString(text, "application/xml");
230
+ const defaultEls = doc.getElementsByTagName("Default");
231
+ for (let i = 0; i < defaultEls.length; i++) {
232
+ const el = defaultEls[i];
233
+ const ext = el.getAttribute("Extension");
234
+ const ct = el.getAttribute("ContentType");
235
+ if (ext && ct) defaults.set(ext, ct);
236
+ }
237
+ const overrideEls = doc.getElementsByTagName("Override");
238
+ for (let i = 0; i < overrideEls.length; i++) {
239
+ const el = overrideEls[i];
240
+ const partName = el.getAttribute("PartName");
241
+ const ct = el.getAttribute("ContentType");
242
+ if (partName && ct) {
243
+ overrides.set(partName.replace(/^\//, ""), ct);
244
+ }
245
+ }
246
+ return { overrides, defaults };
247
+ }
248
+ async function getPartRelationships(pkg, partPath) {
249
+ return parseRelationships(pkg.zip, partPath);
250
+ }
251
+ async function parseRelationships(zip, partPath) {
252
+ const relsPath = partPath === "" ? "_rels/.rels" : buildRelsPath2(partPath);
253
+ const file = zip.file(relsPath);
254
+ if (!file) return [];
255
+ const text = await file.async("text");
256
+ const doc = new DOMParser().parseFromString(text, "application/xml");
257
+ const result = [];
258
+ const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, "Relationship");
259
+ const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName("Relationship");
260
+ for (let i = 0; i < fallbackEls.length; i++) {
261
+ const el = fallbackEls[i];
262
+ const id = el.getAttribute("Id");
263
+ const type = el.getAttribute("Type");
264
+ const target = el.getAttribute("Target");
265
+ if (id && type && target) {
266
+ const targetMode = el.getAttribute("TargetMode");
267
+ result.push({
268
+ id,
269
+ type,
270
+ target,
271
+ ...targetMode ? { targetMode } : {}
272
+ });
273
+ }
274
+ }
275
+ return result;
276
+ }
277
+ function buildRelsPath2(partPath) {
278
+ const lastSlash = partPath.lastIndexOf("/");
279
+ if (lastSlash === -1) {
280
+ return `_rels/${partPath}.rels`;
281
+ }
282
+ const dir = partPath.substring(0, lastSlash);
283
+ const file = partPath.substring(lastSlash + 1);
284
+ return `${dir}/_rels/${file}.rels`;
285
+ }
286
+ async function getPartXml(pkg, partPath) {
287
+ const file = pkg.zip.file(partPath);
288
+ if (!file) return null;
289
+ const text = await file.async("text");
290
+ return new DOMParser().parseFromString(text, "application/xml");
291
+ }
292
+ async function getPartBinary(pkg, partPath) {
293
+ const file = pkg.zip.file(partPath);
294
+ if (!file) return null;
295
+ return file.async("arraybuffer");
296
+ }
297
+ async function getCoreProperties(pkg) {
298
+ const doc = await getPartXml(pkg, "docProps/core.xml");
299
+ if (!doc) return {};
300
+ function getText(ns, localName) {
301
+ const els = doc.getElementsByTagNameNS(ns, localName);
302
+ if (els.length > 0 && els[0].textContent) {
303
+ return els[0].textContent;
304
+ }
305
+ return void 0;
306
+ }
307
+ return {
308
+ title: getText(NS_DC, "title"),
309
+ subject: getText(NS_DC, "subject"),
310
+ creator: getText(NS_DC, "creator"),
311
+ description: getText(NS_DC, "description"),
312
+ keywords: getText(NS_CORE_PROPERTIES, "keywords"),
313
+ lastModifiedBy: getText(NS_CORE_PROPERTIES, "lastModifiedBy"),
314
+ revision: getText(NS_CORE_PROPERTIES, "revision"),
315
+ created: getText(NS_DCTERMS, "created"),
316
+ modified: getText(NS_DCTERMS, "modified")
317
+ };
318
+ }
319
+
211
320
  export {
212
321
  NS_RELATIONSHIPS,
213
322
  NS_CONTENT_TYPES,
@@ -224,6 +333,7 @@ export {
224
333
  REL_THEME,
225
334
  NS_WML,
226
335
  NS_PML,
336
+ NS_PML_2010,
227
337
  NS_SML,
228
338
  NS_DRAWINGML,
229
339
  NS_WP_DRAWING,
@@ -251,6 +361,14 @@ export {
251
361
  REL_SLIDE_LAYOUT,
252
362
  REL_SLIDE_MASTER,
253
363
  CONTENT_TYPE_XLSX_WORKBOOK,
254
- createPackage
364
+ CONTENT_TYPE_XLSX_WORKSHEET,
365
+ CONTENT_TYPE_XLSX_STYLES,
366
+ REL_WORKSHEET,
367
+ createPackage,
368
+ openPackage,
369
+ getPartRelationships,
370
+ getPartXml,
371
+ getPartBinary,
372
+ getCoreProperties
255
373
  };
256
- //# sourceMappingURL=chunk-7DEUGIOO.js.map
374
+ //# sourceMappingURL=chunk-SHLPSADL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ooxml/namespaces.ts","../src/ooxml/writer.ts","../src/ooxml/reader.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/** PowerPoint 2010 extension namespace (p14:) */\nexport const NS_PML_2010 = 'http://schemas.microsoft.com/office/powerpoint/2010/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\nexport const CONTENT_TYPE_XLSX_WORKSHEET =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml';\n\nexport const CONTENT_TYPE_XLSX_STYLES =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml';\n\n/** Relationship type: Worksheet */\nexport const REL_WORKSHEET =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet';\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","/**\n * OOXML Package Reader\n *\n * Opens OOXML archives (.docx, .pptx, .xlsx) and parses their\n * structural metadata: [Content_Types].xml, relationships, and\n * core properties.\n *\n * Uses JSZip to unzip and the browser's DOMParser to parse XML.\n */\n\nimport JSZip from 'jszip';\nimport type { OoxmlPackage, ContentTypeMap, Relationship, CoreProperties } from './types.js';\nimport { NS_RELATIONSHIPS, NS_DC, NS_DCTERMS, NS_CORE_PROPERTIES } from './namespaces.js';\n\n// ============================================\n// Package Opening\n// ============================================\n\n/**\n * Open an OOXML package from raw data.\n *\n * Parses the ZIP archive, [Content_Types].xml, and root relationships.\n *\n * @param data - The raw .docx/.pptx/.xlsx file as ArrayBuffer or Blob\n * @returns A parsed OoxmlPackage\n */\nexport async function openPackage(data: ArrayBuffer | Blob): Promise<OoxmlPackage> {\n const zip = await JSZip.loadAsync(data);\n const contentTypes = await parseContentTypes(zip);\n const rootRelationships = await parseRelationships(zip, '');\n\n return { zip, contentTypes, rootRelationships };\n}\n\n// ============================================\n// Content Types\n// ============================================\n\n/**\n * Parse [Content_Types].xml from the archive.\n */\nasync function parseContentTypes(zip: JSZip): Promise<ContentTypeMap> {\n const overrides = new Map<string, string>();\n const defaults = new Map<string, string>();\n\n const file = zip.file('[Content_Types].xml');\n if (!file) return { overrides, defaults };\n\n const text = await file.async('text');\n const doc = new DOMParser().parseFromString(text, 'application/xml');\n\n // Parse <Default Extension=\"rels\" ContentType=\"...\" />\n const defaultEls = doc.getElementsByTagName('Default');\n for (let i = 0; i < defaultEls.length; i++) {\n const el = defaultEls[i];\n const ext = el.getAttribute('Extension');\n const ct = el.getAttribute('ContentType');\n if (ext && ct) defaults.set(ext, ct);\n }\n\n // Parse <Override PartName=\"/word/document.xml\" ContentType=\"...\" />\n const overrideEls = doc.getElementsByTagName('Override');\n for (let i = 0; i < overrideEls.length; i++) {\n const el = overrideEls[i];\n const partName = el.getAttribute('PartName');\n const ct = el.getAttribute('ContentType');\n if (partName && ct) {\n // Normalize: strip leading slash\n overrides.set(partName.replace(/^\\//, ''), ct);\n }\n }\n\n return { overrides, defaults };\n}\n\n// ============================================\n// Relationships\n// ============================================\n\n/**\n * Parse relationships for a specific part.\n *\n * @param pkg - The OOXML package (or the zip directly)\n * @param partPath - The part path (e.g., \"word/document.xml\").\n * Use \"\" for root-level relationships (_rels/.rels).\n * @returns Array of relationship entries\n */\nexport async function getPartRelationships(\n pkg: OoxmlPackage,\n partPath: string,\n): Promise<Relationship[]> {\n return parseRelationships(pkg.zip, partPath);\n}\n\n/**\n * Parse a _rels/*.rels file from the ZIP.\n *\n * For root relationships, relsPath = \"_rels/.rels\".\n * For part relationships, relsPath = \"<dir>/_rels/<filename>.rels\".\n */\nasync function parseRelationships(zip: JSZip, partPath: string): Promise<Relationship[]> {\n const relsPath = partPath === '' ? '_rels/.rels' : buildRelsPath(partPath);\n\n const file = zip.file(relsPath);\n if (!file) return [];\n\n const text = await file.async('text');\n const doc = new DOMParser().parseFromString(text, 'application/xml');\n const result: Relationship[] = [];\n\n const els = doc.getElementsByTagNameNS(NS_RELATIONSHIPS, 'Relationship');\n // Fallback in case namespace isn't used (some generators omit it)\n const fallbackEls = els.length > 0 ? els : doc.getElementsByTagName('Relationship');\n\n for (let i = 0; i < fallbackEls.length; i++) {\n const el = fallbackEls[i];\n const id = el.getAttribute('Id');\n const type = el.getAttribute('Type');\n const target = el.getAttribute('Target');\n if (id && type && target) {\n const targetMode = el.getAttribute('TargetMode') as 'Internal' | 'External' | null;\n result.push({\n id,\n type,\n target,\n ...(targetMode ? { targetMode } : {}),\n });\n }\n }\n\n return result;\n}\n\n/**\n * Build the _rels path for a given part path.\n *\n * \"word/document.xml\" → \"word/_rels/document.xml.rels\"\n * \"xl/workbook.xml\" → \"xl/_rels/workbook.xml.rels\"\n */\nfunction buildRelsPath(partPath: string): string {\n const lastSlash = partPath.lastIndexOf('/');\n if (lastSlash === -1) {\n return `_rels/${partPath}.rels`;\n }\n const dir = partPath.substring(0, lastSlash);\n const file = partPath.substring(lastSlash + 1);\n return `${dir}/_rels/${file}.rels`;\n}\n\n// ============================================\n// Part Access\n// ============================================\n\n/**\n * Extract an XML part from the package and parse it as a DOM Document.\n *\n * @param pkg - The OOXML package\n * @param partPath - Path within the archive (e.g., \"word/document.xml\")\n * @returns Parsed XML Document, or null if the part doesn't exist\n */\nexport async function getPartXml(pkg: OoxmlPackage, partPath: string): Promise<Document | null> {\n const file = pkg.zip.file(partPath);\n if (!file) return null;\n\n const text = await file.async('text');\n return new DOMParser().parseFromString(text, 'application/xml');\n}\n\n/**\n * Extract a binary part from the package (e.g., an image from word/media/).\n *\n * @param pkg - The OOXML package\n * @param partPath - Path within the archive\n * @returns The binary content, or null if the part doesn't exist\n */\nexport async function getPartBinary(\n pkg: OoxmlPackage,\n partPath: string,\n): Promise<ArrayBuffer | null> {\n const file = pkg.zip.file(partPath);\n if (!file) return null;\n return file.async('arraybuffer');\n}\n\n// ============================================\n// Core Properties\n// ============================================\n\n/**\n * Parse core document properties from docProps/core.xml.\n *\n * @param pkg - The OOXML package\n * @returns Parsed core properties (all fields optional)\n */\nexport async function getCoreProperties(pkg: OoxmlPackage): Promise<CoreProperties> {\n const doc = await getPartXml(pkg, 'docProps/core.xml');\n if (!doc) return {};\n\n function getText(ns: string, localName: string): string | undefined {\n const els = doc!.getElementsByTagNameNS(ns, localName);\n if (els.length > 0 && els[0].textContent) {\n return els[0].textContent;\n }\n return undefined;\n }\n\n return {\n title: getText(NS_DC, 'title'),\n subject: getText(NS_DC, 'subject'),\n creator: getText(NS_DC, 'creator'),\n description: getText(NS_DC, 'description'),\n keywords: getText(NS_CORE_PROPERTIES, 'keywords'),\n lastModifiedBy: getText(NS_CORE_PROPERTIES, 'lastModifiedBy'),\n revision: getText(NS_CORE_PROPERTIES, 'revision'),\n created: getText(NS_DCTERMS, 'created'),\n modified: getText(NS_DCTERMS, 'modified'),\n };\n}\n"],"mappings":"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","names":["JSZip","JSZip","buildRelsPath"]}
@@ -0,0 +1,15 @@
1
+ // src/shared/container.ts
2
+ import { MemoryContentContainer } from "@bendyline/squisq/storage";
3
+ async function buildContainer(markdown, images) {
4
+ const container = new MemoryContentContainer();
5
+ await container.writeDocument(markdown);
6
+ for (const [path, { data, mimeType }] of images) {
7
+ await container.writeFile(path, new Uint8Array(data), mimeType);
8
+ }
9
+ return container;
10
+ }
11
+
12
+ export {
13
+ buildContainer
14
+ };
15
+ //# sourceMappingURL=chunk-SSUPBUF5.js.map
@@ -0,0 +1 @@
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,9 +1,10 @@
1
1
  import {
2
- getPartBinary,
3
- getPartRelationships,
4
- getPartXml,
5
- openPackage
6
- } from "./chunk-YN5HFCEW.js";
2
+ inlineNodeToRuns,
3
+ inlineNodesToRuns
4
+ } from "./chunk-6M7Z25LA.js";
5
+ import {
6
+ stripHtmlTags
7
+ } from "./chunk-PN52A5AA.js";
7
8
  import {
8
9
  CONTENT_TYPE_DOCX_DOCUMENT,
9
10
  CONTENT_TYPE_DOCX_FONT_TABLE,
@@ -22,16 +23,26 @@ import {
22
23
  REL_OFFICE_DOCUMENT,
23
24
  REL_SETTINGS,
24
25
  REL_STYLES,
25
- createPackage
26
- } from "./chunk-7DEUGIOO.js";
26
+ createPackage,
27
+ getPartBinary,
28
+ getPartRelationships,
29
+ getPartXml,
30
+ openPackage
31
+ } from "./chunk-SHLPSADL.js";
27
32
  import {
28
33
  escapeXml,
29
34
  xmlDeclaration
30
35
  } from "./chunk-U4MRIFKL.js";
36
+ import {
37
+ buildContainer
38
+ } from "./chunk-SSUPBUF5.js";
39
+ import {
40
+ extToMime
41
+ } from "./chunk-DQAZR57U.js";
31
42
 
32
43
  // src/docx/export.ts
33
- import { resolveTheme, resolveFontFamily } from "@bendyline/squisq/schemas";
34
- import { docToMarkdown } from "@bendyline/squisq/doc";
44
+ import { resolveFontFamily } from "@bendyline/squisq/schemas";
45
+ import { docToMarkdown, resolveThemeForDoc } from "@bendyline/squisq/doc";
35
46
  import { readFrontmatterThemeId } from "@bendyline/squisq/markdown";
36
47
 
37
48
  // src/docx/styles.ts
@@ -91,7 +102,7 @@ function pointsToTwips(points) {
91
102
  // src/docx/export.ts
92
103
  async function markdownDocToDocx(doc, options = {}) {
93
104
  const resolvedOptions = options.themeId !== void 0 ? options : { ...options, themeId: readFrontmatterThemeId(doc.frontmatter) };
94
- const ctx = new ExportContext(resolvedOptions);
105
+ const ctx = new ExportContext(resolvedOptions, doc);
95
106
  const bodyXml = convertBlocks(doc.children, ctx);
96
107
  return buildDocxPackage(bodyXml, ctx, resolvedOptions);
97
108
  }
@@ -100,7 +111,7 @@ async function docToDocx(doc, options = {}) {
100
111
  return markdownDocToDocx(markdownDoc, options);
101
112
  }
102
113
  var ExportContext = class {
103
- constructor(options) {
114
+ constructor(options, doc) {
104
115
  this.nextRelId = 1;
105
116
  this.nextNumId = 1;
106
117
  this.nextFootnoteId = 1;
@@ -127,7 +138,7 @@ var ExportContext = class {
127
138
  let themeMutedColor;
128
139
  let themeBackgroundColor;
129
140
  if (options.themeId) {
130
- const theme = resolveTheme(options.themeId);
141
+ const theme = resolveThemeForDoc(doc, options.themeId);
131
142
  themeFont = firstFontFromStack(resolveFontFamily(theme.typography?.bodyFont, ""));
132
143
  themeTitleFont = firstFontFromStack(resolveFontFamily(theme.typography?.titleFont, ""));
133
144
  const stripHash = (c) => c.startsWith("#") ? c.slice(1) : c;
@@ -359,40 +370,20 @@ function convertFootnoteDefinition(node, ctx) {
359
370
  ctx.footnotes.set(fnId, footnoteXml);
360
371
  return "";
361
372
  }
373
+ function docxRunHandlers(ctx) {
374
+ return {
375
+ run: (text, format) => makeRun(text, format),
376
+ link: (node, format) => convertLink(node, ctx, format),
377
+ image: (node) => convertImage(node, ctx),
378
+ lineBreak: () => `<w:r><w:br/></w:r>`,
379
+ footnoteRef: (node) => convertFootnoteRef(node, ctx)
380
+ };
381
+ }
362
382
  function convertInlines(nodes, ctx, format = {}) {
363
- const parts = [];
364
- for (const node of nodes) {
365
- parts.push(convertInline(node, ctx, format));
366
- }
367
- return parts.join("");
383
+ return inlineNodesToRuns(nodes, docxRunHandlers(ctx), format);
368
384
  }
369
385
  function convertInline(node, ctx, format) {
370
- switch (node.type) {
371
- case "text":
372
- return makeRun(node.value, format);
373
- case "strong":
374
- return convertInlines(node.children, ctx, { ...format, bold: true });
375
- case "emphasis":
376
- return convertInlines(node.children, ctx, { ...format, italic: true });
377
- case "delete":
378
- return convertInlines(node.children, ctx, { ...format, strike: true });
379
- case "inlineCode":
380
- return makeRun(node.value, { ...format, code: true });
381
- case "link":
382
- return convertLink(node, ctx, format);
383
- case "image":
384
- return convertImage(node, ctx);
385
- case "break":
386
- return `<w:r><w:br/></w:r>`;
387
- case "htmlInline":
388
- return makeRun(stripHtmlTags(node.rawHtml), format);
389
- case "inlineMath":
390
- return makeRun(node.value, { ...format, code: true });
391
- case "footnoteReference":
392
- return convertFootnoteRef(node, ctx);
393
- default:
394
- return "";
395
- }
386
+ return inlineNodeToRuns(node, docxRunHandlers(ctx), format);
396
387
  }
397
388
  function makeRun(text, format) {
398
389
  if (!text) return "";
@@ -658,13 +649,10 @@ function buildFootnotesXml(ctx) {
658
649
  }
659
650
  return xmlDeclaration() + `<w:footnotes xmlns:w="${NS_WML}" xmlns:r="${NS_R}">` + footnotes.join("") + `</w:footnotes>`;
660
651
  }
661
- function stripHtmlTags(html) {
662
- return html.replace(/<[^>]*>/g, "");
663
- }
664
652
 
665
653
  // src/docx/import.ts
666
654
  import { markdownToDoc } from "@bendyline/squisq/doc";
667
- import { MemoryContentContainer } from "@bendyline/squisq/storage";
655
+ import { stringifyMarkdown } from "@bendyline/squisq/markdown";
668
656
  async function docxToMarkdownDoc(data, options = {}) {
669
657
  const pkg = await openPackage(data);
670
658
  const ctx = await buildImportContext(pkg, options);
@@ -687,27 +675,12 @@ async function docxToContainer(data, options = {}) {
687
675
  const pkg = await openPackage(data);
688
676
  const ctx = await buildImportContext(pkg, { ...options, extractImages: true });
689
677
  const documentXml = await getPartXml(pkg, "word/document.xml");
690
- if (!documentXml) {
691
- const container2 = new MemoryContentContainer();
692
- await container2.writeDocument("");
693
- return container2;
694
- }
678
+ if (!documentXml) return buildContainer("", []);
695
679
  const body = getFirstElement(documentXml, "body");
696
- if (!body) {
697
- const container2 = new MemoryContentContainer();
698
- await container2.writeDocument("");
699
- return container2;
700
- }
680
+ if (!body) return buildContainer("", []);
701
681
  const blocks = await convertBody(body, ctx);
702
682
  const markdownDoc = { type: "document", children: blocks };
703
- const { stringifyMarkdown } = await import("@bendyline/squisq/markdown");
704
- const markdown = stringifyMarkdown(markdownDoc);
705
- const container = new MemoryContentContainer();
706
- await container.writeDocument(markdown);
707
- for (const [path, { data: imageData, mimeType }] of ctx.extractedImages) {
708
- await container.writeFile(path, new Uint8Array(imageData), mimeType);
709
- }
710
- return container;
683
+ return buildContainer(stringifyMarkdown(markdownDoc), ctx.extractedImages);
711
684
  }
712
685
  async function buildImportContext(pkg, options) {
713
686
  const ctx = {
@@ -998,7 +971,7 @@ async function extractImage(el, ctx) {
998
971
  }
999
972
  const dot = target.lastIndexOf(".");
1000
973
  const ext = dot !== -1 ? target.slice(dot).toLowerCase() : ".png";
1001
- const mimeType = IMAGE_MIME_MAP[ext] ?? "application/octet-stream";
974
+ const mimeType = extToMime(ext);
1002
975
  ctx.imageCounter++;
1003
976
  const imagePath = `images/image${ctx.imageCounter}${ext}`;
1004
977
  ctx.extractedImages.set(imagePath, { data, mimeType });
@@ -1010,19 +983,6 @@ async function extractImage(el, ctx) {
1010
983
  alt
1011
984
  };
1012
985
  }
1013
- var IMAGE_MIME_MAP = {
1014
- ".png": "image/png",
1015
- ".jpg": "image/jpeg",
1016
- ".jpeg": "image/jpeg",
1017
- ".gif": "image/gif",
1018
- ".bmp": "image/bmp",
1019
- ".tiff": "image/tiff",
1020
- ".tif": "image/tiff",
1021
- ".svg": "image/svg+xml",
1022
- ".webp": "image/webp",
1023
- ".emf": "image/emf",
1024
- ".wmf": "image/wmf"
1025
- };
1026
986
  function findDescendant(el, localName) {
1027
987
  for (const child of Array.from(el.children)) {
1028
988
  if (child.localName === localName) return child;
@@ -1247,4 +1207,4 @@ export {
1247
1207
  docxToDoc,
1248
1208
  docxToContainer
1249
1209
  };
1250
- //# sourceMappingURL=chunk-UDS45KUJ.js.map
1210
+ //# sourceMappingURL=chunk-WWBIKRNP.js.map