@cj-tech-master/excelts 8.1.2 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +2 -2
  2. package/README_zh.md +2 -2
  3. package/dist/browser/modules/excel/cell.js +11 -7
  4. package/dist/browser/modules/excel/column.js +7 -6
  5. package/dist/browser/modules/excel/row.js +5 -1
  6. package/dist/browser/modules/excel/stream/worksheet-reader.js +3 -2
  7. package/dist/browser/modules/excel/utils/cell-format.js +64 -2
  8. package/dist/browser/modules/pdf/excel-bridge.d.ts +4 -3
  9. package/dist/browser/modules/pdf/excel-bridge.js +18 -5
  10. package/dist/browser/modules/pdf/index.d.ts +3 -3
  11. package/dist/browser/modules/pdf/index.js +3 -3
  12. package/dist/browser/modules/pdf/pdf.d.ts +7 -6
  13. package/dist/browser/modules/pdf/pdf.js +7 -6
  14. package/dist/browser/modules/pdf/reader/pdf-reader.d.ts +8 -7
  15. package/dist/browser/modules/pdf/reader/pdf-reader.js +81 -74
  16. package/dist/browser/modules/pdf/render/constants.d.ts +30 -0
  17. package/dist/browser/modules/pdf/render/constants.js +30 -0
  18. package/dist/browser/modules/pdf/render/layout-engine.d.ts +2 -1
  19. package/dist/browser/modules/pdf/render/layout-engine.js +359 -156
  20. package/dist/browser/modules/pdf/render/page-renderer.d.ts +2 -2
  21. package/dist/browser/modules/pdf/render/page-renderer.js +245 -107
  22. package/dist/browser/modules/pdf/render/pdf-exporter.d.ts +3 -2
  23. package/dist/browser/modules/pdf/render/pdf-exporter.js +145 -105
  24. package/dist/browser/modules/pdf/render/style-converter.js +27 -26
  25. package/dist/browser/modules/pdf/types.d.ts +8 -0
  26. package/dist/browser/utils/utils.base.d.ts +5 -0
  27. package/dist/browser/utils/utils.base.js +10 -0
  28. package/dist/cjs/modules/excel/cell.js +11 -7
  29. package/dist/cjs/modules/excel/column.js +7 -6
  30. package/dist/cjs/modules/excel/row.js +5 -1
  31. package/dist/cjs/modules/excel/stream/worksheet-reader.js +3 -2
  32. package/dist/cjs/modules/excel/utils/cell-format.js +64 -2
  33. package/dist/cjs/modules/pdf/excel-bridge.js +18 -5
  34. package/dist/cjs/modules/pdf/index.js +3 -3
  35. package/dist/cjs/modules/pdf/pdf.js +7 -6
  36. package/dist/cjs/modules/pdf/reader/pdf-reader.js +81 -74
  37. package/dist/cjs/modules/pdf/render/constants.js +33 -0
  38. package/dist/cjs/modules/pdf/render/layout-engine.js +359 -156
  39. package/dist/cjs/modules/pdf/render/page-renderer.js +245 -107
  40. package/dist/cjs/modules/pdf/render/pdf-exporter.js +145 -105
  41. package/dist/cjs/modules/pdf/render/style-converter.js +27 -26
  42. package/dist/cjs/utils/utils.base.js +11 -0
  43. package/dist/esm/modules/excel/cell.js +11 -7
  44. package/dist/esm/modules/excel/column.js +7 -6
  45. package/dist/esm/modules/excel/row.js +5 -1
  46. package/dist/esm/modules/excel/stream/worksheet-reader.js +3 -2
  47. package/dist/esm/modules/excel/utils/cell-format.js +64 -2
  48. package/dist/esm/modules/pdf/excel-bridge.js +18 -5
  49. package/dist/esm/modules/pdf/index.js +3 -3
  50. package/dist/esm/modules/pdf/pdf.js +7 -6
  51. package/dist/esm/modules/pdf/reader/pdf-reader.js +81 -74
  52. package/dist/esm/modules/pdf/render/constants.js +30 -0
  53. package/dist/esm/modules/pdf/render/layout-engine.js +359 -156
  54. package/dist/esm/modules/pdf/render/page-renderer.js +245 -107
  55. package/dist/esm/modules/pdf/render/pdf-exporter.js +145 -105
  56. package/dist/esm/modules/pdf/render/style-converter.js +27 -26
  57. package/dist/esm/utils/utils.base.js +10 -0
  58. package/dist/iife/excelts.iife.js +1022 -677
  59. package/dist/iife/excelts.iife.js.map +1 -1
  60. package/dist/iife/excelts.iife.min.js +48 -48
  61. package/dist/types/modules/pdf/excel-bridge.d.ts +4 -3
  62. package/dist/types/modules/pdf/index.d.ts +3 -3
  63. package/dist/types/modules/pdf/pdf.d.ts +7 -6
  64. package/dist/types/modules/pdf/reader/pdf-reader.d.ts +8 -7
  65. package/dist/types/modules/pdf/render/constants.d.ts +30 -0
  66. package/dist/types/modules/pdf/render/layout-engine.d.ts +2 -1
  67. package/dist/types/modules/pdf/render/page-renderer.d.ts +2 -2
  68. package/dist/types/modules/pdf/render/pdf-exporter.d.ts +3 -2
  69. package/dist/types/modules/pdf/types.d.ts +8 -0
  70. package/dist/types/utils/utils.base.d.ts +5 -0
  71. package/package.json +1 -1
package/README.md CHANGED
@@ -100,14 +100,14 @@ wb.getWorksheet(1).eachRow((row, n) => console.log(n, row.values));
100
100
 
101
101
  // PDF — generate from data, no Workbook needed
102
102
  import { pdf } from "@cj-tech-master/excelts/pdf";
103
- const pdfBytes = pdf([
103
+ const pdfBytes = await pdf([
104
104
  ["Product", "Revenue"],
105
105
  ["Widget", 1000]
106
106
  ]);
107
107
 
108
108
  // PDF — read text, images, and metadata from any PDF
109
109
  import { readPdf } from "@cj-tech-master/excelts/pdf";
110
- const result = readPdf(pdfBytes);
110
+ const result = await readPdf(pdfBytes);
111
111
  console.log(result.text); // extracted text
112
112
  console.log(result.metadata); // title, author, etc.
113
113
 
package/README_zh.md CHANGED
@@ -100,14 +100,14 @@ wb.getWorksheet(1).eachRow((row, n) => console.log(n, row.values));
100
100
 
101
101
  // PDF — 直接从数据生成,无需 Workbook
102
102
  import { pdf } from "@cj-tech-master/excelts/pdf";
103
- const pdfBytes = pdf([
103
+ const pdfBytes = await pdf([
104
104
  ["产品", "收入"],
105
105
  ["小工具", 1000]
106
106
  ]);
107
107
 
108
108
  // PDF — 读取任意 PDF 的文本、图片和元数据
109
109
  import { readPdf } from "@cj-tech-master/excelts/pdf";
110
- const result = readPdf(pdfBytes);
110
+ const result = await readPdf(pdfBytes);
111
111
  console.log(result.text); // 提取的文本
112
112
  console.log(result.metadata); // 标题、作者等
113
113
 
@@ -3,6 +3,7 @@ import { Enums } from "./enums.js";
3
3
  import { Note } from "./note.js";
4
4
  import { escapeHtml } from "./utils/under-dash.js";
5
5
  import { slideFormula } from "./utils/shared-formula.js";
6
+ import { copyStyle } from "./utils/copy-style.js";
6
7
  import { ExcelError, InvalidValueTypeError } from "./errors.js";
7
8
  // Returns true if the value is a non-empty object (has at least one own key),
8
9
  // or any truthy non-object value. Returns false for undefined, null, false, 0,
@@ -87,27 +88,27 @@ class Cell {
87
88
  const font = (rowStyle && hasOwnKeys(rowStyle.font) && rowStyle.font) ||
88
89
  (colStyle && hasOwnKeys(colStyle.font) && colStyle.font);
89
90
  if (font) {
90
- style.font = font;
91
+ style.font = structuredClone(font);
91
92
  }
92
93
  const alignment = (rowStyle && hasOwnKeys(rowStyle.alignment) && rowStyle.alignment) ||
93
94
  (colStyle && hasOwnKeys(colStyle.alignment) && colStyle.alignment);
94
95
  if (alignment) {
95
- style.alignment = alignment;
96
+ style.alignment = structuredClone(alignment);
96
97
  }
97
98
  const border = (rowStyle && hasOwnKeys(rowStyle.border) && rowStyle.border) ||
98
99
  (colStyle && hasOwnKeys(colStyle.border) && colStyle.border);
99
100
  if (border) {
100
- style.border = border;
101
+ style.border = structuredClone(border);
101
102
  }
102
103
  const fill = (rowStyle && hasOwnKeys(rowStyle.fill) && rowStyle.fill) ||
103
104
  (colStyle && hasOwnKeys(colStyle.fill) && colStyle.fill);
104
105
  if (fill) {
105
- style.fill = fill;
106
+ style.fill = structuredClone(fill);
106
107
  }
107
108
  const protection = (rowStyle && hasOwnKeys(rowStyle.protection) && rowStyle.protection) ||
108
109
  (colStyle && hasOwnKeys(colStyle.protection) && colStyle.protection);
109
110
  if (protection) {
110
- style.protection = protection;
111
+ style.protection = structuredClone(protection);
111
112
  }
112
113
  return style;
113
114
  }
@@ -151,7 +152,10 @@ class Cell {
151
152
  this._value.release();
152
153
  this._value = Value.create(Cell.Types.Merge, this, master);
153
154
  if (!ignoreStyle) {
154
- this.style = master.style;
155
+ // Deep-copy so each cell has an independent style object.
156
+ // Without this, all cells in the merge share the same reference,
157
+ // and setting a property (e.g. border) on any cell mutates all of them.
158
+ this.style = copyStyle(master.style) ?? {};
155
159
  }
156
160
  }
157
161
  unmerge() {
@@ -318,7 +322,7 @@ class Cell {
318
322
  }
319
323
  }
320
324
  if (value.style) {
321
- this.style = value.style;
325
+ this.style = copyStyle(value.style) ?? {};
322
326
  }
323
327
  else {
324
328
  this.style = {};
@@ -1,5 +1,6 @@
1
1
  import { colCache } from "./utils/col-cache.js";
2
2
  import { isEqual } from "./utils/under-dash.js";
3
+ import { copyStyle } from "./utils/copy-style.js";
3
4
  import { Enums } from "./enums.js";
4
5
  const DEFAULT_COLUMN_WIDTH = 9;
5
6
  /**
@@ -48,7 +49,7 @@ class Column {
48
49
  this.width = value.width !== undefined ? value.width : DEFAULT_COLUMN_WIDTH;
49
50
  this.outlineLevel = value.outlineLevel;
50
51
  if (value.style) {
51
- this.style = value.style;
52
+ this.style = copyStyle(value.style) ?? {};
52
53
  }
53
54
  else {
54
55
  this.style = {};
@@ -259,7 +260,7 @@ class Column {
259
260
  set font(value) {
260
261
  this.style.font = value;
261
262
  this.eachCell(cell => {
262
- cell.font = value;
263
+ cell.font = value ? structuredClone(value) : value;
263
264
  });
264
265
  }
265
266
  get alignment() {
@@ -268,7 +269,7 @@ class Column {
268
269
  set alignment(value) {
269
270
  this.style.alignment = value;
270
271
  this.eachCell(cell => {
271
- cell.alignment = value;
272
+ cell.alignment = value ? structuredClone(value) : value;
272
273
  });
273
274
  }
274
275
  get protection() {
@@ -277,7 +278,7 @@ class Column {
277
278
  set protection(value) {
278
279
  this.style.protection = value;
279
280
  this.eachCell(cell => {
280
- cell.protection = value;
281
+ cell.protection = value ? structuredClone(value) : value;
281
282
  });
282
283
  }
283
284
  get border() {
@@ -286,7 +287,7 @@ class Column {
286
287
  set border(value) {
287
288
  this.style.border = value;
288
289
  this.eachCell(cell => {
289
- cell.border = value;
290
+ cell.border = value ? structuredClone(value) : value;
290
291
  });
291
292
  }
292
293
  get fill() {
@@ -295,7 +296,7 @@ class Column {
295
296
  set fill(value) {
296
297
  this.style.fill = value;
297
298
  this.eachCell(cell => {
298
- cell.fill = value;
299
+ cell.fill = value ? structuredClone(value) : value;
299
300
  });
300
301
  }
301
302
  // =============================================================================
@@ -297,7 +297,11 @@ class Row {
297
297
  this.style[name] = value;
298
298
  this._cells.forEach(cell => {
299
299
  if (cell) {
300
- cell.style[name] = value;
300
+ // Clone object values so each cell gets an independent copy.
301
+ // Without this, mutating a sub-property (e.g. cell.border.top = ...)
302
+ // would leak to every other cell that received the same reference.
303
+ cell.style[name] =
304
+ typeof value === "object" && value !== null ? structuredClone(value) : value;
301
305
  }
302
306
  });
303
307
  }
@@ -7,6 +7,7 @@ import { EventEmitter } from "../../../utils/event-emitter.js";
7
7
  import { SaxParser } from "../../xml/sax.js";
8
8
  import { ExcelStreamStateError } from "../errors.js";
9
9
  import { isDateFmt, excelToDate, decodeOoxmlEscape } from "../../../utils/utils.browser.js";
10
+ import { copyStyle } from "../utils/copy-style.js";
10
11
  import { colCache } from "../utils/col-cache.js";
11
12
  import { Dimensions } from "../range.js";
12
13
  import { Row } from "../row.js";
@@ -178,7 +179,7 @@ class WorksheetReader extends EventEmitter {
178
179
  const styleId = parseInt(node.attributes.s, 10);
179
180
  const style = styles.getStyleModel(styleId);
180
181
  if (style) {
181
- row.style = style;
182
+ row.style = copyStyle(style) ?? {};
182
183
  }
183
184
  }
184
185
  }
@@ -279,7 +280,7 @@ class WorksheetReader extends EventEmitter {
279
280
  if (c.s !== undefined) {
280
281
  const style = styles.getStyleModel(c.s);
281
282
  if (style) {
282
- cell.style = style;
283
+ cell.style = copyStyle(style) ?? {};
283
284
  }
284
285
  }
285
286
  if (c.f) {
@@ -513,6 +513,35 @@ function formatNumberPattern(val, fmt) {
513
513
  const decimalPlaces = decFmt.replace(/[^0#?]/g, "").length;
514
514
  // Round the value
515
515
  const roundedVal = roundTo(scaledVal, decimalPlaces);
516
+ // When value is zero and the format has no required '0' digit placeholders,
517
+ // '?' placeholders become spaces and '#' placeholders produce nothing.
518
+ // This handles accounting format zero sections like "-"?? → "- " (dash + spaces).
519
+ if (roundedVal === 0 && !intFmt.includes("0") && !decFmt.includes("0")) {
520
+ let result = "";
521
+ for (const ch of intFmt) {
522
+ if (ch === "?") {
523
+ result += " ";
524
+ }
525
+ else if (ch !== "#" && ch !== ",") {
526
+ // Preserve literal characters (already unquoted at this point)
527
+ result += ch;
528
+ }
529
+ }
530
+ if (decimalPlaces > 0) {
531
+ // Only emit the decimal point if the decimal format has '?' or '0' placeholders.
532
+ // Pure '#' decimal digits produce nothing for zero values.
533
+ const hasDecContent = /[0?]/.test(decFmt);
534
+ if (hasDecContent) {
535
+ result += ".";
536
+ for (const ch of decFmt) {
537
+ if (ch === "?") {
538
+ result += " ";
539
+ }
540
+ }
541
+ }
542
+ }
543
+ return sign + result;
544
+ }
516
545
  // Split into integer and decimal parts
517
546
  const [intPart, decPart = ""] = roundedVal.toString().split(".");
518
547
  // Check if format has literal characters mixed with digit placeholders (like "0-0", "000-0000")
@@ -552,16 +581,49 @@ function formatNumberPattern(val, fmt) {
552
581
  if (intFmt.includes(",")) {
553
582
  formattedInt = commaify(intPart);
554
583
  }
555
- // Pad integer with leading zeros if needed
584
+ // Pad integer with leading zeros/spaces if needed
585
+ // '0' placeholder → pad with "0", '?' placeholder → pad with " "
556
586
  const minIntDigits = (intFmt.match(/0/g) ?? []).length;
587
+ const totalIntSlots = (intFmt.match(/[0?]/g) ?? []).length;
557
588
  if (formattedInt.length < minIntDigits) {
558
589
  formattedInt = "0".repeat(minIntDigits - formattedInt.length) + formattedInt;
559
590
  }
591
+ if (formattedInt.length < totalIntSlots) {
592
+ formattedInt = " ".repeat(totalIntSlots - formattedInt.length) + formattedInt;
593
+ }
594
+ // '#' integer placeholder: suppress "0" when there are no required '0' or '?' digits
595
+ // and the integer value is zero (e.g. "#" format with value 0 → empty)
596
+ if (formattedInt === "0" && minIntDigits === 0 && totalIntSlots === 0) {
597
+ formattedInt = "";
598
+ }
560
599
  }
561
600
  // Format decimal part
562
601
  let formattedDec = "";
563
602
  if (decimalPlaces > 0) {
564
- formattedDec = "." + (decPart + "0".repeat(decimalPlaces)).substring(0, decimalPlaces);
603
+ const rawDec = (decPart + "0".repeat(decimalPlaces)).substring(0, decimalPlaces);
604
+ // Process each decimal digit position according to its placeholder:
605
+ // '0' → always show digit, '?' → show digit or space, '#' → show digit or nothing (trim trailing)
606
+ const decChars = rawDec.split("");
607
+ // Walk from the end: '#' trailing zeros are removed, '?' trailing zeros become spaces
608
+ for (let i = decFmt.length - 1; i >= 0; i--) {
609
+ if (i >= decChars.length) {
610
+ continue;
611
+ }
612
+ if (decFmt[i] === "#" && decChars[i] === "0") {
613
+ decChars[i] = "";
614
+ }
615
+ else if (decFmt[i] === "?" && decChars[i] === "0") {
616
+ decChars[i] = " ";
617
+ }
618
+ else {
619
+ break; // stop at first non-zero or '0' placeholder
620
+ }
621
+ }
622
+ const decStr = decChars.join("");
623
+ // Only emit decimal point if there is content after it
624
+ if (decStr.length > 0) {
625
+ formattedDec = "." + decStr;
626
+ }
565
627
  }
566
628
  return sign + formattedInt + formattedDec;
567
629
  }
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * const workbook = new Workbook();
13
13
  * // ... build workbook ...
14
- * const pdf = excelToPdf(workbook);
14
+ * const pdf = await excelToPdf(workbook);
15
15
  * ```
16
16
  */
17
17
  import type { Workbook } from "../excel/workbook.js";
@@ -21,9 +21,10 @@ import { type PdfExportOptions } from "./types.js";
21
21
  *
22
22
  * This is a convenience function that converts the Workbook to the PDF module's
23
23
  * data model and then generates the PDF.
24
+ * Yields to the event loop between each output page during layout and rendering.
24
25
  *
25
26
  * @param workbook - An Excel Workbook instance
26
27
  * @param options - PDF export options
27
- * @returns PDF file as a Uint8Array
28
+ * @returns Promise of PDF file as a Uint8Array
28
29
  */
29
- export declare function excelToPdf(workbook: Workbook, options?: PdfExportOptions): Uint8Array;
30
+ export declare function excelToPdf(workbook: Workbook, options?: PdfExportOptions): Promise<Uint8Array>;
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * const workbook = new Workbook();
13
13
  * // ... build workbook ...
14
- * const pdf = excelToPdf(workbook);
14
+ * const pdf = await excelToPdf(workbook);
15
15
  * ```
16
16
  */
17
17
  import { ValueType } from "../excel/enums.js";
@@ -27,12 +27,13 @@ import { PdfCellType } from "./types.js";
27
27
  *
28
28
  * This is a convenience function that converts the Workbook to the PDF module's
29
29
  * data model and then generates the PDF.
30
+ * Yields to the event loop between each output page during layout and rendering.
30
31
  *
31
32
  * @param workbook - An Excel Workbook instance
32
33
  * @param options - PDF export options
33
- * @returns PDF file as a Uint8Array
34
+ * @returns Promise of PDF file as a Uint8Array
34
35
  */
35
- export function excelToPdf(workbook, options) {
36
+ export async function excelToPdf(workbook, options) {
36
37
  const pdfWorkbook = excelWorkbookToPdf(workbook);
37
38
  return exportPdf(pdfWorkbook, options);
38
39
  }
@@ -81,12 +82,24 @@ function convertSheet(ws, workbook) {
81
82
  continue;
82
83
  }
83
84
  const cells = new Map();
84
- row.eachCell({ includeEmpty: false }, cell => {
85
- cells.set(cell.col, convertCell(cell));
85
+ row.eachCell({ includeEmpty: true }, cell => {
86
+ const hasValue = cell.type !== ValueType.Null && cell.type !== ValueType.Merge;
87
+ const hasStyle = cell.style &&
88
+ ((cell.style.border &&
89
+ (cell.style.border.top ||
90
+ cell.style.border.right ||
91
+ cell.style.border.bottom ||
92
+ cell.style.border.left)) ||
93
+ cell.style.fill ||
94
+ cell.style.font);
95
+ if (hasValue || hasStyle) {
96
+ cells.set(cell.col, convertCell(cell));
97
+ }
86
98
  });
87
99
  rows.set(r, {
88
100
  hidden: row.hidden || undefined,
89
101
  height: row.height ?? undefined,
102
+ customHeight: row.customHeight || undefined,
90
103
  cells
91
104
  });
92
105
  }
@@ -7,7 +7,7 @@
7
7
  * ```typescript
8
8
  * import { pdf } from "excelts/pdf";
9
9
  *
10
- * const bytes = pdf([
10
+ * const bytes = await pdf([
11
11
  * ["Product", "Revenue"],
12
12
  * ["Widget", 1000],
13
13
  * ["Gadget", 2500]
@@ -22,14 +22,14 @@
22
22
  * const workbook = new Workbook();
23
23
  * const sheet = workbook.addWorksheet("Sales");
24
24
  * sheet.addRow(["Product", "Revenue"]);
25
- * const bytes = excelToPdf(workbook);
25
+ * const bytes = await excelToPdf(workbook);
26
26
  * ```
27
27
  *
28
28
  * @example Read PDF — extract text, images, and metadata:
29
29
  * ```typescript
30
30
  * import { readPdf } from "excelts/pdf";
31
31
  *
32
- * const result = readPdf(pdfBytes);
32
+ * const result = await readPdf(pdfBytes);
33
33
  * console.log(result.text); // All text
34
34
  * console.log(result.pages[0].text); // Page 1 text
35
35
  * console.log(result.pages[0].images); // Page 1 images
@@ -7,7 +7,7 @@
7
7
  * ```typescript
8
8
  * import { pdf } from "excelts/pdf";
9
9
  *
10
- * const bytes = pdf([
10
+ * const bytes = await pdf([
11
11
  * ["Product", "Revenue"],
12
12
  * ["Widget", 1000],
13
13
  * ["Gadget", 2500]
@@ -22,14 +22,14 @@
22
22
  * const workbook = new Workbook();
23
23
  * const sheet = workbook.addWorksheet("Sales");
24
24
  * sheet.addRow(["Product", "Revenue"]);
25
- * const bytes = excelToPdf(workbook);
25
+ * const bytes = await excelToPdf(workbook);
26
26
  * ```
27
27
  *
28
28
  * @example Read PDF — extract text, images, and metadata:
29
29
  * ```typescript
30
30
  * import { readPdf } from "excelts/pdf";
31
31
  *
32
- * const result = readPdf(pdfBytes);
32
+ * const result = await readPdf(pdfBytes);
33
33
  * console.log(result.text); // All text
34
34
  * console.log(result.pages[0].text); // Page 1 text
35
35
  * console.log(result.pages[0].images); // Page 1 images
@@ -8,7 +8,7 @@
8
8
  * ```typescript
9
9
  * import { pdf } from "@cj-tech-master/excelts/pdf";
10
10
  *
11
- * const bytes = pdf([
11
+ * const bytes = await pdf([
12
12
  * ["Product", "Revenue"],
13
13
  * ["Widget", 1000],
14
14
  * ["Gadget", 2500]
@@ -17,7 +17,7 @@
17
17
  *
18
18
  * @example With options:
19
19
  * ```typescript
20
- * const bytes = pdf([
20
+ * const bytes = await pdf([
21
21
  * ["Name", "Score"],
22
22
  * ["Alice", 95],
23
23
  * ["Bob", 87]
@@ -26,7 +26,7 @@
26
26
  *
27
27
  * @example Multiple sheets:
28
28
  * ```typescript
29
- * const bytes = pdf({
29
+ * const bytes = await pdf({
30
30
  * sheets: [
31
31
  * { name: "Sales", data: [["Product", "Revenue"], ["Widget", 1000]] },
32
32
  * { name: "Costs", data: [["Item", "Amount"], ["Rent", 500]] }
@@ -36,7 +36,7 @@
36
36
  *
37
37
  * @example With column widths and styles:
38
38
  * ```typescript
39
- * const bytes = pdf({
39
+ * const bytes = await pdf({
40
40
  * name: "Report",
41
41
  * columns: [{ width: 25 }, { width: 15 }],
42
42
  * data: [
@@ -113,9 +113,10 @@ export type PdfInput = PdfRow[] | PdfSheet | PdfBook;
113
113
  * Generate a PDF.
114
114
  *
115
115
  * Accepts anything from a plain 2D array to a multi-sheet workbook.
116
+ * Yields to the event loop between each output page during layout and rendering.
116
117
  *
117
118
  * @param input - 2D array, sheet object, or workbook object
118
119
  * @param options - PDF export options (page size, margins, etc.)
119
- * @returns PDF file as Uint8Array
120
+ * @returns Promise of PDF file as Uint8Array
120
121
  */
121
- export declare function pdf(input: PdfInput, options?: PdfExportOptions): Uint8Array;
122
+ export declare function pdf(input: PdfInput, options?: PdfExportOptions): Promise<Uint8Array>;
@@ -8,7 +8,7 @@
8
8
  * ```typescript
9
9
  * import { pdf } from "@cj-tech-master/excelts/pdf";
10
10
  *
11
- * const bytes = pdf([
11
+ * const bytes = await pdf([
12
12
  * ["Product", "Revenue"],
13
13
  * ["Widget", 1000],
14
14
  * ["Gadget", 2500]
@@ -17,7 +17,7 @@
17
17
  *
18
18
  * @example With options:
19
19
  * ```typescript
20
- * const bytes = pdf([
20
+ * const bytes = await pdf([
21
21
  * ["Name", "Score"],
22
22
  * ["Alice", 95],
23
23
  * ["Bob", 87]
@@ -26,7 +26,7 @@
26
26
  *
27
27
  * @example Multiple sheets:
28
28
  * ```typescript
29
- * const bytes = pdf({
29
+ * const bytes = await pdf({
30
30
  * sheets: [
31
31
  * { name: "Sales", data: [["Product", "Revenue"], ["Widget", 1000]] },
32
32
  * { name: "Costs", data: [["Item", "Amount"], ["Rent", 500]] }
@@ -36,7 +36,7 @@
36
36
  *
37
37
  * @example With column widths and styles:
38
38
  * ```typescript
39
- * const bytes = pdf({
39
+ * const bytes = await pdf({
40
40
  * name: "Report",
41
41
  * columns: [{ width: 25 }, { width: 15 }],
42
42
  * data: [
@@ -55,12 +55,13 @@ import { exportPdf } from "./render/pdf-exporter.js";
55
55
  * Generate a PDF.
56
56
  *
57
57
  * Accepts anything from a plain 2D array to a multi-sheet workbook.
58
+ * Yields to the event loop between each output page during layout and rendering.
58
59
  *
59
60
  * @param input - 2D array, sheet object, or workbook object
60
61
  * @param options - PDF export options (page size, margins, etc.)
61
- * @returns PDF file as Uint8Array
62
+ * @returns Promise of PDF file as Uint8Array
62
63
  */
63
- export function pdf(input, options) {
64
+ export async function pdf(input, options) {
64
65
  const workbook = normalizeInput(input);
65
66
  return exportPdf(workbook, options);
66
67
  }
@@ -16,18 +16,18 @@
16
16
  * - Cross-reference tables and streams (PDF 1.5+)
17
17
  * - Incremental updates and xref recovery
18
18
  *
19
- * @example Basic text extraction:
19
+ * @example Text extraction:
20
20
  * ```typescript
21
21
  * import { readPdf } from "excelts/pdf";
22
22
  *
23
- * const pdf = readPdf(pdfBytes);
23
+ * const pdf = await readPdf(pdfBytes);
24
24
  * console.log(pdf.text); // All text from all pages
25
25
  * console.log(pdf.pages[0].text); // Text from page 1
26
26
  * ```
27
27
  *
28
28
  * @example Image extraction:
29
29
  * ```typescript
30
- * const pdf = readPdf(pdfBytes);
30
+ * const pdf = await readPdf(pdfBytes);
31
31
  * for (const image of pdf.pages[0].images) {
32
32
  * console.log(image.format, image.width, image.height);
33
33
  * fs.writeFileSync(`image.${image.format}`, image.data);
@@ -36,7 +36,7 @@
36
36
  *
37
37
  * @example Metadata:
38
38
  * ```typescript
39
- * const pdf = readPdf(pdfBytes);
39
+ * const pdf = await readPdf(pdfBytes);
40
40
  * console.log(pdf.metadata.title);
41
41
  * console.log(pdf.metadata.author);
42
42
  * console.log(pdf.metadata.pageCount);
@@ -44,7 +44,7 @@
44
44
  *
45
45
  * @example Encrypted PDF:
46
46
  * ```typescript
47
- * const pdf = readPdf(pdfBytes, { password: "secret" });
47
+ * const pdf = await readPdf(pdfBytes, { password: "secret" });
48
48
  * ```
49
49
  */
50
50
  import type { TextLine } from "./text-reconstruction.js";
@@ -133,11 +133,12 @@ export interface ReadPdfResult {
133
133
  }
134
134
  /**
135
135
  * Read a PDF file and extract text, images, and metadata.
136
+ * Yields to the event loop between pages to avoid blocking.
136
137
  *
137
138
  * @param data - Raw PDF file bytes
138
139
  * @param options - Extraction options
139
- * @returns Extracted content
140
+ * @returns Promise of extracted content
140
141
  * @throws {PdfStructureError} If the PDF structure is invalid
141
142
  * @throws {PdfError} If decryption fails (wrong password)
142
143
  */
143
- export declare function readPdf(data: Uint8Array, options?: ReadPdfOptions): ReadPdfResult;
144
+ export declare function readPdf(data: Uint8Array, options?: ReadPdfOptions): Promise<ReadPdfResult>;