documents.js 1.41.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.cjs CHANGED
@@ -6,17 +6,26 @@ let odf_js = require("odf.js");
6
6
  let fflate = require("fflate");
7
7
  //#region src/model/content.ts
8
8
  const CONTENT_FORMAT_VERSION = 1;
9
- const ContentDocumentSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
10
- kind: zod.z.literal("wordprocessing"),
11
- formatVersion: zod.z.literal(1),
12
- metadata: document_content_model.LayoutMetadataSchema,
13
- sections: zod.z.array(document_content_model.ContentSectionSchema)
14
- }), zod.z.object({
15
- kind: zod.z.literal("presentation"),
16
- formatVersion: zod.z.literal(1),
17
- metadata: document_content_model.LayoutMetadataSchema,
18
- slides: zod.z.array(document_content_model.ContentSlideSchema)
19
- })]);
9
+ const ContentDocumentSchema = zod.z.discriminatedUnion("kind", [
10
+ zod.z.object({
11
+ kind: zod.z.literal("wordprocessing"),
12
+ formatVersion: zod.z.literal(1),
13
+ metadata: document_content_model.LayoutMetadataSchema,
14
+ sections: zod.z.array(document_content_model.ContentSectionSchema)
15
+ }),
16
+ zod.z.object({
17
+ kind: zod.z.literal("presentation"),
18
+ formatVersion: zod.z.literal(1),
19
+ metadata: document_content_model.LayoutMetadataSchema,
20
+ slides: zod.z.array(document_content_model.ContentSlideSchema)
21
+ }),
22
+ zod.z.object({
23
+ kind: zod.z.literal("spreadsheet"),
24
+ formatVersion: zod.z.literal(1),
25
+ metadata: document_content_model.LayoutMetadataSchema,
26
+ sheets: zod.z.array(document_content_model.ContentSheetSchema)
27
+ })
28
+ ]);
20
29
  //#endregion
21
30
  //#region src/model/geometry.ts
22
31
  function flipY(box, containerHeightPt) {
@@ -7916,6 +7925,17 @@ function readOdpContent(pkg) {
7916
7925
  };
7917
7926
  }
7918
7927
  //#endregion
7928
+ //#region src/odf/ods/read.ts
7929
+ function readOdsContent(pkg) {
7930
+ const odsDoc = (0, odf_js.readOds)(pkg);
7931
+ return {
7932
+ kind: "spreadsheet",
7933
+ formatVersion: 1,
7934
+ metadata: { ...odsDoc.metadata },
7935
+ sheets: odsDoc.sheets
7936
+ };
7937
+ }
7938
+ //#endregion
7919
7939
  //#region src/pdf/text-layout.ts
7920
7940
  const WORD_OR_WHITESPACE_PATTERN = /\n|\s+|\S+/g;
7921
7941
  function atomizeRuns(runs, measurer) {
@@ -8543,6 +8563,410 @@ function convertPresentationToLayout(doc, options) {
8543
8563
  };
8544
8564
  }
8545
8565
  //#endregion
8566
+ //#region src/layout/sheets.ts
8567
+ const DEFAULT_COLUMN_WIDTH_PT = 64;
8568
+ const DEFAULT_ROW_HEIGHT_PT = 15;
8569
+ const NOMINAL_CELL_TEXT_SIZE_PT = 10;
8570
+ const HEADER_LABEL_SIZE_PT = 8;
8571
+ const CELL_TEXT_PADDING_PT = 2;
8572
+ const HEADER_LABEL_PADDING_PT = 2;
8573
+ const MINIMUM_SCALE = .01;
8574
+ const NUMERIC_OVERFLOW_TEXT = "###";
8575
+ const GRIDLINE_COLOR = (0, document_content_model.rgbHexToColor)("#D0D0D0");
8576
+ const GRIDLINE_WIDTH_PT = .5;
8577
+ const HEADER_LABEL_COLOR = (0, document_content_model.rgbHexToColor)("#606060");
8578
+ function columnLetters(index) {
8579
+ let n = index + 1;
8580
+ let letters = "";
8581
+ while (n > 0) {
8582
+ const remainder = (n - 1) % 26;
8583
+ letters = String.fromCharCode(65 + remainder) + letters;
8584
+ n = Math.floor((n - 1) / 26);
8585
+ }
8586
+ return letters;
8587
+ }
8588
+ function resolvePrintRange(sheet) {
8589
+ if (sheet.printSettings.printRange !== void 0) return sheet.printSettings.printRange;
8590
+ if (sheet.cells.length === 0) return;
8591
+ let startRow = Number.POSITIVE_INFINITY;
8592
+ let startColumn = Number.POSITIVE_INFINITY;
8593
+ let endRow = Number.NEGATIVE_INFINITY;
8594
+ let endColumn = Number.NEGATIVE_INFINITY;
8595
+ for (const cell of sheet.cells) {
8596
+ startRow = Math.min(startRow, cell.row);
8597
+ startColumn = Math.min(startColumn, cell.column);
8598
+ endRow = Math.max(endRow, cell.row + (cell.rowSpan ?? 1) - 1);
8599
+ endColumn = Math.max(endColumn, cell.column + (cell.colSpan ?? 1) - 1);
8600
+ }
8601
+ return {
8602
+ startRow,
8603
+ startColumn,
8604
+ endRow,
8605
+ endColumn
8606
+ };
8607
+ }
8608
+ function resolveAxis(entries, start, end, defaultSizePt) {
8609
+ const sorted = [...entries].sort((a, b) => a.index - b.index);
8610
+ const resolved = [];
8611
+ let pointer = 0;
8612
+ let currentSizePt = defaultSizePt;
8613
+ let currentHidden = false;
8614
+ for (let index = start; index <= end; index++) {
8615
+ while (pointer < sorted.length && sorted[pointer].index <= index) {
8616
+ currentSizePt = sorted[pointer].sizePt;
8617
+ currentHidden = sorted[pointer].hidden ?? false;
8618
+ pointer++;
8619
+ }
8620
+ resolved.push({
8621
+ index,
8622
+ sizePt: currentHidden ? 0 : currentSizePt,
8623
+ hidden: currentHidden
8624
+ });
8625
+ }
8626
+ return resolved;
8627
+ }
8628
+ function computeHeaderGutter(printSettings, range, measurer) {
8629
+ if (!printSettings.headers) return {
8630
+ widthPt: 0,
8631
+ heightPt: 0
8632
+ };
8633
+ const widestRowLabel = String(range.endRow + 1);
8634
+ return {
8635
+ widthPt: measurer.widthOfTextAtSize(widestRowLabel, document_content_model.DEFAULT_LAYOUT_FONT, HEADER_LABEL_SIZE_PT) + 4,
8636
+ heightPt: measurer.lineHeightAtSize(document_content_model.DEFAULT_LAYOUT_FONT, HEADER_LABEL_SIZE_PT)
8637
+ };
8638
+ }
8639
+ function resolveScale(printSettings, availableWidthPt, availableHeightPt, totalContentWidthPt, totalContentHeightPt) {
8640
+ if (printSettings.scale !== void 0) return Math.max(printSettings.scale / 100, MINIMUM_SCALE);
8641
+ if (printSettings.fitToPages !== void 0) {
8642
+ const budgetWidthPt = availableWidthPt * printSettings.fitToPages.width;
8643
+ const budgetHeightPt = availableHeightPt * printSettings.fitToPages.height;
8644
+ const widthRatio = totalContentWidthPt > 0 ? budgetWidthPt / totalContentWidthPt : 1;
8645
+ const heightRatio = totalContentHeightPt > 0 ? budgetHeightPt / totalContentHeightPt : 1;
8646
+ return Math.max(Math.min(widthRatio, heightRatio, 1), MINIMUM_SCALE);
8647
+ }
8648
+ return 1;
8649
+ }
8650
+ function partitionIndices(indices, sizeOf, availablePt, manualBreaks) {
8651
+ const bands = [];
8652
+ let current = [];
8653
+ let currentSizePt = 0;
8654
+ for (const index of indices) {
8655
+ if (manualBreaks.has(index) && current.length > 0) {
8656
+ bands.push(current);
8657
+ current = [];
8658
+ currentSizePt = 0;
8659
+ }
8660
+ const sizePt = sizeOf(index);
8661
+ if (current.length > 0 && currentSizePt + sizePt > availablePt) {
8662
+ bands.push(current);
8663
+ current = [];
8664
+ currentSizePt = 0;
8665
+ }
8666
+ current.push(index);
8667
+ currentSizePt += sizePt;
8668
+ }
8669
+ if (current.length > 0) bands.push(current);
8670
+ return bands;
8671
+ }
8672
+ function cellStyledRuns(cell) {
8673
+ if (cell.runs !== void 0 && cell.runs.length > 0) return toStyledRuns(cell.runs.map((run) => run.sizePt === void 0 ? {
8674
+ ...run,
8675
+ sizePt: NOMINAL_CELL_TEXT_SIZE_PT
8676
+ } : run));
8677
+ return [{
8678
+ text: cell.displayText,
8679
+ font: document_content_model.DEFAULT_LAYOUT_FONT,
8680
+ sizePt: NOMINAL_CELL_TEXT_SIZE_PT,
8681
+ color: document_content_model.COLOR_BLACK
8682
+ }];
8683
+ }
8684
+ function isNumericLikeValue(kind) {
8685
+ return kind === "number" || kind === "percentage" || kind === "currency" || kind === "date" || kind === "time";
8686
+ }
8687
+ function defaultAlignmentForValue(kind) {
8688
+ if (isNumericLikeValue(kind)) return "right";
8689
+ if (kind === "boolean" || kind === "error") return "center";
8690
+ return "left";
8691
+ }
8692
+ function isCellVisuallyEmpty(cell) {
8693
+ return cell === void 0 || cell.value.kind === "empty" && cell.displayText.length === 0;
8694
+ }
8695
+ function truncateFragmentsToWidth(fragments, measurer, maxWidthPt) {
8696
+ const result = [];
8697
+ for (const fragment of fragments) {
8698
+ if (fragment.xOffsetPt >= maxWidthPt) break;
8699
+ const remainingWidthPt = maxWidthPt - fragment.xOffsetPt;
8700
+ if (measurer.widthOfTextAtSize(fragment.text, fragment.font, fragment.sizePt) <= remainingWidthPt) {
8701
+ result.push(fragment);
8702
+ continue;
8703
+ }
8704
+ const chars = Array.from(fragment.text);
8705
+ let width = 0;
8706
+ let fitCount = 0;
8707
+ for (const char of chars) {
8708
+ const charWidthPt = measurer.widthOfTextAtSize(char, fragment.font, fragment.sizePt);
8709
+ if (width + charWidthPt > remainingWidthPt) break;
8710
+ width += charWidthPt;
8711
+ fitCount++;
8712
+ }
8713
+ if (fitCount > 0) result.push({
8714
+ ...fragment,
8715
+ text: chars.slice(0, fitCount).join("")
8716
+ });
8717
+ break;
8718
+ }
8719
+ return result;
8720
+ }
8721
+ function buildPositionedAxis(repeatIndices, repeatSizePtOf, bandIndices, bandSizePtOf) {
8722
+ const indices = [...repeatIndices, ...bandIndices];
8723
+ const sizesPt = [...repeatIndices.map(repeatSizePtOf), ...bandIndices.map(bandSizePtOf)];
8724
+ const offsetsPt = [0];
8725
+ let running = 0;
8726
+ for (const size of sizesPt) {
8727
+ running += size;
8728
+ offsetsPt.push(running);
8729
+ }
8730
+ return {
8731
+ indices,
8732
+ sizesPt,
8733
+ offsetsPt,
8734
+ positionByIndex: new Map(indices.map((index, position) => [index, position]))
8735
+ };
8736
+ }
8737
+ function axisSpanSizePt(axis, startIndex, span) {
8738
+ const startPosition = axis.positionByIndex.get(startIndex);
8739
+ if (startPosition === void 0) return 0;
8740
+ return sumColumnWidthsPt(axis.sizesPt, startPosition, span);
8741
+ }
8742
+ function renderCellText(cell, rowCells, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageHeightPt, measurer, out) {
8743
+ const columnPosition = columnAxis.positionByIndex.get(cell.column);
8744
+ const rowPosition = rowAxis.positionByIndex.get(cell.row);
8745
+ if (columnPosition === void 0 || rowPosition === void 0) return;
8746
+ const ownWidthPt = axisSpanSizePt(columnAxis, cell.column, cell.colSpan ?? 1);
8747
+ const heightPt = axisSpanSizePt(rowAxis, cell.row, cell.rowSpan ?? 1);
8748
+ const xLeftPt = gridLeftXPt + columnAxis.offsetsPt[columnPosition];
8749
+ const yTopDownPt = gridTopYDownPt + rowAxis.offsetsPt[rowPosition];
8750
+ const alignment = defaultAlignmentForValue(cell.value.kind);
8751
+ const numericLike = isNumericLikeValue(cell.value.kind);
8752
+ const styledRuns = cellStyledRuns(cell);
8753
+ const naturalLine = wrapRunsToWidth(styledRuns, measurer, Number.POSITIVE_INFINITY)[0];
8754
+ let availableWidthPt = Math.max(0, ownWidthPt - 4);
8755
+ let fragments = naturalLine.fragments;
8756
+ let lineWidthPt = naturalLine.widthPt;
8757
+ if (lineWidthPt > availableWidthPt) if (numericLike) {
8758
+ const overflowLine = wrapRunsToWidth([{
8759
+ text: NUMERIC_OVERFLOW_TEXT,
8760
+ font: styledRuns[0].font,
8761
+ sizePt: styledRuns[0].sizePt,
8762
+ color: styledRuns[0].color
8763
+ }], measurer, Number.POSITIVE_INFINITY)[0];
8764
+ fragments = overflowLine.fragments;
8765
+ lineWidthPt = overflowLine.widthPt;
8766
+ } else if (cell.value.kind === "string") {
8767
+ let spillColumn = cell.column + (cell.colSpan ?? 1);
8768
+ while (lineWidthPt > availableWidthPt) {
8769
+ const neighborPosition = columnAxis.positionByIndex.get(spillColumn);
8770
+ if (neighborPosition === void 0 || !isCellVisuallyEmpty(rowCells?.get(spillColumn))) break;
8771
+ availableWidthPt += columnAxis.sizesPt[neighborPosition];
8772
+ spillColumn++;
8773
+ }
8774
+ if (lineWidthPt > availableWidthPt) fragments = truncateFragmentsToWidth(fragments, measurer, availableWidthPt);
8775
+ } else fragments = truncateFragmentsToWidth(fragments, measurer, availableWidthPt);
8776
+ const alignOffsetPt = alignmentOffsetPt(alignment, availableWidthPt, lineWidthPt);
8777
+ const textStartXPt = xLeftPt + CELL_TEXT_PADDING_PT + alignOffsetPt;
8778
+ const lineHeightPt = lineNaturalHeightPt(naturalLine, measurer, styledRuns[0]);
8779
+ const baselineYDownPt = yTopDownPt + Math.max(CELL_TEXT_PADDING_PT, heightPt - CELL_TEXT_PADDING_PT - lineHeightPt) + naturalLine.ascentPt;
8780
+ for (const fragment of fragments) {
8781
+ const textItem = {
8782
+ kind: "text",
8783
+ text: fragment.text,
8784
+ xPt: textStartXPt + fragment.xOffsetPt,
8785
+ yPt: pageHeightPt - baselineYDownPt,
8786
+ font: fragment.font,
8787
+ sizePt: fragment.sizePt,
8788
+ color: fragment.color,
8789
+ underline: fragment.underline,
8790
+ sourcePath: fragment.sourcePath
8791
+ };
8792
+ out.push(textItem);
8793
+ }
8794
+ }
8795
+ function renderHeaderLabels(gutter, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageHeightPt, measurer, out) {
8796
+ const labelFont = document_content_model.DEFAULT_LAYOUT_FONT;
8797
+ const lineHeightPt = measurer.lineHeightAtSize(labelFont, HEADER_LABEL_SIZE_PT);
8798
+ const ascentPt = measurer.ascenderAtSize(labelFont, HEADER_LABEL_SIZE_PT);
8799
+ columnAxis.indices.forEach((columnIndex, position) => {
8800
+ const label = columnLetters(columnIndex);
8801
+ const widthPt = columnAxis.sizesPt[position];
8802
+ const labelWidthPt = measurer.widthOfTextAtSize(label, labelFont, HEADER_LABEL_SIZE_PT);
8803
+ const xPt = gridLeftXPt + columnAxis.offsetsPt[position] + alignmentOffsetPt("center", widthPt, labelWidthPt);
8804
+ const baselineYDownPt = gridTopYDownPt - gutter.heightPt + (gutter.heightPt - lineHeightPt) / 2 + ascentPt;
8805
+ out.push({
8806
+ kind: "text",
8807
+ text: label,
8808
+ xPt,
8809
+ yPt: pageHeightPt - baselineYDownPt,
8810
+ font: labelFont,
8811
+ sizePt: HEADER_LABEL_SIZE_PT,
8812
+ color: HEADER_LABEL_COLOR
8813
+ });
8814
+ });
8815
+ rowAxis.indices.forEach((rowIndex, position) => {
8816
+ const label = String(rowIndex + 1);
8817
+ const heightPt = rowAxis.sizesPt[position];
8818
+ const labelWidthPt = measurer.widthOfTextAtSize(label, labelFont, HEADER_LABEL_SIZE_PT);
8819
+ const xPt = gridLeftXPt - gutter.widthPt + Math.max(HEADER_LABEL_PADDING_PT, gutter.widthPt - HEADER_LABEL_PADDING_PT - labelWidthPt);
8820
+ const baselineYDownPt = gridTopYDownPt + rowAxis.offsetsPt[position] + Math.max(0, (heightPt - lineHeightPt) / 2) + ascentPt;
8821
+ out.push({
8822
+ kind: "text",
8823
+ text: label,
8824
+ xPt,
8825
+ yPt: pageHeightPt - baselineYDownPt,
8826
+ font: labelFont,
8827
+ sizePt: HEADER_LABEL_SIZE_PT,
8828
+ color: HEADER_LABEL_COLOR
8829
+ });
8830
+ });
8831
+ }
8832
+ function renderGridlines(gridLeftXPt, gridTopYDownPt, gridWidthPt, gridHeightPt, columnOffsetsPt, rowOffsetsPt, pageHeightPt, out) {
8833
+ for (const offsetPt of columnOffsetsPt) {
8834
+ const xPt = gridLeftXPt + offsetPt;
8835
+ const line = {
8836
+ kind: "line",
8837
+ x1Pt: xPt,
8838
+ y1Pt: pageHeightPt - gridTopYDownPt,
8839
+ x2Pt: xPt,
8840
+ y2Pt: pageHeightPt - (gridTopYDownPt + gridHeightPt),
8841
+ color: GRIDLINE_COLOR,
8842
+ widthPt: GRIDLINE_WIDTH_PT
8843
+ };
8844
+ out.push(line);
8845
+ }
8846
+ for (const offsetPt of rowOffsetsPt) {
8847
+ const yDownPt = gridTopYDownPt + offsetPt;
8848
+ const line = {
8849
+ kind: "line",
8850
+ x1Pt: gridLeftXPt,
8851
+ y1Pt: pageHeightPt - yDownPt,
8852
+ x2Pt: gridLeftXPt + gridWidthPt,
8853
+ y2Pt: pageHeightPt - yDownPt,
8854
+ color: GRIDLINE_COLOR,
8855
+ widthPt: GRIDLINE_WIDTH_PT
8856
+ };
8857
+ out.push(line);
8858
+ }
8859
+ }
8860
+ function bandableIndices(start, end, repeat) {
8861
+ const indices = [];
8862
+ for (let i = start; i <= end; i++) {
8863
+ if (repeat !== void 0 && i >= repeat.start && i <= repeat.end) continue;
8864
+ indices.push(i);
8865
+ }
8866
+ return indices;
8867
+ }
8868
+ function rangeIndices(start, end) {
8869
+ const indices = [];
8870
+ for (let i = start; i <= end; i++) indices.push(i);
8871
+ return indices;
8872
+ }
8873
+ function convertSheetToPages(sheet, measurer, signal, out) {
8874
+ throwIfAborted(signal);
8875
+ const range = resolvePrintRange(sheet);
8876
+ if (range === void 0) return;
8877
+ const { printSettings } = sheet;
8878
+ const { pageSize, margins } = printSettings;
8879
+ const pageContentWidthPt = Math.max(0, pageSize.widthPt - margins.leftPt - margins.rightPt);
8880
+ const pageContentHeightPt = Math.max(0, pageSize.heightPt - margins.topPt - margins.bottomPt);
8881
+ const columnEntries = resolveAxis(sheet.columns.map((c) => ({
8882
+ index: c.index,
8883
+ sizePt: c.widthPt,
8884
+ hidden: c.hidden
8885
+ })), range.startColumn, range.endColumn, DEFAULT_COLUMN_WIDTH_PT);
8886
+ const rowEntries = resolveAxis(sheet.rows.map((r) => ({
8887
+ index: r.index,
8888
+ sizePt: r.heightPt,
8889
+ hidden: r.hidden
8890
+ })), range.startRow, range.endRow, DEFAULT_ROW_HEIGHT_PT);
8891
+ const columnSizeByIndex = new Map(columnEntries.map((e) => [e.index, e.sizePt]));
8892
+ const rowSizeByIndex = new Map(rowEntries.map((e) => [e.index, e.sizePt]));
8893
+ const hiddenColumnIndices = new Set(columnEntries.filter((e) => e.hidden).map((e) => e.index));
8894
+ const hiddenRowIndices = new Set(rowEntries.filter((e) => e.hidden).map((e) => e.index));
8895
+ const gutter = computeHeaderGutter(printSettings, range, measurer);
8896
+ const repeatColumns = printSettings.repeatColumns;
8897
+ const repeatRows = printSettings.repeatRows;
8898
+ const repeatColumnIndices = repeatColumns === void 0 ? [] : rangeIndices(repeatColumns.start, repeatColumns.end);
8899
+ const repeatRowIndices = repeatRows === void 0 ? [] : rangeIndices(repeatRows.start, repeatRows.end);
8900
+ const repeatColumnsWidthPt = repeatColumnIndices.reduce((sum, i) => sum + (columnSizeByIndex.get(i) ?? 0), 0);
8901
+ const repeatRowsHeightPt = repeatRowIndices.reduce((sum, i) => sum + (rowSizeByIndex.get(i) ?? 0), 0);
8902
+ const bandableColumnIndices = bandableIndices(range.startColumn, range.endColumn, repeatColumns);
8903
+ const bandableRowIndices = bandableIndices(range.startRow, range.endRow, repeatRows);
8904
+ const availableWidthPt = Math.max(0, pageContentWidthPt - gutter.widthPt - repeatColumnsWidthPt);
8905
+ const availableHeightPt = Math.max(0, pageContentHeightPt - gutter.heightPt - repeatRowsHeightPt);
8906
+ 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));
8907
+ const descaledAvailableWidthPt = availableWidthPt / scale;
8908
+ const descaledAvailableHeightPt = availableHeightPt / scale;
8909
+ const manualBreakColumns = new Set(printSettings.manualBreaks?.columns ?? []);
8910
+ const manualBreakRows = new Set(printSettings.manualBreaks?.rows ?? []);
8911
+ throwIfAborted(signal);
8912
+ const columnBands = partitionIndices(bandableColumnIndices, (i) => columnSizeByIndex.get(i) ?? 0, descaledAvailableWidthPt, manualBreakColumns);
8913
+ const rowBands = partitionIndices(bandableRowIndices, (i) => rowSizeByIndex.get(i) ?? 0, descaledAvailableHeightPt, manualBreakRows);
8914
+ const cellsByRow = /* @__PURE__ */ new Map();
8915
+ for (const cell of sheet.cells) {
8916
+ let row = cellsByRow.get(cell.row);
8917
+ if (row === void 0) {
8918
+ row = /* @__PURE__ */ new Map();
8919
+ cellsByRow.set(cell.row, row);
8920
+ }
8921
+ row.set(cell.column, cell);
8922
+ }
8923
+ const scaledSizeOf = (sizeByIndex) => (index) => (sizeByIndex.get(index) ?? 0) * scale;
8924
+ const unscaledSizeOf = (sizeByIndex) => (index) => sizeByIndex.get(index) ?? 0;
8925
+ const bandPairs = printSettings.pageOrder === "overThenDown" ? rowBands.flatMap((rowBand) => columnBands.map((columnBand) => ({
8926
+ columnBand,
8927
+ rowBand
8928
+ }))) : columnBands.flatMap((columnBand) => rowBands.map((rowBand) => ({
8929
+ columnBand,
8930
+ rowBand
8931
+ })));
8932
+ for (const { columnBand, rowBand } of bandPairs) {
8933
+ throwIfAborted(signal);
8934
+ const columnAxis = buildPositionedAxis(repeatColumnIndices, unscaledSizeOf(columnSizeByIndex), columnBand, scaledSizeOf(columnSizeByIndex));
8935
+ const rowAxis = buildPositionedAxis(repeatRowIndices, unscaledSizeOf(rowSizeByIndex), rowBand, scaledSizeOf(rowSizeByIndex));
8936
+ const gridLeftXPt = margins.leftPt + gutter.widthPt;
8937
+ const gridTopYDownPt = margins.topPt + gutter.heightPt;
8938
+ const gridWidthPt = columnAxis.offsetsPt[columnAxis.offsetsPt.length - 1];
8939
+ const gridHeightPt = rowAxis.offsetsPt[rowAxis.offsetsPt.length - 1];
8940
+ const items = [];
8941
+ if (printSettings.gridlines) renderGridlines(gridLeftXPt, gridTopYDownPt, gridWidthPt, gridHeightPt, columnAxis.offsetsPt, rowAxis.offsetsPt, pageSize.heightPt, items);
8942
+ if (printSettings.headers) renderHeaderLabels(gutter, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageSize.heightPt, measurer, items);
8943
+ for (const rowIndex of rowAxis.indices) {
8944
+ const rowCells = cellsByRow.get(rowIndex);
8945
+ if (rowCells === void 0) continue;
8946
+ for (const [columnIndex, cell] of rowCells) {
8947
+ throwIfAborted(signal);
8948
+ if (!columnAxis.positionByIndex.has(columnIndex) || hiddenColumnIndices.has(columnIndex) || hiddenRowIndices.has(cell.row)) continue;
8949
+ renderCellText(cell, rowCells, columnAxis, rowAxis, gridLeftXPt, gridTopYDownPt, pageSize.heightPt, measurer, items);
8950
+ }
8951
+ }
8952
+ out.push({
8953
+ widthPt: pageSize.widthPt,
8954
+ heightPt: pageSize.heightPt,
8955
+ items
8956
+ });
8957
+ }
8958
+ }
8959
+ function convertSpreadsheetToLayout(doc, options) {
8960
+ const pages = [];
8961
+ for (const sheet of doc.sheets) convertSheetToPages(sheet, options.measurer, options.signal, pages);
8962
+ return {
8963
+ formatVersion: document_content_model.LAYOUT_FORMAT_VERSION,
8964
+ metadata: doc.metadata,
8965
+ pages,
8966
+ images: {}
8967
+ };
8968
+ }
8969
+ //#endregion
8546
8970
  //#region src/layout/reconstruct.ts
8547
8971
  const ZERO_MARGINS = {
8548
8972
  topPt: 0,
@@ -8911,6 +9335,17 @@ function odpToPdf(bytes, options) {
8911
9335
  onSubstitution: options?.onSubstitution
8912
9336
  });
8913
9337
  }
9338
+ function odsToPdf(bytes, options) {
9339
+ const content = readOdsContent((0, odf_js.decodePackage)(bytes));
9340
+ if (content.kind !== "spreadsheet") throw new Error("readOdsContent returned a non-spreadsheet ContentDocument");
9341
+ return writePdf(convertSpreadsheetToLayout(content, {
9342
+ measurer: createStandardFontMeasurer(),
9343
+ signal: options?.signal
9344
+ }), {
9345
+ signal: options?.signal,
9346
+ onSubstitution: options?.onSubstitution
9347
+ });
9348
+ }
8914
9349
  function pdfToDocx(bytes, options) {
8915
9350
  const content = reconstructWordprocessing(readPdf(bytes, {
8916
9351
  signal: options?.signal,
@@ -8976,6 +9411,10 @@ const SUPPORTED_CONVERSIONS = [
8976
9411
  source: "odp",
8977
9412
  target: "pdf"
8978
9413
  },
9414
+ {
9415
+ source: "ods",
9416
+ target: "pdf"
9417
+ },
8979
9418
  {
8980
9419
  source: "pdf",
8981
9420
  target: "docx"
@@ -9068,6 +9507,19 @@ function createLocalDocumentConverter() {
9068
9507
  diagnostics
9069
9508
  });
9070
9509
  }
9510
+ if (source.format === "ods" && targetFormat === "pdf") {
9511
+ const bytes = odsToPdf(source.bytes, {
9512
+ signal: options.signal,
9513
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
9514
+ });
9515
+ return Promise.resolve({
9516
+ document: {
9517
+ format: "pdf",
9518
+ bytes
9519
+ },
9520
+ diagnostics
9521
+ });
9522
+ }
9071
9523
  if (source.format === "pdf" && targetFormat === "docx") {
9072
9524
  const bytes = pdfToDocx(source.bytes, {
9073
9525
  signal: options.signal,
@@ -9180,6 +9632,12 @@ Object.defineProperty(exports, "ContentBlockSchema", {
9180
9632
  return document_content_model.ContentBlockSchema;
9181
9633
  }
9182
9634
  });
9635
+ Object.defineProperty(exports, "ContentCellValueSchema", {
9636
+ enumerable: true,
9637
+ get: function() {
9638
+ return document_content_model.ContentCellValueSchema;
9639
+ }
9640
+ });
9183
9641
  exports.ContentDocumentSchema = ContentDocumentSchema;
9184
9642
  Object.defineProperty(exports, "ContentImageBlockSchema", {
9185
9643
  enumerable: true,
@@ -9217,6 +9675,48 @@ Object.defineProperty(exports, "ContentShapeSchema", {
9217
9675
  return document_content_model.ContentShapeSchema;
9218
9676
  }
9219
9677
  });
9678
+ Object.defineProperty(exports, "ContentSheetCellSchema", {
9679
+ enumerable: true,
9680
+ get: function() {
9681
+ return document_content_model.ContentSheetCellSchema;
9682
+ }
9683
+ });
9684
+ Object.defineProperty(exports, "ContentSheetColumnSchema", {
9685
+ enumerable: true,
9686
+ get: function() {
9687
+ return document_content_model.ContentSheetColumnSchema;
9688
+ }
9689
+ });
9690
+ Object.defineProperty(exports, "ContentSheetPrintRangeSchema", {
9691
+ enumerable: true,
9692
+ get: function() {
9693
+ return document_content_model.ContentSheetPrintRangeSchema;
9694
+ }
9695
+ });
9696
+ Object.defineProperty(exports, "ContentSheetPrintSettingsSchema", {
9697
+ enumerable: true,
9698
+ get: function() {
9699
+ return document_content_model.ContentSheetPrintSettingsSchema;
9700
+ }
9701
+ });
9702
+ Object.defineProperty(exports, "ContentSheetRepeatRangeSchema", {
9703
+ enumerable: true,
9704
+ get: function() {
9705
+ return document_content_model.ContentSheetRepeatRangeSchema;
9706
+ }
9707
+ });
9708
+ Object.defineProperty(exports, "ContentSheetRowSchema", {
9709
+ enumerable: true,
9710
+ get: function() {
9711
+ return document_content_model.ContentSheetRowSchema;
9712
+ }
9713
+ });
9714
+ Object.defineProperty(exports, "ContentSheetSchema", {
9715
+ enumerable: true,
9716
+ get: function() {
9717
+ return document_content_model.ContentSheetSchema;
9718
+ }
9719
+ });
9220
9720
  Object.defineProperty(exports, "ContentSlideSchema", {
9221
9721
  enumerable: true,
9222
9722
  get: function() {
@@ -9420,6 +9920,7 @@ Object.defineProperty(exports, "compactPackageCodec", {
9420
9920
  }
9421
9921
  });
9422
9922
  exports.convertPresentationToLayout = convertPresentationToLayout;
9923
+ exports.convertSpreadsheetToLayout = convertSpreadsheetToLayout;
9423
9924
  exports.convertWordprocessingToLayout = convertWordprocessingToLayout;
9424
9925
  exports.createDocx = createDocx;
9425
9926
  exports.createLocalDocumentConverter = createLocalDocumentConverter;
@@ -9492,6 +9993,7 @@ Object.defineProperty(exports, "isXmlNode", {
9492
9993
  });
9493
9994
  exports.odpPdfCodec = odpPdfCodec;
9494
9995
  exports.odpToPdf = odpToPdf;
9996
+ exports.odsToPdf = odsToPdf;
9495
9997
  exports.odtPdfCodec = odtPdfCodec;
9496
9998
  exports.odtToPdf = odtToPdf;
9497
9999
  exports.openDocx = openDocx;
@@ -9525,6 +10027,7 @@ exports.pptxPdfCodec = pptxPdfCodec;
9525
10027
  exports.pptxToPdf = pptxToPdf;
9526
10028
  exports.readDocxContent = readDocxContent;
9527
10029
  exports.readOdpContent = readOdpContent;
10030
+ exports.readOdsContent = readOdsContent;
9528
10031
  exports.readOdtContent = readOdtContent;
9529
10032
  exports.readPdf = readPdf;
9530
10033
  exports.readPptxContent = readPptxContent;