documents.js 1.40.0 → 1.42.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.
package/dist/index.js CHANGED
@@ -1,21 +1,30 @@
1
- import { AttributeSchema, BinaryPartSchema, CommentSchema, CompactPackageSchema, CompactPartSchema, CompactXmlNodeSchema, DefinedNameSchema, PackageSchema, PartSchema, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, attr, attr as attr$1, base64ToBytes, base64ToBytes as base64ToBytes$1, buildXml, bytesToBase64, bytesToBase64 as bytesToBase64$1, childrenWithTag, compactCodec, compactPackageCodec, decodeCompactPackage, decodeEntities, decodePackage, decodePackage as decodePackage$1, elementsWithTag, encodeCompactPackage, encodePackage, encodePackage as encodePackage$1, fromCompact, isCompactXmlNode, isXmlNode, packageCodec, parsePackage, parseXml, readDocx, readPptx, resolveRelationships, resolveRelationships as resolveRelationships$1, rootElement, rootElement as rootElement$1, serializePackage, textContent, textContent as textContent$1, toCompact, unzipPackage, walk, xmlCodec, zipPackage } from "ooxml.js";
2
- import { COLOR_BLACK, ContentBlockSchema, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentRunSchema, ContentSectionSchema, ContentSectionSchema as ContentSectionSchema$1, ContentShapeSchema, ContentSlideSchema, ContentSlideSchema as ContentSlideSchema$1, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, DEFAULT_LAYOUT_FONT, LAYOUT_FORMAT_VERSION, LAYOUT_FORMAT_VERSION as LAYOUT_FORMAT_VERSION$1, LayoutDocumentSchema, LayoutMetadataSchema, PAGE_SIZE_A4, PAGE_SIZE_LETTER, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, colorToRgbHex, isContentBlock, rgbHexToColor } from "document-content-model";
1
+ import { AttributeSchema, BinaryPartSchema, CommentSchema, CompactPackageSchema, CompactPartSchema, CompactXmlNodeSchema, DefinedNameSchema, PackageSchema, PartSchema, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, attr, attr as attr$1, base64ToBytes, base64ToBytes as base64ToBytes$1, buildXml, bytesToBase64, bytesToBase64 as bytesToBase64$1, childrenWithTag, compactCodec, compactPackageCodec, decodeCompactPackage, decodeEntities, decodePackage, decodePackage as decodePackage$1, elementsWithTag, elementsWithTag as elementsWithTag$1, encodeCompactPackage, encodePackage, encodePackage as encodePackage$1, fromCompact, isCompactXmlNode, isXmlNode, packageCodec, parsePackage, parseXml, readDocx, readPptx, resolveRelationships, resolveRelationships as resolveRelationships$1, rootElement, rootElement as rootElement$1, serializePackage, textContent, textContent as textContent$1, toCompact, unzipPackage, walk, xmlCodec, zipPackage } from "ooxml.js";
2
+ import { COLOR_BLACK, ContentBlockSchema, ContentCellValueSchema, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentRunSchema, ContentSectionSchema, ContentSectionSchema as ContentSectionSchema$1, ContentShapeSchema, ContentSheetCellSchema, ContentSheetColumnSchema, ContentSheetPrintRangeSchema, ContentSheetPrintSettingsSchema, ContentSheetRepeatRangeSchema, ContentSheetRowSchema, ContentSheetSchema, ContentSheetSchema as ContentSheetSchema$1, ContentSlideSchema, ContentSlideSchema as ContentSlideSchema$1, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, DEFAULT_LAYOUT_FONT, LAYOUT_FORMAT_VERSION, LAYOUT_FORMAT_VERSION as LAYOUT_FORMAT_VERSION$1, LayoutDocumentSchema, LayoutMetadataSchema, PAGE_SIZE_A4, PAGE_SIZE_LETTER, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, colorToRgbHex, isContentBlock, rgbHexToColor } from "document-content-model";
3
3
  import { z } from "zod";
4
- import { ODF_MEDIA_TYPES, StyleRegistry, decodeOdfText, decodePackage as decodePackage$2, encodePackage as encodePackage$2, formatOdfLength, readOdp, readOdt, resolveStyle, setDocumentMediaType, syncManifest, xmlnsAttributes } from "odf.js";
4
+ import { ODF_MEDIA_TYPES, StyleRegistry, applyOdfTransform, base64ToBytes as base64ToBytes$2, bytesToBase64 as bytesToBase64$2, decodeOdfText, decodePackage as decodePackage$2, encodePackage as encodePackage$2, formatOdfLength, parseOdfLength, readOdp, readOds, readOdt, resolveOdfShapeGeometry, resolveStyle, setDocumentMediaType, syncManifest, syncManifest as syncManifest$1, xmlnsAttributes } from "odf.js";
5
5
  import { Unzlib, inflateSync, unzlibSync, zlibSync } from "fflate";
6
6
  //#region src/model/content.ts
7
7
  const CONTENT_FORMAT_VERSION = 1;
8
- const ContentDocumentSchema = z.discriminatedUnion("kind", [z.object({
9
- kind: z.literal("wordprocessing"),
10
- formatVersion: z.literal(1),
11
- metadata: LayoutMetadataSchema,
12
- sections: z.array(ContentSectionSchema$1)
13
- }), z.object({
14
- kind: z.literal("presentation"),
15
- formatVersion: z.literal(1),
16
- metadata: LayoutMetadataSchema,
17
- slides: z.array(ContentSlideSchema$1)
18
- })]);
8
+ const ContentDocumentSchema = z.discriminatedUnion("kind", [
9
+ z.object({
10
+ kind: z.literal("wordprocessing"),
11
+ formatVersion: z.literal(1),
12
+ metadata: LayoutMetadataSchema,
13
+ sections: z.array(ContentSectionSchema$1)
14
+ }),
15
+ z.object({
16
+ kind: z.literal("presentation"),
17
+ formatVersion: z.literal(1),
18
+ metadata: LayoutMetadataSchema,
19
+ slides: z.array(ContentSlideSchema$1)
20
+ }),
21
+ z.object({
22
+ kind: z.literal("spreadsheet"),
23
+ formatVersion: z.literal(1),
24
+ metadata: LayoutMetadataSchema,
25
+ sheets: z.array(ContentSheetSchema$1)
26
+ })
27
+ ]);
19
28
  //#endregion
20
29
  //#region src/model/geometry.ts
21
30
  function flipY(box, containerHeightPt) {
@@ -300,11 +309,11 @@ function ensureContentTypeOverride(pkg, partPath, contentType) {
300
309
  //#endregion
301
310
  //#region src/opc/media.ts
302
311
  const IMAGE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
303
- function escapeRegExp(value) {
312
+ function escapeRegExp$1(value) {
304
313
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
305
314
  }
306
315
  function nextMediaIndex(pkg, mediaDir, fileNamePrefix, extension) {
307
- const pattern = new RegExp(`^${escapeRegExp(fileNamePrefix)}(\\d+)\\.${escapeRegExp(extension)}$`);
316
+ const pattern = new RegExp(`^${escapeRegExp$1(fileNamePrefix)}(\\d+)\\.${escapeRegExp$1(extension)}$`);
308
317
  const prefix = `${mediaDir}/`;
309
318
  let max = 0;
310
319
  for (const path of Object.keys(pkg.parts)) {
@@ -318,7 +327,7 @@ function nextMediaIndex(pkg, mediaDir, fileNamePrefix, extension) {
318
327
  }
319
328
  return max + 1;
320
329
  }
321
- function addImageMedia(pkg, fromPartPath, mediaDir, format, bytes) {
330
+ function addImageMedia$1(pkg, fromPartPath, mediaDir, format, bytes) {
322
331
  const extension = format === "jpeg" ? "jpeg" : "png";
323
332
  const fileNamePrefix = "image";
324
333
  const partPath = `${mediaDir}/${fileNamePrefix}${nextMediaIndex(pkg, mediaDir, fileNamePrefix, extension)}.${extension}`;
@@ -400,7 +409,7 @@ function buildInlineDrawing(relationshipId, widthPt, heightPt, id, altText) {
400
409
  }, [inline]);
401
410
  }
402
411
  function insertImageMedia(context, documentRoot, image) {
403
- const { relationshipId } = addImageMedia(context.pkg, context.partPath, context.mediaDir, image.format, image.bytes);
412
+ const { relationshipId } = addImageMedia$1(context.pkg, context.partPath, context.mediaDir, image.format, image.bytes);
404
413
  const id = nextDrawingId(documentRoot);
405
414
  return buildInlineDrawing(relationshipId, image.widthPt, image.heightPt, id, image.altText);
406
415
  }
@@ -520,7 +529,7 @@ function needsSpacePreserve(text) {
520
529
  }
521
530
  //#endregion
522
531
  //#region src/edit/docx/run.ts
523
- function directChild$5(parent, tag) {
532
+ function directChild$8(parent, tag) {
524
533
  for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
525
534
  }
526
535
  function appendUElement(rPr, value) {
@@ -529,7 +538,7 @@ function appendUElement(rPr, value) {
529
538
  return created;
530
539
  }
531
540
  function findOrCreateT(run) {
532
- const existing = directChild$5(run, "w:t");
541
+ const existing = directChild$8(run, "w:t");
533
542
  if (existing !== void 0) return existing;
534
543
  const created = el("w:t");
535
544
  run.children.push(created);
@@ -549,7 +558,7 @@ var DocxRun = class {
549
558
  }
550
559
  rPr(create) {
551
560
  const node = this.live();
552
- return create ? ensureFirstChild(node, "w:rPr") : directChild$5(node, "w:rPr");
561
+ return create ? ensureFirstChild(node, "w:rPr") : directChild$8(node, "w:rPr");
553
562
  }
554
563
  get text() {
555
564
  return textContent$1(this.live());
@@ -573,14 +582,14 @@ var DocxRun = class {
573
582
  }
574
583
  get underline() {
575
584
  const rPr = this.rPr(false);
576
- const uElement = rPr === void 0 ? void 0 : directChild$5(rPr, "w:u");
585
+ const uElement = rPr === void 0 ? void 0 : directChild$8(rPr, "w:u");
577
586
  if (uElement === void 0) return false;
578
587
  for (const a of uElement.attributes) if (a.name === "w:val") return a.value !== "none";
579
588
  return true;
580
589
  }
581
590
  set underline(value) {
582
591
  const rPr = this.rPr(true);
583
- const existing = directChild$5(rPr, "w:u");
592
+ const existing = directChild$8(rPr, "w:u");
584
593
  if (existing === void 0) {
585
594
  appendUElement(rPr, value);
586
595
  return;
@@ -654,7 +663,7 @@ function buildRun$1(init = {}) {
654
663
  }
655
664
  //#endregion
656
665
  //#region src/edit/docx/paragraph.ts
657
- function directChild$4(parent, tag) {
666
+ function directChild$7(parent, tag) {
658
667
  for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
659
668
  }
660
669
  var DocxParagraph = class {
@@ -673,7 +682,7 @@ var DocxParagraph = class {
673
682
  }
674
683
  pPr(create) {
675
684
  const node = this.live();
676
- return create ? ensureFirstChild(node, "w:pPr") : directChild$4(node, "w:pPr");
685
+ return create ? ensureFirstChild(node, "w:pPr") : directChild$7(node, "w:pPr");
677
686
  }
678
687
  get text() {
679
688
  return textContent$1(this.live());
@@ -710,7 +719,7 @@ var DocxParagraph = class {
710
719
  set styleId(value) {
711
720
  if (value === void 0) {
712
721
  const pPr = this.pPr(false);
713
- const existing = pPr === void 0 ? void 0 : directChild$4(pPr, "w:pStyle");
722
+ const existing = pPr === void 0 ? void 0 : directChild$7(pPr, "w:pStyle");
714
723
  if (existing !== void 0 && pPr !== void 0) removeChild(pPr.children, existing);
715
724
  return;
716
725
  }
@@ -722,7 +731,7 @@ var DocxParagraph = class {
722
731
  set alignment(value) {
723
732
  if (value === void 0) {
724
733
  const pPr = this.pPr(false);
725
- const existing = pPr === void 0 ? void 0 : directChild$4(pPr, "w:jc");
734
+ const existing = pPr === void 0 ? void 0 : directChild$7(pPr, "w:jc");
726
735
  if (existing !== void 0 && pPr !== void 0) removeChild(pPr.children, existing);
727
736
  return;
728
737
  }
@@ -730,12 +739,12 @@ var DocxParagraph = class {
730
739
  }
731
740
  get list() {
732
741
  const pPr = this.pPr(false);
733
- const numPr = pPr === void 0 ? void 0 : directChild$4(pPr, "w:numPr");
742
+ const numPr = pPr === void 0 ? void 0 : directChild$7(pPr, "w:numPr");
734
743
  if (numPr === void 0) return;
735
- const numIdElement = directChild$4(numPr, "w:numId");
744
+ const numIdElement = directChild$7(numPr, "w:numId");
736
745
  const numId = numIdElement === void 0 ? void 0 : attr$1(numIdElement, "w:val");
737
746
  if (numId === void 0) return;
738
- const ilvlElement = directChild$4(numPr, "w:ilvl");
747
+ const ilvlElement = directChild$7(numPr, "w:ilvl");
739
748
  const ilvl = ilvlElement === void 0 ? void 0 : attr$1(ilvlElement, "w:val");
740
749
  return {
741
750
  numId,
@@ -745,7 +754,7 @@ var DocxParagraph = class {
745
754
  set list(value) {
746
755
  const pPr = this.pPr(true);
747
756
  if (value === void 0) {
748
- const existing = directChild$4(pPr, "w:numPr");
757
+ const existing = directChild$7(pPr, "w:numPr");
749
758
  if (existing !== void 0) removeChild(pPr.children, existing);
750
759
  return;
751
760
  }
@@ -779,7 +788,7 @@ function buildParagraph$1(init = {}) {
779
788
  const CONTENT_TYPES_NS$1 = "http://schemas.openxmlformats.org/package/2006/content-types";
780
789
  const RELS_NS$1 = "http://schemas.openxmlformats.org/package/2006/relationships";
781
790
  const WORDML_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
782
- function declaration$2() {
791
+ function declaration$3() {
783
792
  return {
784
793
  type: "declaration",
785
794
  attributes: [
@@ -848,23 +857,23 @@ function createEmptyDocxPackage() {
848
857
  return { parts: {
849
858
  "[Content_Types].xml": {
850
859
  kind: "xml",
851
- nodes: [declaration$2(), contentTypes]
860
+ nodes: [declaration$3(), contentTypes]
852
861
  },
853
862
  "_rels/.rels": {
854
863
  kind: "xml",
855
- nodes: [declaration$2(), rootRels]
864
+ nodes: [declaration$3(), rootRels]
856
865
  },
857
866
  "word/document.xml": {
858
867
  kind: "xml",
859
- nodes: [declaration$2(), document]
868
+ nodes: [declaration$3(), document]
860
869
  },
861
870
  "word/_rels/document.xml.rels": {
862
871
  kind: "xml",
863
- nodes: [declaration$2(), documentRels]
872
+ nodes: [declaration$3(), documentRels]
864
873
  },
865
874
  "word/styles.xml": {
866
875
  kind: "xml",
867
- nodes: [declaration$2(), styles]
876
+ nodes: [declaration$3(), styles]
868
877
  }
869
878
  } };
870
879
  }
@@ -1155,7 +1164,7 @@ const SLIDE_LAYOUT_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/
1155
1164
  const THEME_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
1156
1165
  const NOTES_MASTER_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster";
1157
1166
  const MIN_MASTER_OR_LAYOUT_ID = 2147483648;
1158
- function declaration$1() {
1167
+ function declaration$2() {
1159
1168
  return {
1160
1169
  type: "declaration",
1161
1170
  attributes: [
@@ -1305,7 +1314,7 @@ function ensureNotesMaster(pkg) {
1305
1314
  });
1306
1315
  pkg.parts[NOTES_MASTER_PART_PATH] = {
1307
1316
  kind: "xml",
1308
- nodes: [declaration$1(), buildNotesMaster()]
1317
+ nodes: [declaration$2(), buildNotesMaster()]
1309
1318
  };
1310
1319
  ensureContentTypeOverride(pkg, NOTES_MASTER_PART_PATH, NOTES_MASTER_CONTENT_TYPE);
1311
1320
  const presentationToNotesMasterTarget = buildRelativeTarget(PRESENTATION_PART_PATH$1, NOTES_MASTER_PART_PATH);
@@ -1344,15 +1353,15 @@ function createEmptyPptxPackage() {
1344
1353
  const pkg = { parts: {
1345
1354
  "[Content_Types].xml": {
1346
1355
  kind: "xml",
1347
- nodes: [declaration$1(), contentTypes]
1356
+ nodes: [declaration$2(), contentTypes]
1348
1357
  },
1349
1358
  "_rels/.rels": {
1350
1359
  kind: "xml",
1351
- nodes: [declaration$1(), rootRels]
1360
+ nodes: [declaration$2(), rootRels]
1352
1361
  },
1353
1362
  [PRESENTATION_PART_PATH$1]: {
1354
1363
  kind: "xml",
1355
- nodes: [declaration$1(), el("p:presentation", {
1364
+ nodes: [declaration$2(), el("p:presentation", {
1356
1365
  "xmlns:p": PML_NS,
1357
1366
  "xmlns:r": R_NS
1358
1367
  })]
@@ -1365,7 +1374,7 @@ function createEmptyPptxPackage() {
1365
1374
  });
1366
1375
  pkg.parts[SLIDE_LAYOUT_PART_PATH] = {
1367
1376
  kind: "xml",
1368
- nodes: [declaration$1(), buildSlideLayout()]
1377
+ nodes: [declaration$2(), buildSlideLayout()]
1369
1378
  };
1370
1379
  ensureContentTypeOverride(pkg, SLIDE_LAYOUT_PART_PATH, SLIDE_LAYOUT_CONTENT_TYPE);
1371
1380
  const masterToLayoutTarget = buildRelativeTarget(SLIDE_MASTER_PART_PATH, SLIDE_LAYOUT_PART_PATH);
@@ -1380,12 +1389,12 @@ function createEmptyPptxPackage() {
1380
1389
  });
1381
1390
  pkg.parts[SLIDE_MASTER_PART_PATH] = {
1382
1391
  kind: "xml",
1383
- nodes: [declaration$1(), buildSlideMaster(masterToLayoutRelId)]
1392
+ nodes: [declaration$2(), buildSlideMaster(masterToLayoutRelId)]
1384
1393
  };
1385
1394
  ensureContentTypeOverride(pkg, SLIDE_MASTER_PART_PATH, SLIDE_MASTER_CONTENT_TYPE);
1386
1395
  pkg.parts[THEME_PART_PATH] = {
1387
1396
  kind: "xml",
1388
- nodes: [declaration$1(), buildTheme()]
1397
+ nodes: [declaration$2(), buildTheme()]
1389
1398
  };
1390
1399
  ensureContentTypeOverride(pkg, THEME_PART_PATH, THEME_CONTENT_TYPE);
1391
1400
  const presentationToMasterTarget = buildRelativeTarget(PRESENTATION_PART_PATH$1, SLIDE_MASTER_PART_PATH);
@@ -1410,7 +1419,7 @@ function createEmptyPptxPackage() {
1410
1419
  }
1411
1420
  //#endregion
1412
1421
  //#region src/edit/pptx/shape.ts
1413
- function directChild$3(parent, tag) {
1422
+ function directChild$6(parent, tag) {
1414
1423
  for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
1415
1424
  }
1416
1425
  function parseEmuAttr(element, name) {
@@ -1431,7 +1440,7 @@ var PptxShape = class {
1431
1440
  }
1432
1441
  spPrElement(create) {
1433
1442
  const node = this.live();
1434
- const existing = directChild$3(node, "p:spPr");
1443
+ const existing = directChild$6(node, "p:spPr");
1435
1444
  if (existing !== void 0 || !create) return existing;
1436
1445
  const created = el("p:spPr");
1437
1446
  node.children.push(created);
@@ -1439,10 +1448,10 @@ var PptxShape = class {
1439
1448
  }
1440
1449
  get frame() {
1441
1450
  const spPr = this.spPrElement(false);
1442
- const xfrm = spPr === void 0 ? void 0 : directChild$3(spPr, "a:xfrm");
1451
+ const xfrm = spPr === void 0 ? void 0 : directChild$6(spPr, "a:xfrm");
1443
1452
  if (xfrm === void 0) return;
1444
- const off = directChild$3(xfrm, "a:off");
1445
- const ext = directChild$3(xfrm, "a:ext");
1453
+ const off = directChild$6(xfrm, "a:off");
1454
+ const ext = directChild$6(xfrm, "a:ext");
1446
1455
  if (off === void 0 || ext === void 0) return;
1447
1456
  const x = parseEmuAttr(off, "x");
1448
1457
  const y = parseEmuAttr(off, "y");
@@ -1458,7 +1467,7 @@ var PptxShape = class {
1458
1467
  }
1459
1468
  set frame(value) {
1460
1469
  const spPr = this.spPrElement(true);
1461
- let xfrm = directChild$3(spPr, "a:xfrm");
1470
+ let xfrm = directChild$6(spPr, "a:xfrm");
1462
1471
  if (xfrm === void 0) {
1463
1472
  xfrm = el("a:xfrm");
1464
1473
  spPr.children.unshift(xfrm);
@@ -1472,12 +1481,12 @@ var PptxShape = class {
1472
1481
  })];
1473
1482
  }
1474
1483
  get text() {
1475
- const txBody = directChild$3(this.live(), "p:txBody");
1484
+ const txBody = directChild$6(this.live(), "p:txBody");
1476
1485
  return txBody === void 0 ? "" : textContent$1(txBody);
1477
1486
  }
1478
1487
  set text(value) {
1479
1488
  const node = this.live();
1480
- let txBody = directChild$3(node, "p:txBody");
1489
+ let txBody = directChild$6(node, "p:txBody");
1481
1490
  if (txBody === void 0) {
1482
1491
  txBody = el("p:txBody", {}, [el("a:bodyPr"), el("a:lstStyle")]);
1483
1492
  node.children.push(txBody);
@@ -1488,7 +1497,7 @@ var PptxShape = class {
1488
1497
  }
1489
1498
  setParagraphs(paragraphs) {
1490
1499
  const node = this.live();
1491
- let txBody = directChild$3(node, "p:txBody");
1500
+ let txBody = directChild$6(node, "p:txBody");
1492
1501
  if (txBody === void 0) {
1493
1502
  txBody = el("p:txBody", {}, [el("a:bodyPr"), el("a:lstStyle")]);
1494
1503
  node.children.push(txBody);
@@ -1594,17 +1603,17 @@ function nextShapeId(slideRoot) {
1594
1603
  return max + 1;
1595
1604
  }
1596
1605
  function insertPictureShapeMedia(context, slideRoot, frame, image) {
1597
- const { relationshipId } = addImageMedia(context.pkg, context.partPath, context.mediaDir, image.format, image.bytes);
1606
+ const { relationshipId } = addImageMedia$1(context.pkg, context.partPath, context.mediaDir, image.format, image.bytes);
1598
1607
  return buildPictureShape(frame, relationshipId, nextShapeId(slideRoot));
1599
1608
  }
1600
1609
  //#endregion
1601
1610
  //#region src/edit/pptx/slide.ts
1602
- function directChild$2(parent, tag) {
1611
+ function directChild$5(parent, tag) {
1603
1612
  for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
1604
1613
  }
1605
1614
  function findSpTree(slideRoot) {
1606
- const cSld = directChild$2(slideRoot, "p:cSld");
1607
- const spTree = cSld === void 0 ? void 0 : directChild$2(cSld, "p:spTree");
1615
+ const cSld = directChild$5(slideRoot, "p:cSld");
1616
+ const spTree = cSld === void 0 ? void 0 : directChild$5(cSld, "p:spTree");
1608
1617
  if (spTree === void 0) throw new Error("slide has no p:cSld/p:spTree element");
1609
1618
  return spTree;
1610
1619
  }
@@ -1736,7 +1745,7 @@ const PRESENTATION_PART_PATH = "ppt/presentation.xml";
1736
1745
  const MEDIA_DIR = "ppt/media";
1737
1746
  const SLIDE_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.presentationml.slide+xml";
1738
1747
  const SLIDE_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide";
1739
- function directChild$1(parent, tag) {
1748
+ function directChild$4(parent, tag) {
1740
1749
  for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
1741
1750
  }
1742
1751
  function attrValue(element, name) {
@@ -1748,12 +1757,12 @@ function findPresentationRoot(pkg) {
1748
1757
  return root;
1749
1758
  }
1750
1759
  function findSldIdLst(presentationRoot) {
1751
- const sldIdLst = directChild$1(presentationRoot, "p:sldIdLst");
1760
+ const sldIdLst = directChild$4(presentationRoot, "p:sldIdLst");
1752
1761
  if (sldIdLst === void 0) throw new Error(`${PRESENTATION_PART_PATH} has no p:sldIdLst element`);
1753
1762
  return sldIdLst;
1754
1763
  }
1755
1764
  function findSldSz(presentationRoot) {
1756
- const sldSz = directChild$1(presentationRoot, "p:sldSz");
1765
+ const sldSz = directChild$4(presentationRoot, "p:sldSz");
1757
1766
  if (sldSz === void 0) throw new Error(`${PRESENTATION_PART_PATH} has no p:sldSz element`);
1758
1767
  return sldSz;
1759
1768
  }
@@ -1914,12 +1923,12 @@ function buildPptxPackage(content) {
1914
1923
  if (firstSlide !== void 0) editor.slideSize = firstSlide.size;
1915
1924
  for (const slide of content.slides) {
1916
1925
  const pptxSlide = editor.addSlide();
1917
- for (const shape of slide.shapes) appendShape(pptxSlide, shape);
1926
+ for (const shape of slide.shapes) appendShape$1(pptxSlide, shape);
1918
1927
  if (slide.notes.length > 0) pptxSlide.notes = slide.notes;
1919
1928
  }
1920
1929
  return editor.toPackage();
1921
1930
  }
1922
- function appendShape(slide, shape) {
1931
+ function appendShape$1(slide, shape) {
1923
1932
  const [onlyBlock] = shape.blocks;
1924
1933
  if (shape.blocks.length === 1 && onlyBlock?.kind === "image") {
1925
1934
  slide.addImage({
@@ -1952,12 +1961,12 @@ function appendShape(slide, shape) {
1952
1961
  }
1953
1962
  //#endregion
1954
1963
  //#region src/edit/odt/automatic-styles.ts
1955
- const CONTENT_PART_PATH$1 = "content.xml";
1964
+ const CONTENT_PART_PATH$2 = "content.xml";
1956
1965
  function ensureAutomaticStyles(pkg) {
1957
- const part = pkg.parts[CONTENT_PART_PATH$1];
1958
- if (part?.kind !== "xml") throw new Error(`ensureAutomaticStyles: package has no ${CONTENT_PART_PATH$1} part`);
1966
+ const part = pkg.parts[CONTENT_PART_PATH$2];
1967
+ if (part?.kind !== "xml") throw new Error(`ensureAutomaticStyles: package has no ${CONTENT_PART_PATH$2} part`);
1959
1968
  const root = part.nodes.find((n) => n.type === "element");
1960
- if (root === void 0) throw new Error(`ensureAutomaticStyles: ${CONTENT_PART_PATH$1} has no root element`);
1969
+ if (root === void 0) throw new Error(`ensureAutomaticStyles: ${CONTENT_PART_PATH$2} has no root element`);
1961
1970
  for (const child of root.children) if (child.type === "element" && child.tag === "office:automatic-styles") return child;
1962
1971
  const created = el("office:automatic-styles");
1963
1972
  const insertBeforeTags = /* @__PURE__ */ new Set([
@@ -2051,7 +2060,7 @@ function applyStyleChange(pkg, element, family, change) {
2051
2060
  ...readCurrentStyleProperties(pkg, element, family),
2052
2061
  ...change
2053
2062
  };
2054
- const name = StyleRegistry.forPart(pkg, CONTENT_PART_PATH$1).intern({
2063
+ const name = StyleRegistry.forPart(pkg, CONTENT_PART_PATH$2).intern({
2055
2064
  family,
2056
2065
  properties: merged
2057
2066
  });
@@ -2282,7 +2291,7 @@ function buildList(pkg) {
2282
2291
  }
2283
2292
  //#endregion
2284
2293
  //#region src/edit/odt/scaffold.ts
2285
- const CONTENT_NS_PREFIXES = [
2294
+ const CONTENT_NS_PREFIXES$1 = [
2286
2295
  "office",
2287
2296
  "style",
2288
2297
  "text",
@@ -2292,7 +2301,7 @@ const CONTENT_NS_PREFIXES = [
2292
2301
  "svg",
2293
2302
  "xlink"
2294
2303
  ];
2295
- const STYLES_NS_PREFIXES = [
2304
+ const STYLES_NS_PREFIXES$1 = [
2296
2305
  "office",
2297
2306
  "style",
2298
2307
  "text",
@@ -2302,16 +2311,16 @@ const STYLES_NS_PREFIXES = [
2302
2311
  "svg",
2303
2312
  "xlink"
2304
2313
  ];
2305
- const META_NS_PREFIXES = [
2314
+ const META_NS_PREFIXES$1 = [
2306
2315
  "office",
2307
2316
  "meta",
2308
2317
  "dc"
2309
2318
  ];
2310
- const ODF_VERSION = "1.3";
2311
- const PAGE_LAYOUT_NAME = "PM1";
2312
- const MASTER_PAGE_NAME = "Standard";
2319
+ const ODF_VERSION$1 = "1.3";
2320
+ const PAGE_LAYOUT_NAME$1 = "PM1";
2321
+ const MASTER_PAGE_NAME$1 = "Standard";
2313
2322
  const DEFAULT_MARGIN_PT = 72;
2314
- function declaration() {
2323
+ function declaration$1() {
2315
2324
  return {
2316
2325
  type: "declaration",
2317
2326
  attributes: [
@@ -2330,8 +2339,8 @@ function declaration() {
2330
2339
  ]
2331
2340
  };
2332
2341
  }
2333
- function buildPageLayout() {
2334
- return el("style:page-layout", { "style:name": PAGE_LAYOUT_NAME }, [el("style:page-layout-properties", {
2342
+ function buildPageLayout$1() {
2343
+ return el("style:page-layout", { "style:name": PAGE_LAYOUT_NAME$1 }, [el("style:page-layout-properties", {
2335
2344
  "fo:page-width": `${PAGE_SIZE_LETTER.widthPt}pt`,
2336
2345
  "fo:page-height": `${PAGE_SIZE_LETTER.heightPt}pt`,
2337
2346
  "fo:margin-top": `${DEFAULT_MARGIN_PT}pt`,
@@ -2340,44 +2349,44 @@ function buildPageLayout() {
2340
2349
  "fo:margin-left": `${DEFAULT_MARGIN_PT}pt`
2341
2350
  })]);
2342
2351
  }
2343
- function buildStylesXml() {
2352
+ function buildStylesXml$1() {
2344
2353
  return el("office:document-styles", {
2345
- ...xmlnsAttributes([...STYLES_NS_PREFIXES]),
2346
- "office:version": ODF_VERSION
2354
+ ...xmlnsAttributes([...STYLES_NS_PREFIXES$1]),
2355
+ "office:version": ODF_VERSION$1
2347
2356
  }, [
2348
2357
  el("office:styles"),
2349
- el("office:automatic-styles", {}, [buildPageLayout()]),
2358
+ el("office:automatic-styles", {}, [buildPageLayout$1()]),
2350
2359
  el("office:master-styles", {}, [el("style:master-page", {
2351
- "style:name": MASTER_PAGE_NAME,
2352
- "style:page-layout-name": PAGE_LAYOUT_NAME
2360
+ "style:name": MASTER_PAGE_NAME$1,
2361
+ "style:page-layout-name": PAGE_LAYOUT_NAME$1
2353
2362
  })])
2354
2363
  ]);
2355
2364
  }
2356
- function buildContentXml() {
2365
+ function buildContentXml$1() {
2357
2366
  return el("office:document-content", {
2358
- ...xmlnsAttributes([...CONTENT_NS_PREFIXES]),
2359
- "office:version": ODF_VERSION
2367
+ ...xmlnsAttributes([...CONTENT_NS_PREFIXES$1]),
2368
+ "office:version": ODF_VERSION$1
2360
2369
  }, [el("office:automatic-styles"), el("office:body", {}, [el("office:text")])]);
2361
2370
  }
2362
- function buildMetaXml() {
2371
+ function buildMetaXml$1() {
2363
2372
  return el("office:document-meta", {
2364
- ...xmlnsAttributes([...META_NS_PREFIXES]),
2365
- "office:version": ODF_VERSION
2373
+ ...xmlnsAttributes([...META_NS_PREFIXES$1]),
2374
+ "office:version": ODF_VERSION$1
2366
2375
  }, [el("office:meta")]);
2367
2376
  }
2368
2377
  function createEmptyOdtPackage() {
2369
2378
  const pkg = { parts: {
2370
2379
  "content.xml": {
2371
2380
  kind: "xml",
2372
- nodes: [declaration(), buildContentXml()]
2381
+ nodes: [declaration$1(), buildContentXml$1()]
2373
2382
  },
2374
2383
  "styles.xml": {
2375
2384
  kind: "xml",
2376
- nodes: [declaration(), buildStylesXml()]
2385
+ nodes: [declaration$1(), buildStylesXml$1()]
2377
2386
  },
2378
2387
  "meta.xml": {
2379
2388
  kind: "xml",
2380
- nodes: [declaration(), buildMetaXml()]
2389
+ nodes: [declaration$1(), buildMetaXml$1()]
2381
2390
  }
2382
2391
  } };
2383
2392
  setDocumentMediaType(pkg, ODF_MEDIA_TYPES.odt);
@@ -2498,20 +2507,20 @@ function buildTable(pkg, init) {
2498
2507
  }
2499
2508
  //#endregion
2500
2509
  //#region src/edit/odt/editor.ts
2501
- const CONTENT_PART_PATH = "content.xml";
2510
+ const CONTENT_PART_PATH$1 = "content.xml";
2502
2511
  function findContentRoot(pkg) {
2503
- const part = pkg.parts[CONTENT_PART_PATH];
2512
+ const part = pkg.parts[CONTENT_PART_PATH$1];
2504
2513
  const root = part?.kind === "xml" ? part.nodes.find((n) => n.type === "element") : void 0;
2505
- if (root === void 0) throw new Error(`package has no root element at ${CONTENT_PART_PATH}`);
2514
+ if (root === void 0) throw new Error(`package has no root element at ${CONTENT_PART_PATH$1}`);
2506
2515
  return root;
2507
2516
  }
2508
- function directChild(parent, tag) {
2517
+ function directChild$3(parent, tag) {
2509
2518
  for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
2510
2519
  }
2511
2520
  function findOfficeText(contentRoot) {
2512
- const body = directChild(contentRoot, "office:body");
2513
- const text = body === void 0 ? void 0 : directChild(body, "office:text");
2514
- if (text === void 0) throw new Error(`${CONTENT_PART_PATH} has no office:body/office:text element`);
2521
+ const body = directChild$3(contentRoot, "office:body");
2522
+ const text = body === void 0 ? void 0 : directChild$3(body, "office:text");
2523
+ if (text === void 0) throw new Error(`${CONTENT_PART_PATH$1} has no office:body/office:text element`);
2515
2524
  return text;
2516
2525
  }
2517
2526
  var OdtBodyImpl = class {
@@ -2642,6 +2651,474 @@ function appendBlock(body, block) {
2642
2651
  else if (block.kind === "table") appendTable(body, block);
2643
2652
  }
2644
2653
  //#endregion
2654
+ //#region src/edit/odp/scaffold.ts
2655
+ const CONTENT_NS_PREFIXES = [
2656
+ "office",
2657
+ "style",
2658
+ "text",
2659
+ "table",
2660
+ "draw",
2661
+ "presentation",
2662
+ "fo",
2663
+ "svg",
2664
+ "xlink"
2665
+ ];
2666
+ const STYLES_NS_PREFIXES = [
2667
+ "office",
2668
+ "style",
2669
+ "text",
2670
+ "table",
2671
+ "draw",
2672
+ "presentation",
2673
+ "fo",
2674
+ "svg",
2675
+ "xlink"
2676
+ ];
2677
+ const META_NS_PREFIXES = [
2678
+ "office",
2679
+ "meta",
2680
+ "dc"
2681
+ ];
2682
+ const ODF_VERSION = "1.3";
2683
+ const MASTER_PAGE_NAME = "Standard";
2684
+ function declaration() {
2685
+ return {
2686
+ type: "declaration",
2687
+ attributes: [
2688
+ {
2689
+ name: "version",
2690
+ value: "1.0"
2691
+ },
2692
+ {
2693
+ name: "encoding",
2694
+ value: "UTF-8"
2695
+ },
2696
+ {
2697
+ name: "standalone",
2698
+ value: "yes"
2699
+ }
2700
+ ]
2701
+ };
2702
+ }
2703
+ function buildPageLayout() {
2704
+ return el("style:page-layout", { "style:name": "PM1" }, [el("style:page-layout-properties", {
2705
+ "fo:page-width": `${SLIDE_SIZE_WIDESCREEN.widthPt}pt`,
2706
+ "fo:page-height": `${SLIDE_SIZE_WIDESCREEN.heightPt}pt`
2707
+ })]);
2708
+ }
2709
+ function buildStylesXml() {
2710
+ return el("office:document-styles", {
2711
+ ...xmlnsAttributes([...STYLES_NS_PREFIXES]),
2712
+ "office:version": ODF_VERSION
2713
+ }, [
2714
+ el("office:styles"),
2715
+ el("office:automatic-styles", {}, [buildPageLayout()]),
2716
+ el("office:master-styles", {}, [el("style:master-page", {
2717
+ "style:name": MASTER_PAGE_NAME,
2718
+ "style:page-layout-name": "PM1"
2719
+ })])
2720
+ ]);
2721
+ }
2722
+ function buildContentXml() {
2723
+ return el("office:document-content", {
2724
+ ...xmlnsAttributes([...CONTENT_NS_PREFIXES]),
2725
+ "office:version": ODF_VERSION
2726
+ }, [el("office:automatic-styles"), el("office:body", {}, [el("office:presentation")])]);
2727
+ }
2728
+ function buildMetaXml() {
2729
+ return el("office:document-meta", {
2730
+ ...xmlnsAttributes([...META_NS_PREFIXES]),
2731
+ "office:version": ODF_VERSION
2732
+ }, [el("office:meta")]);
2733
+ }
2734
+ function createEmptyOdpPackage() {
2735
+ const pkg = { parts: {
2736
+ "content.xml": {
2737
+ kind: "xml",
2738
+ nodes: [declaration(), buildContentXml()]
2739
+ },
2740
+ "styles.xml": {
2741
+ kind: "xml",
2742
+ nodes: [declaration(), buildStylesXml()]
2743
+ },
2744
+ "meta.xml": {
2745
+ kind: "xml",
2746
+ nodes: [declaration(), buildMetaXml()]
2747
+ }
2748
+ } };
2749
+ setDocumentMediaType(pkg, ODF_MEDIA_TYPES.odp);
2750
+ syncManifest(pkg);
2751
+ return pkg;
2752
+ }
2753
+ //#endregion
2754
+ //#region src/odf-package/media.ts
2755
+ const PICTURES_DIR = "Pictures";
2756
+ function escapeRegExp(value) {
2757
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2758
+ }
2759
+ function nextPictureIndex(pkg, extension) {
2760
+ const pattern = new RegExp(`^image(\\d+)\\.${escapeRegExp(extension)}$`);
2761
+ const prefix = `${PICTURES_DIR}/`;
2762
+ let max = 0;
2763
+ for (const path of Object.keys(pkg.parts)) {
2764
+ if (!path.startsWith(prefix)) continue;
2765
+ const match = pattern.exec(path.slice(prefix.length));
2766
+ if (match === null) continue;
2767
+ const digits = match[1];
2768
+ if (digits === void 0) continue;
2769
+ const n = Number.parseInt(digits, 10);
2770
+ if (n > max) max = n;
2771
+ }
2772
+ return max + 1;
2773
+ }
2774
+ function addImageMedia(pkg, imageBytes, format) {
2775
+ const index = nextPictureIndex(pkg, format);
2776
+ const partPath = `${PICTURES_DIR}/image${index}.${format}`;
2777
+ pkg.parts[partPath] = {
2778
+ kind: "binary",
2779
+ base64: bytesToBase64$2(imageBytes)
2780
+ };
2781
+ syncManifest$1(pkg);
2782
+ return { partPath };
2783
+ }
2784
+ //#endregion
2785
+ //#region src/edit/odp/shape.ts
2786
+ function directChild$2(parent, tag) {
2787
+ for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
2788
+ }
2789
+ function buildTransformAttr(frame, rotationDeg) {
2790
+ const angleRad = -rotationDeg * Math.PI / 180;
2791
+ const localCenter = {
2792
+ xPt: frame.widthPt / 2,
2793
+ yPt: frame.heightPt / 2
2794
+ };
2795
+ const rotatedCenter = applyOdfTransform([{
2796
+ kind: "rotate",
2797
+ angleRad
2798
+ }], localCenter);
2799
+ const desiredCenter = {
2800
+ xPt: frame.xPt + frame.widthPt / 2,
2801
+ yPt: frame.yPt + frame.heightPt / 2
2802
+ };
2803
+ const txPt = desiredCenter.xPt - rotatedCenter.xPt;
2804
+ const tyPt = desiredCenter.yPt - rotatedCenter.yPt;
2805
+ return `rotate(${angleRad}) translate(${formatOdfLength(txPt)} ${formatOdfLength(tyPt)})`;
2806
+ }
2807
+ var OdpShape = class {
2808
+ container;
2809
+ node;
2810
+ pkg;
2811
+ removed = false;
2812
+ constructor(container, node, pkg) {
2813
+ this.container = container;
2814
+ this.node = node;
2815
+ this.pkg = pkg;
2816
+ }
2817
+ live() {
2818
+ if (this.removed) throw new Error("this OdpShape has been removed from its slide and can no longer be used");
2819
+ return this.node;
2820
+ }
2821
+ get name() {
2822
+ return attr$1(this.live(), "draw:name");
2823
+ }
2824
+ get frame() {
2825
+ return resolveOdfShapeGeometry(this.live())?.frame;
2826
+ }
2827
+ set frame(value) {
2828
+ this.applyGeometry(value, this.rotationDeg);
2829
+ }
2830
+ get rotationDeg() {
2831
+ return resolveOdfShapeGeometry(this.live())?.rotationDeg;
2832
+ }
2833
+ set rotationDeg(value) {
2834
+ const currentFrame = this.frame;
2835
+ if (currentFrame === void 0) throw new Error("cannot set rotationDeg on a shape with no resolvable frame (missing svg:width/svg:height)");
2836
+ this.applyGeometry(currentFrame, value);
2837
+ }
2838
+ applyGeometry(frame, rotationDeg) {
2839
+ const node = this.live();
2840
+ setAttr(node, "svg:width", formatOdfLength(frame.widthPt));
2841
+ setAttr(node, "svg:height", formatOdfLength(frame.heightPt));
2842
+ if (rotationDeg === void 0 || rotationDeg === 0) {
2843
+ removeAttr(node, "draw:transform");
2844
+ setAttr(node, "svg:x", formatOdfLength(frame.xPt));
2845
+ setAttr(node, "svg:y", formatOdfLength(frame.yPt));
2846
+ } else {
2847
+ removeAttr(node, "svg:x");
2848
+ removeAttr(node, "svg:y");
2849
+ setAttr(node, "draw:transform", buildTransformAttr(frame, rotationDeg));
2850
+ }
2851
+ }
2852
+ textBox(create) {
2853
+ const node = this.live();
2854
+ const existing = directChild$2(node, "draw:text-box");
2855
+ if (existing !== void 0 || !create) return existing;
2856
+ const created = el("draw:text-box");
2857
+ node.children.push(created);
2858
+ return created;
2859
+ }
2860
+ paragraphs() {
2861
+ const textBox = this.textBox(false);
2862
+ if (textBox === void 0) return [];
2863
+ const out = [];
2864
+ for (const child of textBox.children) if (child.type === "element" && child.tag === "text:p") out.push(new OdtParagraph(textBox.children, child, this.pkg));
2865
+ return out;
2866
+ }
2867
+ appendParagraph(init) {
2868
+ const textBox = this.textBox(true);
2869
+ const paragraphElement = buildParagraph(this.pkg, init);
2870
+ textBox.children.push(paragraphElement);
2871
+ return new OdtParagraph(textBox.children, paragraphElement, this.pkg);
2872
+ }
2873
+ get text() {
2874
+ return this.paragraphs().map((p) => p.text).join("\n");
2875
+ }
2876
+ set text(value) {
2877
+ const textBox = this.textBox(true);
2878
+ textBox.children = [buildParagraph(this.pkg, { text: value })];
2879
+ }
2880
+ addList() {
2881
+ const textBox = this.textBox(true);
2882
+ const listElement = buildList(this.pkg);
2883
+ textBox.children.push(listElement);
2884
+ return new OdtList(textBox.children, listElement, this.pkg);
2885
+ }
2886
+ remove() {
2887
+ removeChild(this.container, this.live());
2888
+ this.removed = true;
2889
+ }
2890
+ };
2891
+ function buildTextBoxFrame(pkg, frame, text) {
2892
+ return el("draw:frame", {
2893
+ "svg:x": formatOdfLength(frame.xPt),
2894
+ "svg:y": formatOdfLength(frame.yPt),
2895
+ "svg:width": formatOdfLength(frame.widthPt),
2896
+ "svg:height": formatOdfLength(frame.heightPt)
2897
+ }, [el("draw:text-box", {}, [buildParagraph(pkg, { text })])]);
2898
+ }
2899
+ function buildImageFrame(partPath, frame) {
2900
+ return el("draw:frame", {
2901
+ "svg:x": formatOdfLength(frame.xPt),
2902
+ "svg:y": formatOdfLength(frame.yPt),
2903
+ "svg:width": formatOdfLength(frame.widthPt),
2904
+ "svg:height": formatOdfLength(frame.heightPt)
2905
+ }, [el("draw:image", { "xlink:href": partPath })]);
2906
+ }
2907
+ //#endregion
2908
+ //#region src/edit/odp/image.ts
2909
+ function insertImageFrameMedia(context, frame, image) {
2910
+ const { partPath } = addImageMedia(context.pkg, image.bytes, image.format);
2911
+ return buildImageFrame(partPath, frame);
2912
+ }
2913
+ //#endregion
2914
+ //#region src/edit/odp/slide.ts
2915
+ function directChild$1(parent, tag) {
2916
+ for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
2917
+ }
2918
+ const NOTES_FRAME_X_PT = 20;
2919
+ const NOTES_FRAME_Y_PT = 400;
2920
+ const NOTES_FRAME_WIDTH_PT = 300;
2921
+ const NOTES_FRAME_HEIGHT_PT = 100;
2922
+ function buildNotesElement(pkg, value) {
2923
+ const textBox = el("draw:text-box", {}, value.split("\n").map((line) => buildParagraph(pkg, { text: line })));
2924
+ return el("presentation:notes", {}, [el("draw:frame", {
2925
+ "svg:x": formatOdfLength(NOTES_FRAME_X_PT),
2926
+ "svg:y": formatOdfLength(NOTES_FRAME_Y_PT),
2927
+ "svg:width": formatOdfLength(NOTES_FRAME_WIDTH_PT),
2928
+ "svg:height": formatOdfLength(NOTES_FRAME_HEIGHT_PT)
2929
+ }, [textBox])]);
2930
+ }
2931
+ var OdpSlide = class {
2932
+ container;
2933
+ node;
2934
+ context;
2935
+ removed = false;
2936
+ constructor(container, node, context) {
2937
+ this.container = container;
2938
+ this.node = node;
2939
+ this.context = context;
2940
+ }
2941
+ live() {
2942
+ if (this.removed) throw new Error("this OdpSlide has been removed from the presentation and can no longer be used");
2943
+ return this.node;
2944
+ }
2945
+ shapes() {
2946
+ const node = this.live();
2947
+ const out = [];
2948
+ for (const child of node.children) if (child.type === "element" && child.tag === "draw:frame") out.push(new OdpShape(node.children, child, this.context.pkg));
2949
+ return out;
2950
+ }
2951
+ addTextBox(init) {
2952
+ const node = this.live();
2953
+ const frameElement = buildTextBoxFrame(this.context.pkg, init.frame, init.text);
2954
+ node.children.push(frameElement);
2955
+ return new OdpShape(node.children, frameElement, this.context.pkg);
2956
+ }
2957
+ addImage(init) {
2958
+ const node = this.live();
2959
+ const frameElement = insertImageFrameMedia({ pkg: this.context.pkg }, init.frame, init);
2960
+ node.children.push(frameElement);
2961
+ return new OdpShape(node.children, frameElement, this.context.pkg);
2962
+ }
2963
+ get notes() {
2964
+ const notesElement = directChild$1(this.live(), "presentation:notes");
2965
+ if (notesElement === void 0) return "";
2966
+ return elementsWithTag$1(notesElement.children, "text:p").map((p) => decodeOdfText$1(p.children)).join("\n");
2967
+ }
2968
+ set notes(value) {
2969
+ const node = this.live();
2970
+ const existing = directChild$1(node, "presentation:notes");
2971
+ const notesElement = buildNotesElement(this.context.pkg, value);
2972
+ if (existing === void 0) node.children.push(notesElement);
2973
+ else existing.children = notesElement.children;
2974
+ }
2975
+ remove() {
2976
+ removeChild(this.container, this.live());
2977
+ this.removed = true;
2978
+ }
2979
+ };
2980
+ //#endregion
2981
+ //#region src/edit/odp/editor.ts
2982
+ const CONTENT_PART_PATH = "content.xml";
2983
+ const STYLES_PART_PATH = "styles.xml";
2984
+ function directChild(parent, tag) {
2985
+ for (const child of parent.children) if (child.type === "element" && child.tag === tag) return child;
2986
+ }
2987
+ function findRoot(pkg, partPath) {
2988
+ const part = pkg.parts[partPath];
2989
+ const root = part?.kind === "xml" ? part.nodes.find((n) => n.type === "element") : void 0;
2990
+ if (root === void 0) throw new Error(`package has no root element at ${partPath}`);
2991
+ return root;
2992
+ }
2993
+ function findOfficePresentation(pkg) {
2994
+ const body = directChild(findRoot(pkg, CONTENT_PART_PATH), "office:body");
2995
+ const presentation = body === void 0 ? void 0 : directChild(body, "office:presentation");
2996
+ if (presentation === void 0) throw new Error(`${CONTENT_PART_PATH} has no office:body/office:presentation element`);
2997
+ return presentation;
2998
+ }
2999
+ function findPageLayoutProperties(pkg) {
3000
+ const pageLayout = directChild(findRoot(pkg, STYLES_PART_PATH), "office:automatic-styles")?.children.find((c) => c.type === "element" && c.tag === "style:page-layout" && attr$1(c, "style:name") === "PM1");
3001
+ const properties = pageLayout === void 0 ? void 0 : directChild(pageLayout, "style:page-layout-properties");
3002
+ if (properties === void 0) throw new Error(`${STYLES_PART_PATH} has no style:page-layout[style:name="PM1"]/style:page-layout-properties element`);
3003
+ return properties;
3004
+ }
3005
+ var OdpEditor = class {
3006
+ pkg;
3007
+ constructor(pkg) {
3008
+ this.pkg = pkg;
3009
+ }
3010
+ slides() {
3011
+ const presentation = findOfficePresentation(this.pkg);
3012
+ const out = [];
3013
+ for (const child of presentation.children) if (child.type === "element" && child.tag === "draw:page") {
3014
+ const context = { pkg: this.pkg };
3015
+ out.push(new OdpSlide(presentation.children, child, context));
3016
+ }
3017
+ return out;
3018
+ }
3019
+ addSlide() {
3020
+ const presentation = findOfficePresentation(this.pkg);
3021
+ const pageElement = el("draw:page", { "draw:master-page-name": MASTER_PAGE_NAME });
3022
+ presentation.children.push(pageElement);
3023
+ const context = { pkg: this.pkg };
3024
+ return new OdpSlide(presentation.children, pageElement, context);
3025
+ }
3026
+ removeSlideAt(index) {
3027
+ const presentation = findOfficePresentation(this.pkg);
3028
+ const target = presentation.children.filter((c) => c.type === "element" && c.tag === "draw:page")[index];
3029
+ if (target === void 0) throw new Error(`slide index ${index} does not exist`);
3030
+ const listIndex = presentation.children.indexOf(target);
3031
+ presentation.children.splice(listIndex, 1);
3032
+ }
3033
+ moveSlide(from, to) {
3034
+ const presentation = findOfficePresentation(this.pkg);
3035
+ const pageIndices = [];
3036
+ presentation.children.forEach((child, i) => {
3037
+ if (child.type === "element" && child.tag === "draw:page") pageIndices.push(i);
3038
+ });
3039
+ const fromChildIndex = pageIndices[from];
3040
+ if (fromChildIndex === void 0) throw new Error(`slide index ${from} does not exist`);
3041
+ const [moved] = presentation.children.splice(fromChildIndex, 1);
3042
+ if (moved === void 0) throw new Error(`slide index ${from} does not exist`);
3043
+ const updatedIndices = [];
3044
+ presentation.children.forEach((child, i) => {
3045
+ if (child.type === "element" && child.tag === "draw:page") updatedIndices.push(i);
3046
+ });
3047
+ const insertAt = to < updatedIndices.length ? updatedIndices[to] ?? presentation.children.length : presentation.children.length;
3048
+ presentation.children.splice(insertAt, 0, moved);
3049
+ }
3050
+ get slideSize() {
3051
+ const properties = findPageLayoutProperties(this.pkg);
3052
+ const widthValue = attr$1(properties, "fo:page-width");
3053
+ const heightValue = attr$1(properties, "fo:page-height");
3054
+ const widthPt = widthValue === void 0 ? void 0 : parseOdfLength(widthValue);
3055
+ const heightPt = heightValue === void 0 ? void 0 : parseOdfLength(heightValue);
3056
+ return {
3057
+ widthPt: widthPt ?? 0,
3058
+ heightPt: heightPt ?? 0
3059
+ };
3060
+ }
3061
+ set slideSize(size) {
3062
+ const properties = findPageLayoutProperties(this.pkg);
3063
+ properties.attributes = [{
3064
+ name: "fo:page-width",
3065
+ value: formatOdfLength(size.widthPt)
3066
+ }, {
3067
+ name: "fo:page-height",
3068
+ value: formatOdfLength(size.heightPt)
3069
+ }];
3070
+ }
3071
+ toPackage() {
3072
+ return this.pkg;
3073
+ }
3074
+ toBytes() {
3075
+ return encodePackage$2(this.pkg);
3076
+ }
3077
+ };
3078
+ function openOdp(bytes) {
3079
+ return new OdpEditor(decodePackage$2(bytes));
3080
+ }
3081
+ function createOdp() {
3082
+ return new OdpEditor(createEmptyOdpPackage());
3083
+ }
3084
+ //#endregion
3085
+ //#region src/edit/odp/content.ts
3086
+ function buildOdpPackage(content) {
3087
+ if (content.kind !== "presentation") throw new Error("buildOdpPackage requires a presentation ContentDocument");
3088
+ const editor = createOdp();
3089
+ const firstSlide = content.slides[0];
3090
+ if (firstSlide !== void 0) editor.slideSize = firstSlide.size;
3091
+ for (const slide of content.slides) {
3092
+ const odpSlide = editor.addSlide();
3093
+ for (const shape of slide.shapes) appendShape(odpSlide, shape);
3094
+ if (slide.notes.length > 0) odpSlide.notes = slide.notes;
3095
+ }
3096
+ return editor.toPackage();
3097
+ }
3098
+ function appendShape(slide, shape) {
3099
+ const [onlyBlock] = shape.blocks;
3100
+ if (shape.blocks.length === 1 && onlyBlock?.kind === "image") {
3101
+ const imageShape = slide.addImage({
3102
+ frame: shape.frame,
3103
+ format: onlyBlock.format,
3104
+ bytes: base64ToBytes$2(onlyBlock.base64),
3105
+ altText: onlyBlock.altText
3106
+ });
3107
+ if (shape.rotationDeg !== void 0) imageShape.rotationDeg = shape.rotationDeg;
3108
+ return;
3109
+ }
3110
+ const textShape = slide.addTextBox({
3111
+ frame: shape.frame,
3112
+ text: ""
3113
+ });
3114
+ if (shape.rotationDeg !== void 0) textShape.rotationDeg = shape.rotationDeg;
3115
+ textShape.paragraphs()[0]?.remove();
3116
+ for (const block of shape.blocks) {
3117
+ if (block.kind !== "paragraph") continue;
3118
+ populateParagraph(textShape.appendParagraph(), block);
3119
+ }
3120
+ }
3121
+ //#endregion
2645
3122
  //#region src/bytes/crc32.ts
2646
3123
  const CRC32_POLYNOMIAL = 3988292384;
2647
3124
  const BYTE_VALUES = 256;
@@ -7447,6 +7924,17 @@ function readOdpContent(pkg) {
7447
7924
  };
7448
7925
  }
7449
7926
  //#endregion
7927
+ //#region src/odf/ods/read.ts
7928
+ function readOdsContent(pkg) {
7929
+ const odsDoc = readOds(pkg);
7930
+ return {
7931
+ kind: "spreadsheet",
7932
+ formatVersion: 1,
7933
+ metadata: { ...odsDoc.metadata },
7934
+ sheets: odsDoc.sheets
7935
+ };
7936
+ }
7937
+ //#endregion
7450
7938
  //#region src/pdf/text-layout.ts
7451
7939
  const WORD_OR_WHITESPACE_PATTERN = /\n|\s+|\S+/g;
7452
7940
  function atomizeRuns(runs, measurer) {
@@ -8074,6 +8562,410 @@ function convertPresentationToLayout(doc, options) {
8074
8562
  };
8075
8563
  }
8076
8564
  //#endregion
8565
+ //#region src/layout/sheets.ts
8566
+ const DEFAULT_COLUMN_WIDTH_PT = 64;
8567
+ const DEFAULT_ROW_HEIGHT_PT = 15;
8568
+ const NOMINAL_CELL_TEXT_SIZE_PT = 10;
8569
+ const HEADER_LABEL_SIZE_PT = 8;
8570
+ const CELL_TEXT_PADDING_PT = 2;
8571
+ const HEADER_LABEL_PADDING_PT = 2;
8572
+ const MINIMUM_SCALE = .01;
8573
+ const NUMERIC_OVERFLOW_TEXT = "###";
8574
+ const GRIDLINE_COLOR = rgbHexToColor("#D0D0D0");
8575
+ const GRIDLINE_WIDTH_PT = .5;
8576
+ const HEADER_LABEL_COLOR = rgbHexToColor("#606060");
8577
+ function columnLetters(index) {
8578
+ let n = index + 1;
8579
+ let letters = "";
8580
+ while (n > 0) {
8581
+ const remainder = (n - 1) % 26;
8582
+ letters = String.fromCharCode(65 + remainder) + letters;
8583
+ n = Math.floor((n - 1) / 26);
8584
+ }
8585
+ return letters;
8586
+ }
8587
+ function resolvePrintRange(sheet) {
8588
+ if (sheet.printSettings.printRange !== void 0) return sheet.printSettings.printRange;
8589
+ if (sheet.cells.length === 0) return;
8590
+ let startRow = Number.POSITIVE_INFINITY;
8591
+ let startColumn = Number.POSITIVE_INFINITY;
8592
+ let endRow = Number.NEGATIVE_INFINITY;
8593
+ let endColumn = Number.NEGATIVE_INFINITY;
8594
+ for (const cell of sheet.cells) {
8595
+ startRow = Math.min(startRow, cell.row);
8596
+ startColumn = Math.min(startColumn, cell.column);
8597
+ endRow = Math.max(endRow, cell.row + (cell.rowSpan ?? 1) - 1);
8598
+ endColumn = Math.max(endColumn, cell.column + (cell.colSpan ?? 1) - 1);
8599
+ }
8600
+ return {
8601
+ startRow,
8602
+ startColumn,
8603
+ endRow,
8604
+ endColumn
8605
+ };
8606
+ }
8607
+ function resolveAxis(entries, start, end, defaultSizePt) {
8608
+ const sorted = [...entries].sort((a, b) => a.index - b.index);
8609
+ const resolved = [];
8610
+ let pointer = 0;
8611
+ let currentSizePt = defaultSizePt;
8612
+ let currentHidden = false;
8613
+ for (let index = start; index <= end; index++) {
8614
+ while (pointer < sorted.length && sorted[pointer].index <= index) {
8615
+ currentSizePt = sorted[pointer].sizePt;
8616
+ currentHidden = sorted[pointer].hidden ?? false;
8617
+ pointer++;
8618
+ }
8619
+ resolved.push({
8620
+ index,
8621
+ sizePt: currentHidden ? 0 : currentSizePt,
8622
+ hidden: currentHidden
8623
+ });
8624
+ }
8625
+ return resolved;
8626
+ }
8627
+ function computeHeaderGutter(printSettings, range, measurer) {
8628
+ if (!printSettings.headers) return {
8629
+ widthPt: 0,
8630
+ heightPt: 0
8631
+ };
8632
+ const widestRowLabel = String(range.endRow + 1);
8633
+ return {
8634
+ widthPt: measurer.widthOfTextAtSize(widestRowLabel, DEFAULT_LAYOUT_FONT, HEADER_LABEL_SIZE_PT) + 4,
8635
+ heightPt: measurer.lineHeightAtSize(DEFAULT_LAYOUT_FONT, HEADER_LABEL_SIZE_PT)
8636
+ };
8637
+ }
8638
+ function resolveScale(printSettings, availableWidthPt, availableHeightPt, totalContentWidthPt, totalContentHeightPt) {
8639
+ if (printSettings.scale !== void 0) return Math.max(printSettings.scale / 100, MINIMUM_SCALE);
8640
+ if (printSettings.fitToPages !== void 0) {
8641
+ const budgetWidthPt = availableWidthPt * printSettings.fitToPages.width;
8642
+ const budgetHeightPt = availableHeightPt * printSettings.fitToPages.height;
8643
+ const widthRatio = totalContentWidthPt > 0 ? budgetWidthPt / totalContentWidthPt : 1;
8644
+ const heightRatio = totalContentHeightPt > 0 ? budgetHeightPt / totalContentHeightPt : 1;
8645
+ return Math.max(Math.min(widthRatio, heightRatio, 1), MINIMUM_SCALE);
8646
+ }
8647
+ return 1;
8648
+ }
8649
+ function partitionIndices(indices, sizeOf, availablePt, manualBreaks) {
8650
+ const bands = [];
8651
+ let current = [];
8652
+ let currentSizePt = 0;
8653
+ for (const index of indices) {
8654
+ if (manualBreaks.has(index) && current.length > 0) {
8655
+ bands.push(current);
8656
+ current = [];
8657
+ currentSizePt = 0;
8658
+ }
8659
+ const sizePt = sizeOf(index);
8660
+ if (current.length > 0 && currentSizePt + sizePt > availablePt) {
8661
+ bands.push(current);
8662
+ current = [];
8663
+ currentSizePt = 0;
8664
+ }
8665
+ current.push(index);
8666
+ currentSizePt += sizePt;
8667
+ }
8668
+ if (current.length > 0) bands.push(current);
8669
+ return bands;
8670
+ }
8671
+ function cellStyledRuns(cell) {
8672
+ if (cell.runs !== void 0 && cell.runs.length > 0) return toStyledRuns(cell.runs.map((run) => run.sizePt === void 0 ? {
8673
+ ...run,
8674
+ sizePt: NOMINAL_CELL_TEXT_SIZE_PT
8675
+ } : run));
8676
+ return [{
8677
+ text: cell.displayText,
8678
+ font: DEFAULT_LAYOUT_FONT,
8679
+ sizePt: NOMINAL_CELL_TEXT_SIZE_PT,
8680
+ color: COLOR_BLACK
8681
+ }];
8682
+ }
8683
+ function isNumericLikeValue(kind) {
8684
+ return kind === "number" || kind === "percentage" || kind === "currency" || kind === "date" || kind === "time";
8685
+ }
8686
+ function defaultAlignmentForValue(kind) {
8687
+ if (isNumericLikeValue(kind)) return "right";
8688
+ if (kind === "boolean" || kind === "error") return "center";
8689
+ return "left";
8690
+ }
8691
+ function isCellVisuallyEmpty(cell) {
8692
+ return cell === void 0 || cell.value.kind === "empty" && cell.displayText.length === 0;
8693
+ }
8694
+ function truncateFragmentsToWidth(fragments, measurer, maxWidthPt) {
8695
+ const result = [];
8696
+ for (const fragment of fragments) {
8697
+ if (fragment.xOffsetPt >= maxWidthPt) break;
8698
+ const remainingWidthPt = maxWidthPt - fragment.xOffsetPt;
8699
+ if (measurer.widthOfTextAtSize(fragment.text, fragment.font, fragment.sizePt) <= remainingWidthPt) {
8700
+ result.push(fragment);
8701
+ continue;
8702
+ }
8703
+ const chars = Array.from(fragment.text);
8704
+ let width = 0;
8705
+ let fitCount = 0;
8706
+ for (const char of chars) {
8707
+ const charWidthPt = measurer.widthOfTextAtSize(char, fragment.font, fragment.sizePt);
8708
+ if (width + charWidthPt > remainingWidthPt) break;
8709
+ width += charWidthPt;
8710
+ fitCount++;
8711
+ }
8712
+ if (fitCount > 0) result.push({
8713
+ ...fragment,
8714
+ text: chars.slice(0, fitCount).join("")
8715
+ });
8716
+ break;
8717
+ }
8718
+ return result;
8719
+ }
8720
+ function buildPositionedAxis(repeatIndices, repeatSizePtOf, bandIndices, bandSizePtOf) {
8721
+ const indices = [...repeatIndices, ...bandIndices];
8722
+ const sizesPt = [...repeatIndices.map(repeatSizePtOf), ...bandIndices.map(bandSizePtOf)];
8723
+ const offsetsPt = [0];
8724
+ let running = 0;
8725
+ for (const size of sizesPt) {
8726
+ running += size;
8727
+ offsetsPt.push(running);
8728
+ }
8729
+ return {
8730
+ indices,
8731
+ sizesPt,
8732
+ offsetsPt,
8733
+ positionByIndex: new Map(indices.map((index, position) => [index, position]))
8734
+ };
8735
+ }
8736
+ function axisSpanSizePt(axis, startIndex, span) {
8737
+ const startPosition = axis.positionByIndex.get(startIndex);
8738
+ if (startPosition === void 0) return 0;
8739
+ return sumColumnWidthsPt(axis.sizesPt, startPosition, span);
8740
+ }
8741
+ function renderCellText(cell, rowCells, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageHeightPt, measurer, out) {
8742
+ const columnPosition = columnAxis.positionByIndex.get(cell.column);
8743
+ const rowPosition = rowAxis.positionByIndex.get(cell.row);
8744
+ if (columnPosition === void 0 || rowPosition === void 0) return;
8745
+ const ownWidthPt = axisSpanSizePt(columnAxis, cell.column, cell.colSpan ?? 1);
8746
+ const heightPt = axisSpanSizePt(rowAxis, cell.row, cell.rowSpan ?? 1);
8747
+ const xLeftPt = gridLeftXPt + columnAxis.offsetsPt[columnPosition];
8748
+ const yTopDownPt = gridTopYDownPt + rowAxis.offsetsPt[rowPosition];
8749
+ const alignment = defaultAlignmentForValue(cell.value.kind);
8750
+ const numericLike = isNumericLikeValue(cell.value.kind);
8751
+ const styledRuns = cellStyledRuns(cell);
8752
+ const naturalLine = wrapRunsToWidth(styledRuns, measurer, Number.POSITIVE_INFINITY)[0];
8753
+ let availableWidthPt = Math.max(0, ownWidthPt - 4);
8754
+ let fragments = naturalLine.fragments;
8755
+ let lineWidthPt = naturalLine.widthPt;
8756
+ if (lineWidthPt > availableWidthPt) if (numericLike) {
8757
+ const overflowLine = wrapRunsToWidth([{
8758
+ text: NUMERIC_OVERFLOW_TEXT,
8759
+ font: styledRuns[0].font,
8760
+ sizePt: styledRuns[0].sizePt,
8761
+ color: styledRuns[0].color
8762
+ }], measurer, Number.POSITIVE_INFINITY)[0];
8763
+ fragments = overflowLine.fragments;
8764
+ lineWidthPt = overflowLine.widthPt;
8765
+ } else if (cell.value.kind === "string") {
8766
+ let spillColumn = cell.column + (cell.colSpan ?? 1);
8767
+ while (lineWidthPt > availableWidthPt) {
8768
+ const neighborPosition = columnAxis.positionByIndex.get(spillColumn);
8769
+ if (neighborPosition === void 0 || !isCellVisuallyEmpty(rowCells?.get(spillColumn))) break;
8770
+ availableWidthPt += columnAxis.sizesPt[neighborPosition];
8771
+ spillColumn++;
8772
+ }
8773
+ if (lineWidthPt > availableWidthPt) fragments = truncateFragmentsToWidth(fragments, measurer, availableWidthPt);
8774
+ } else fragments = truncateFragmentsToWidth(fragments, measurer, availableWidthPt);
8775
+ const alignOffsetPt = alignmentOffsetPt(alignment, availableWidthPt, lineWidthPt);
8776
+ const textStartXPt = xLeftPt + CELL_TEXT_PADDING_PT + alignOffsetPt;
8777
+ const lineHeightPt = lineNaturalHeightPt(naturalLine, measurer, styledRuns[0]);
8778
+ const baselineYDownPt = yTopDownPt + Math.max(CELL_TEXT_PADDING_PT, heightPt - CELL_TEXT_PADDING_PT - lineHeightPt) + naturalLine.ascentPt;
8779
+ for (const fragment of fragments) {
8780
+ const textItem = {
8781
+ kind: "text",
8782
+ text: fragment.text,
8783
+ xPt: textStartXPt + fragment.xOffsetPt,
8784
+ yPt: pageHeightPt - baselineYDownPt,
8785
+ font: fragment.font,
8786
+ sizePt: fragment.sizePt,
8787
+ color: fragment.color,
8788
+ underline: fragment.underline,
8789
+ sourcePath: fragment.sourcePath
8790
+ };
8791
+ out.push(textItem);
8792
+ }
8793
+ }
8794
+ function renderHeaderLabels(gutter, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageHeightPt, measurer, out) {
8795
+ const labelFont = DEFAULT_LAYOUT_FONT;
8796
+ const lineHeightPt = measurer.lineHeightAtSize(labelFont, HEADER_LABEL_SIZE_PT);
8797
+ const ascentPt = measurer.ascenderAtSize(labelFont, HEADER_LABEL_SIZE_PT);
8798
+ columnAxis.indices.forEach((columnIndex, position) => {
8799
+ const label = columnLetters(columnIndex);
8800
+ const widthPt = columnAxis.sizesPt[position];
8801
+ const labelWidthPt = measurer.widthOfTextAtSize(label, labelFont, HEADER_LABEL_SIZE_PT);
8802
+ const xPt = gridLeftXPt + columnAxis.offsetsPt[position] + alignmentOffsetPt("center", widthPt, labelWidthPt);
8803
+ const baselineYDownPt = gridTopYDownPt - gutter.heightPt + (gutter.heightPt - lineHeightPt) / 2 + ascentPt;
8804
+ out.push({
8805
+ kind: "text",
8806
+ text: label,
8807
+ xPt,
8808
+ yPt: pageHeightPt - baselineYDownPt,
8809
+ font: labelFont,
8810
+ sizePt: HEADER_LABEL_SIZE_PT,
8811
+ color: HEADER_LABEL_COLOR
8812
+ });
8813
+ });
8814
+ rowAxis.indices.forEach((rowIndex, position) => {
8815
+ const label = String(rowIndex + 1);
8816
+ const heightPt = rowAxis.sizesPt[position];
8817
+ const labelWidthPt = measurer.widthOfTextAtSize(label, labelFont, HEADER_LABEL_SIZE_PT);
8818
+ const xPt = gridLeftXPt - gutter.widthPt + Math.max(HEADER_LABEL_PADDING_PT, gutter.widthPt - HEADER_LABEL_PADDING_PT - labelWidthPt);
8819
+ const baselineYDownPt = gridTopYDownPt + rowAxis.offsetsPt[position] + Math.max(0, (heightPt - lineHeightPt) / 2) + ascentPt;
8820
+ out.push({
8821
+ kind: "text",
8822
+ text: label,
8823
+ xPt,
8824
+ yPt: pageHeightPt - baselineYDownPt,
8825
+ font: labelFont,
8826
+ sizePt: HEADER_LABEL_SIZE_PT,
8827
+ color: HEADER_LABEL_COLOR
8828
+ });
8829
+ });
8830
+ }
8831
+ function renderGridlines(gridLeftXPt, gridTopYDownPt, gridWidthPt, gridHeightPt, columnOffsetsPt, rowOffsetsPt, pageHeightPt, out) {
8832
+ for (const offsetPt of columnOffsetsPt) {
8833
+ const xPt = gridLeftXPt + offsetPt;
8834
+ const line = {
8835
+ kind: "line",
8836
+ x1Pt: xPt,
8837
+ y1Pt: pageHeightPt - gridTopYDownPt,
8838
+ x2Pt: xPt,
8839
+ y2Pt: pageHeightPt - (gridTopYDownPt + gridHeightPt),
8840
+ color: GRIDLINE_COLOR,
8841
+ widthPt: GRIDLINE_WIDTH_PT
8842
+ };
8843
+ out.push(line);
8844
+ }
8845
+ for (const offsetPt of rowOffsetsPt) {
8846
+ const yDownPt = gridTopYDownPt + offsetPt;
8847
+ const line = {
8848
+ kind: "line",
8849
+ x1Pt: gridLeftXPt,
8850
+ y1Pt: pageHeightPt - yDownPt,
8851
+ x2Pt: gridLeftXPt + gridWidthPt,
8852
+ y2Pt: pageHeightPt - yDownPt,
8853
+ color: GRIDLINE_COLOR,
8854
+ widthPt: GRIDLINE_WIDTH_PT
8855
+ };
8856
+ out.push(line);
8857
+ }
8858
+ }
8859
+ function bandableIndices(start, end, repeat) {
8860
+ const indices = [];
8861
+ for (let i = start; i <= end; i++) {
8862
+ if (repeat !== void 0 && i >= repeat.start && i <= repeat.end) continue;
8863
+ indices.push(i);
8864
+ }
8865
+ return indices;
8866
+ }
8867
+ function rangeIndices(start, end) {
8868
+ const indices = [];
8869
+ for (let i = start; i <= end; i++) indices.push(i);
8870
+ return indices;
8871
+ }
8872
+ function convertSheetToPages(sheet, measurer, signal, out) {
8873
+ throwIfAborted(signal);
8874
+ const range = resolvePrintRange(sheet);
8875
+ if (range === void 0) return;
8876
+ const { printSettings } = sheet;
8877
+ const { pageSize, margins } = printSettings;
8878
+ const pageContentWidthPt = Math.max(0, pageSize.widthPt - margins.leftPt - margins.rightPt);
8879
+ const pageContentHeightPt = Math.max(0, pageSize.heightPt - margins.topPt - margins.bottomPt);
8880
+ const columnEntries = resolveAxis(sheet.columns.map((c) => ({
8881
+ index: c.index,
8882
+ sizePt: c.widthPt,
8883
+ hidden: c.hidden
8884
+ })), range.startColumn, range.endColumn, DEFAULT_COLUMN_WIDTH_PT);
8885
+ const rowEntries = resolveAxis(sheet.rows.map((r) => ({
8886
+ index: r.index,
8887
+ sizePt: r.heightPt,
8888
+ hidden: r.hidden
8889
+ })), range.startRow, range.endRow, DEFAULT_ROW_HEIGHT_PT);
8890
+ const columnSizeByIndex = new Map(columnEntries.map((e) => [e.index, e.sizePt]));
8891
+ const rowSizeByIndex = new Map(rowEntries.map((e) => [e.index, e.sizePt]));
8892
+ const hiddenColumnIndices = new Set(columnEntries.filter((e) => e.hidden).map((e) => e.index));
8893
+ const hiddenRowIndices = new Set(rowEntries.filter((e) => e.hidden).map((e) => e.index));
8894
+ const gutter = computeHeaderGutter(printSettings, range, measurer);
8895
+ const repeatColumns = printSettings.repeatColumns;
8896
+ const repeatRows = printSettings.repeatRows;
8897
+ const repeatColumnIndices = repeatColumns === void 0 ? [] : rangeIndices(repeatColumns.start, repeatColumns.end);
8898
+ const repeatRowIndices = repeatRows === void 0 ? [] : rangeIndices(repeatRows.start, repeatRows.end);
8899
+ const repeatColumnsWidthPt = repeatColumnIndices.reduce((sum, i) => sum + (columnSizeByIndex.get(i) ?? 0), 0);
8900
+ const repeatRowsHeightPt = repeatRowIndices.reduce((sum, i) => sum + (rowSizeByIndex.get(i) ?? 0), 0);
8901
+ const bandableColumnIndices = bandableIndices(range.startColumn, range.endColumn, repeatColumns);
8902
+ const bandableRowIndices = bandableIndices(range.startRow, range.endRow, repeatRows);
8903
+ const availableWidthPt = Math.max(0, pageContentWidthPt - gutter.widthPt - repeatColumnsWidthPt);
8904
+ const availableHeightPt = Math.max(0, pageContentHeightPt - gutter.heightPt - repeatRowsHeightPt);
8905
+ const scale = resolveScale(printSettings, availableWidthPt, availableHeightPt, bandableColumnIndices.reduce((sum, i) => sum + (columnSizeByIndex.get(i) ?? 0), 0), bandableRowIndices.reduce((sum, i) => sum + (rowSizeByIndex.get(i) ?? 0), 0));
8906
+ const descaledAvailableWidthPt = availableWidthPt / scale;
8907
+ const descaledAvailableHeightPt = availableHeightPt / scale;
8908
+ const manualBreakColumns = new Set(printSettings.manualBreaks?.columns ?? []);
8909
+ const manualBreakRows = new Set(printSettings.manualBreaks?.rows ?? []);
8910
+ throwIfAborted(signal);
8911
+ const columnBands = partitionIndices(bandableColumnIndices, (i) => columnSizeByIndex.get(i) ?? 0, descaledAvailableWidthPt, manualBreakColumns);
8912
+ const rowBands = partitionIndices(bandableRowIndices, (i) => rowSizeByIndex.get(i) ?? 0, descaledAvailableHeightPt, manualBreakRows);
8913
+ const cellsByRow = /* @__PURE__ */ new Map();
8914
+ for (const cell of sheet.cells) {
8915
+ let row = cellsByRow.get(cell.row);
8916
+ if (row === void 0) {
8917
+ row = /* @__PURE__ */ new Map();
8918
+ cellsByRow.set(cell.row, row);
8919
+ }
8920
+ row.set(cell.column, cell);
8921
+ }
8922
+ const scaledSizeOf = (sizeByIndex) => (index) => (sizeByIndex.get(index) ?? 0) * scale;
8923
+ const unscaledSizeOf = (sizeByIndex) => (index) => sizeByIndex.get(index) ?? 0;
8924
+ const bandPairs = printSettings.pageOrder === "overThenDown" ? rowBands.flatMap((rowBand) => columnBands.map((columnBand) => ({
8925
+ columnBand,
8926
+ rowBand
8927
+ }))) : columnBands.flatMap((columnBand) => rowBands.map((rowBand) => ({
8928
+ columnBand,
8929
+ rowBand
8930
+ })));
8931
+ for (const { columnBand, rowBand } of bandPairs) {
8932
+ throwIfAborted(signal);
8933
+ const columnAxis = buildPositionedAxis(repeatColumnIndices, unscaledSizeOf(columnSizeByIndex), columnBand, scaledSizeOf(columnSizeByIndex));
8934
+ const rowAxis = buildPositionedAxis(repeatRowIndices, unscaledSizeOf(rowSizeByIndex), rowBand, scaledSizeOf(rowSizeByIndex));
8935
+ const gridLeftXPt = margins.leftPt + gutter.widthPt;
8936
+ const gridTopYDownPt = margins.topPt + gutter.heightPt;
8937
+ const gridWidthPt = columnAxis.offsetsPt[columnAxis.offsetsPt.length - 1];
8938
+ const gridHeightPt = rowAxis.offsetsPt[rowAxis.offsetsPt.length - 1];
8939
+ const items = [];
8940
+ if (printSettings.gridlines) renderGridlines(gridLeftXPt, gridTopYDownPt, gridWidthPt, gridHeightPt, columnAxis.offsetsPt, rowAxis.offsetsPt, pageSize.heightPt, items);
8941
+ if (printSettings.headers) renderHeaderLabels(gutter, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageSize.heightPt, measurer, items);
8942
+ for (const rowIndex of rowAxis.indices) {
8943
+ const rowCells = cellsByRow.get(rowIndex);
8944
+ if (rowCells === void 0) continue;
8945
+ for (const [columnIndex, cell] of rowCells) {
8946
+ throwIfAborted(signal);
8947
+ if (!columnAxis.positionByIndex.has(columnIndex) || hiddenColumnIndices.has(columnIndex) || hiddenRowIndices.has(cell.row)) continue;
8948
+ renderCellText(cell, rowCells, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageSize.heightPt, measurer, items);
8949
+ }
8950
+ }
8951
+ out.push({
8952
+ widthPt: pageSize.widthPt,
8953
+ heightPt: pageSize.heightPt,
8954
+ items
8955
+ });
8956
+ }
8957
+ }
8958
+ function convertSpreadsheetToLayout(doc, options) {
8959
+ const pages = [];
8960
+ for (const sheet of doc.sheets) convertSheetToPages(sheet, options.measurer, options.signal, pages);
8961
+ return {
8962
+ formatVersion: LAYOUT_FORMAT_VERSION$1,
8963
+ metadata: doc.metadata,
8964
+ pages,
8965
+ images: {}
8966
+ };
8967
+ }
8968
+ //#endregion
8077
8969
  //#region src/layout/reconstruct.ts
8078
8970
  const ZERO_MARGINS = {
8079
8971
  topPt: 0,
@@ -8442,6 +9334,17 @@ function odpToPdf(bytes, options) {
8442
9334
  onSubstitution: options?.onSubstitution
8443
9335
  });
8444
9336
  }
9337
+ function odsToPdf(bytes, options) {
9338
+ const content = readOdsContent(decodePackage$2(bytes));
9339
+ if (content.kind !== "spreadsheet") throw new Error("readOdsContent returned a non-spreadsheet ContentDocument");
9340
+ return writePdf(convertSpreadsheetToLayout(content, {
9341
+ measurer: createStandardFontMeasurer(),
9342
+ signal: options?.signal
9343
+ }), {
9344
+ signal: options?.signal,
9345
+ onSubstitution: options?.onSubstitution
9346
+ });
9347
+ }
8445
9348
  function pdfToDocx(bytes, options) {
8446
9349
  const content = reconstructWordprocessing(readPdf(bytes, {
8447
9350
  signal: options?.signal,
@@ -8463,6 +9366,13 @@ function pdfToOdt(bytes, options) {
8463
9366
  }), { signal: options?.signal });
8464
9367
  return encodePackage$2(buildOdtPackage(content));
8465
9368
  }
9369
+ function pdfToOdp(bytes, options) {
9370
+ const content = reconstructPresentation(readPdf(bytes, {
9371
+ signal: options?.signal,
9372
+ sink: options?.sink
9373
+ }), { signal: options?.signal });
9374
+ return encodePackage$2(buildOdpPackage(content));
9375
+ }
8466
9376
  //#endregion
8467
9377
  //#region src/convert/codec.ts
8468
9378
  const docxPdfCodec = z.codec(DocxBytesSchema, PdfBytesSchema, {
@@ -8477,6 +9387,10 @@ const odtPdfCodec = z.codec(OdtBytesSchema, PdfBytesSchema, {
8477
9387
  decode: (odtBytes) => odtToPdf(odtBytes),
8478
9388
  encode: (pdfBytes) => pdfToOdt(pdfBytes)
8479
9389
  });
9390
+ const odpPdfCodec = z.codec(OdpBytesSchema, PdfBytesSchema, {
9391
+ decode: (odpBytes) => odpToPdf(odpBytes),
9392
+ encode: (pdfBytes) => pdfToOdp(pdfBytes)
9393
+ });
8480
9394
  //#endregion
8481
9395
  //#region src/convert/local.ts
8482
9396
  const SUPPORTED_CONVERSIONS = [
@@ -8496,6 +9410,10 @@ const SUPPORTED_CONVERSIONS = [
8496
9410
  source: "odp",
8497
9411
  target: "pdf"
8498
9412
  },
9413
+ {
9414
+ source: "ods",
9415
+ target: "pdf"
9416
+ },
8499
9417
  {
8500
9418
  source: "pdf",
8501
9419
  target: "docx"
@@ -8507,6 +9425,10 @@ const SUPPORTED_CONVERSIONS = [
8507
9425
  {
8508
9426
  source: "pdf",
8509
9427
  target: "odt"
9428
+ },
9429
+ {
9430
+ source: "pdf",
9431
+ target: "odp"
8510
9432
  }
8511
9433
  ];
8512
9434
  function substitutionDiagnostic(substitution, context) {
@@ -8584,6 +9506,19 @@ function createLocalDocumentConverter() {
8584
9506
  diagnostics
8585
9507
  });
8586
9508
  }
9509
+ if (source.format === "ods" && targetFormat === "pdf") {
9510
+ const bytes = odsToPdf(source.bytes, {
9511
+ signal: options.signal,
9512
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
9513
+ });
9514
+ return Promise.resolve({
9515
+ document: {
9516
+ format: "pdf",
9517
+ bytes
9518
+ },
9519
+ diagnostics
9520
+ });
9521
+ }
8587
9522
  if (source.format === "pdf" && targetFormat === "docx") {
8588
9523
  const bytes = pdfToDocx(source.bytes, {
8589
9524
  signal: options.signal,
@@ -8623,6 +9558,19 @@ function createLocalDocumentConverter() {
8623
9558
  diagnostics
8624
9559
  });
8625
9560
  }
9561
+ if (source.format === "pdf" && targetFormat === "odp") {
9562
+ const bytes = pdfToOdp(source.bytes, {
9563
+ signal: options.signal,
9564
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
9565
+ });
9566
+ return Promise.resolve({
9567
+ document: {
9568
+ format: "odp",
9569
+ bytes
9570
+ },
9571
+ diagnostics
9572
+ });
9573
+ }
8626
9574
  return Promise.reject(/* @__PURE__ */ new Error(`unsupported conversion: ${source.format} -> ${targetFormat}`));
8627
9575
  }
8628
9576
  };
@@ -8634,4 +9582,4 @@ function fixedClock(date) {
8634
9582
  return { now: () => date };
8635
9583
  }
8636
9584
  //#endregion
8637
- export { AttributeSchema, BinaryPartSchema, COLOR_BLACK, CONTENT_FORMAT_VERSION, CommentSchema, CompactPackageSchema, CompactPartSchema, CompactXmlNodeSchema, ContentBlockSchema, ContentDocumentSchema, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentRunSchema, ContentSectionSchema, ContentShapeSchema, ContentSlideSchema, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, DEFAULT_LAYOUT_FONT, DefinedNameSchema, DocxBytesSchema, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, LAYOUT_FORMAT_VERSION, NOOP_DIAGNOSTIC_SINK, OdgBytesSchema, OdpBytesSchema, OdsBytesSchema, OdtBytesSchema, OdtEditor, OdtList, OdtListItem, OdtParagraph, OdtRun, OdtTable, OdtTableCell, OdtTableRow, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PackageSchema, PartSchema, PdfBytesSchema, PdfEncryptedError, PdfParseError, PptxBytesSchema, PptxEditor, PptxShape, PptxSlide, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildOdtPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createOdt, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxPdfCodec, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, odpToPdf, odtPdfCodec, odtToPdf, openDocx, openOdt, openPptx, packageCodec, parsePackage, parseXml, pdfCodec, pdfToDocx, pdfToOdt, pdfToPptx, pptxPdfCodec, pptxToPdf, readDocxContent, readOdpContent, readOdtContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };
9585
+ export { AttributeSchema, BinaryPartSchema, COLOR_BLACK, CONTENT_FORMAT_VERSION, CommentSchema, CompactPackageSchema, CompactPartSchema, CompactXmlNodeSchema, ContentBlockSchema, ContentCellValueSchema, ContentDocumentSchema, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentRunSchema, ContentSectionSchema, ContentShapeSchema, ContentSheetCellSchema, ContentSheetColumnSchema, ContentSheetPrintRangeSchema, ContentSheetPrintSettingsSchema, ContentSheetRepeatRangeSchema, ContentSheetRowSchema, ContentSheetSchema, ContentSlideSchema, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, DEFAULT_LAYOUT_FONT, DefinedNameSchema, DocxBytesSchema, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, LAYOUT_FORMAT_VERSION, NOOP_DIAGNOSTIC_SINK, OdgBytesSchema, OdpBytesSchema, OdpEditor, OdpShape, OdpSlide, OdsBytesSchema, OdtBytesSchema, OdtEditor, OdtList, OdtListItem, OdtParagraph, OdtRun, OdtTable, OdtTableCell, OdtTableRow, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PackageSchema, PartSchema, PdfBytesSchema, PdfEncryptedError, PdfParseError, PptxBytesSchema, PptxEditor, PptxShape, PptxSlide, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildOdpPackage, buildOdtPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertSpreadsheetToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createOdp, createOdt, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxPdfCodec, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, odpPdfCodec, odpToPdf, odsToPdf, odtPdfCodec, odtToPdf, openDocx, openOdp, openOdt, openPptx, packageCodec, parsePackage, parseXml, pdfCodec, pdfToDocx, pdfToOdp, pdfToOdt, pdfToPptx, pptxPdfCodec, pptxToPdf, readDocxContent, readOdpContent, readOdsContent, readOdtContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };