@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.
- package/README.md +2 -2
- package/README_zh.md +2 -2
- package/dist/browser/modules/excel/cell.js +11 -7
- package/dist/browser/modules/excel/column.js +7 -6
- package/dist/browser/modules/excel/row.js +5 -1
- package/dist/browser/modules/excel/stream/worksheet-reader.js +3 -2
- package/dist/browser/modules/excel/utils/cell-format.js +64 -2
- package/dist/browser/modules/pdf/excel-bridge.d.ts +4 -3
- package/dist/browser/modules/pdf/excel-bridge.js +18 -5
- package/dist/browser/modules/pdf/index.d.ts +3 -3
- package/dist/browser/modules/pdf/index.js +3 -3
- package/dist/browser/modules/pdf/pdf.d.ts +7 -6
- package/dist/browser/modules/pdf/pdf.js +7 -6
- package/dist/browser/modules/pdf/reader/pdf-reader.d.ts +8 -7
- package/dist/browser/modules/pdf/reader/pdf-reader.js +81 -74
- package/dist/browser/modules/pdf/render/constants.d.ts +30 -0
- package/dist/browser/modules/pdf/render/constants.js +30 -0
- package/dist/browser/modules/pdf/render/layout-engine.d.ts +2 -1
- package/dist/browser/modules/pdf/render/layout-engine.js +359 -156
- package/dist/browser/modules/pdf/render/page-renderer.d.ts +2 -2
- package/dist/browser/modules/pdf/render/page-renderer.js +245 -107
- package/dist/browser/modules/pdf/render/pdf-exporter.d.ts +3 -2
- package/dist/browser/modules/pdf/render/pdf-exporter.js +145 -105
- package/dist/browser/modules/pdf/render/style-converter.js +27 -26
- package/dist/browser/modules/pdf/types.d.ts +8 -0
- package/dist/browser/utils/utils.base.d.ts +5 -0
- package/dist/browser/utils/utils.base.js +10 -0
- package/dist/cjs/modules/excel/cell.js +11 -7
- package/dist/cjs/modules/excel/column.js +7 -6
- package/dist/cjs/modules/excel/row.js +5 -1
- package/dist/cjs/modules/excel/stream/worksheet-reader.js +3 -2
- package/dist/cjs/modules/excel/utils/cell-format.js +64 -2
- package/dist/cjs/modules/pdf/excel-bridge.js +18 -5
- package/dist/cjs/modules/pdf/index.js +3 -3
- package/dist/cjs/modules/pdf/pdf.js +7 -6
- package/dist/cjs/modules/pdf/reader/pdf-reader.js +81 -74
- package/dist/cjs/modules/pdf/render/constants.js +33 -0
- package/dist/cjs/modules/pdf/render/layout-engine.js +359 -156
- package/dist/cjs/modules/pdf/render/page-renderer.js +245 -107
- package/dist/cjs/modules/pdf/render/pdf-exporter.js +145 -105
- package/dist/cjs/modules/pdf/render/style-converter.js +27 -26
- package/dist/cjs/utils/utils.base.js +11 -0
- package/dist/esm/modules/excel/cell.js +11 -7
- package/dist/esm/modules/excel/column.js +7 -6
- package/dist/esm/modules/excel/row.js +5 -1
- package/dist/esm/modules/excel/stream/worksheet-reader.js +3 -2
- package/dist/esm/modules/excel/utils/cell-format.js +64 -2
- package/dist/esm/modules/pdf/excel-bridge.js +18 -5
- package/dist/esm/modules/pdf/index.js +3 -3
- package/dist/esm/modules/pdf/pdf.js +7 -6
- package/dist/esm/modules/pdf/reader/pdf-reader.js +81 -74
- package/dist/esm/modules/pdf/render/constants.js +30 -0
- package/dist/esm/modules/pdf/render/layout-engine.js +359 -156
- package/dist/esm/modules/pdf/render/page-renderer.js +245 -107
- package/dist/esm/modules/pdf/render/pdf-exporter.js +145 -105
- package/dist/esm/modules/pdf/render/style-converter.js +27 -26
- package/dist/esm/utils/utils.base.js +10 -0
- package/dist/iife/excelts.iife.js +1022 -677
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +48 -48
- package/dist/types/modules/pdf/excel-bridge.d.ts +4 -3
- package/dist/types/modules/pdf/index.d.ts +3 -3
- package/dist/types/modules/pdf/pdf.d.ts +7 -6
- package/dist/types/modules/pdf/reader/pdf-reader.d.ts +8 -7
- package/dist/types/modules/pdf/render/constants.d.ts +30 -0
- package/dist/types/modules/pdf/render/layout-engine.d.ts +2 -1
- package/dist/types/modules/pdf/render/page-renderer.d.ts +2 -2
- package/dist/types/modules/pdf/render/pdf-exporter.d.ts +3 -2
- package/dist/types/modules/pdf/types.d.ts +8 -0
- package/dist/types/utils/utils.base.d.ts +5 -0
- 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
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
85
|
-
|
|
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
|
|
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
|
|
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>;
|