@cj-tech-master/excelts 6.1.3 → 6.2.0-canary.20260328172614.9d0f2b2
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 +124 -8
- package/README_zh.md +124 -8
- package/dist/browser/index.browser.d.ts +6 -5
- package/dist/browser/index.browser.js +8 -5
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/modules/archive/unzip/zip-extract-core.js +22 -0
- package/dist/browser/modules/archive/zip/zip-entry-options.d.ts +9 -9
- package/dist/browser/modules/archive/zip-spec/zip-parser-core.js +17 -5
- package/dist/browser/modules/csv/format/formatter.js +6 -1
- package/dist/browser/modules/csv/index.d.ts +2 -2
- package/dist/browser/modules/csv/index.js +3 -3
- package/dist/browser/modules/csv/parse/sync.js +6 -1
- package/dist/browser/modules/csv/worker/worker-script.generated.d.ts +1 -1
- package/dist/browser/modules/csv/worker/worker-script.generated.js +1 -1
- package/dist/browser/modules/excel/errors.d.ts +2 -2
- package/dist/browser/modules/excel/stream/workbook-reader.browser.d.ts +12 -0
- package/dist/browser/modules/excel/stream/workbook-reader.browser.js +16 -2
- package/dist/browser/modules/excel/stream/workbook-reader.js +18 -0
- package/dist/browser/modules/excel/stream/worksheet-writer.js +5 -24
- package/dist/browser/modules/excel/utils/cell-format.d.ts +17 -0
- package/dist/browser/modules/excel/utils/cell-format.js +38 -0
- package/dist/browser/modules/excel/utils/font-data.d.ts +90 -0
- package/dist/browser/modules/excel/utils/font-data.js +719 -0
- package/dist/browser/modules/excel/utils/sheet-protection.d.ts +26 -0
- package/dist/browser/modules/excel/utils/sheet-protection.js +35 -0
- package/dist/browser/modules/excel/utils/text-metrics.d.ts +167 -0
- package/dist/browser/modules/excel/utils/text-metrics.js +556 -0
- package/dist/browser/modules/excel/workbook.browser.js +3 -1
- package/dist/browser/modules/excel/worksheet.d.ts +34 -0
- package/dist/browser/modules/excel/worksheet.js +197 -60
- package/dist/browser/modules/excel/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.d.ts +1 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.d.ts +1 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/cf-ext/databar-ext-xform.d.ts +1 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.d.ts +1 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +66 -33
- package/dist/browser/modules/pdf/core/encryption.d.ts +77 -0
- package/dist/browser/modules/pdf/core/encryption.js +310 -0
- package/dist/browser/modules/pdf/core/pdf-object.d.ts +65 -0
- package/dist/browser/modules/pdf/core/pdf-object.js +180 -0
- package/dist/browser/modules/pdf/core/pdf-stream.d.ts +195 -0
- package/dist/browser/modules/pdf/core/pdf-stream.js +456 -0
- package/dist/browser/modules/pdf/core/pdf-writer.d.ts +84 -0
- package/dist/browser/modules/pdf/core/pdf-writer.js +452 -0
- package/dist/browser/modules/pdf/errors.d.ts +33 -0
- package/dist/browser/modules/pdf/errors.js +46 -0
- package/dist/browser/modules/pdf/excel-bridge.d.ts +29 -0
- package/dist/browser/modules/pdf/excel-bridge.js +423 -0
- package/dist/browser/modules/pdf/font/font-embedder.d.ts +49 -0
- package/dist/browser/modules/pdf/font/font-embedder.js +559 -0
- package/dist/browser/modules/pdf/font/font-manager.d.ts +119 -0
- package/dist/browser/modules/pdf/font/font-manager.js +357 -0
- package/dist/browser/modules/pdf/font/metrics.d.ts +59 -0
- package/dist/browser/modules/pdf/font/metrics.js +244 -0
- package/dist/browser/modules/pdf/font/ttf-parser.d.ts +73 -0
- package/dist/browser/modules/pdf/font/ttf-parser.js +531 -0
- package/dist/browser/modules/pdf/index.d.ts +37 -0
- package/dist/browser/modules/pdf/index.js +41 -0
- package/dist/browser/modules/pdf/pdf.d.ts +121 -0
- package/dist/browser/modules/pdf/pdf.js +255 -0
- package/dist/browser/modules/pdf/render/layout-engine.d.ts +25 -0
- package/dist/browser/modules/pdf/render/layout-engine.js +649 -0
- package/dist/browser/modules/pdf/render/page-renderer.d.ts +42 -0
- package/dist/browser/modules/pdf/render/page-renderer.js +637 -0
- package/dist/browser/modules/pdf/render/pdf-exporter.d.ts +19 -0
- package/dist/browser/modules/pdf/render/pdf-exporter.js +484 -0
- package/dist/browser/modules/pdf/render/png-decoder.d.ts +26 -0
- package/dist/browser/modules/pdf/render/png-decoder.js +295 -0
- package/dist/browser/modules/pdf/render/style-converter.d.ts +67 -0
- package/dist/browser/modules/pdf/render/style-converter.js +308 -0
- package/dist/browser/modules/pdf/types.d.ts +510 -0
- package/dist/browser/modules/pdf/types.js +36 -0
- package/dist/cjs/index.js +14 -2
- package/dist/cjs/modules/archive/unzip/zip-extract-core.js +22 -0
- package/dist/cjs/modules/archive/zip-spec/zip-parser-core.js +17 -5
- package/dist/cjs/modules/csv/format/formatter.js +6 -1
- package/dist/cjs/modules/csv/index.js +14 -14
- package/dist/cjs/modules/csv/parse/sync.js +6 -1
- package/dist/cjs/modules/csv/worker/worker-script.generated.js +1 -1
- package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +16 -2
- package/dist/cjs/modules/excel/stream/workbook-reader.js +18 -0
- package/dist/cjs/modules/excel/stream/worksheet-writer.js +5 -24
- package/dist/cjs/modules/excel/utils/cell-format.js +39 -0
- package/dist/cjs/modules/excel/utils/font-data.js +729 -0
- package/dist/cjs/modules/excel/utils/sheet-protection.js +38 -0
- package/dist/cjs/modules/excel/utils/text-metrics.js +574 -0
- package/dist/cjs/modules/excel/workbook.browser.js +3 -1
- package/dist/cjs/modules/excel/worksheet.js +196 -59
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +66 -33
- package/dist/cjs/modules/pdf/core/encryption.js +316 -0
- package/dist/cjs/modules/pdf/core/pdf-object.js +192 -0
- package/dist/cjs/modules/pdf/core/pdf-stream.js +460 -0
- package/dist/cjs/modules/pdf/core/pdf-writer.js +456 -0
- package/dist/cjs/modules/pdf/errors.js +54 -0
- package/dist/cjs/modules/pdf/excel-bridge.js +426 -0
- package/dist/cjs/modules/pdf/font/font-embedder.js +562 -0
- package/dist/cjs/modules/pdf/font/font-manager.js +362 -0
- package/dist/cjs/modules/pdf/font/metrics.js +253 -0
- package/dist/cjs/modules/pdf/font/ttf-parser.js +534 -0
- package/dist/cjs/modules/pdf/index.js +52 -0
- package/dist/cjs/modules/pdf/pdf.js +258 -0
- package/dist/cjs/modules/pdf/render/layout-engine.js +653 -0
- package/dist/cjs/modules/pdf/render/page-renderer.js +644 -0
- package/dist/cjs/modules/pdf/render/pdf-exporter.js +487 -0
- package/dist/cjs/modules/pdf/render/png-decoder.js +298 -0
- package/dist/cjs/modules/pdf/render/style-converter.js +319 -0
- package/dist/cjs/modules/pdf/types.js +39 -0
- package/dist/esm/index.browser.js +8 -5
- package/dist/esm/index.js +4 -0
- package/dist/esm/modules/archive/unzip/zip-extract-core.js +22 -0
- package/dist/esm/modules/archive/zip-spec/zip-parser-core.js +17 -5
- package/dist/esm/modules/csv/format/formatter.js +6 -1
- package/dist/esm/modules/csv/index.js +3 -3
- package/dist/esm/modules/csv/parse/sync.js +6 -1
- package/dist/esm/modules/csv/worker/worker-script.generated.js +1 -1
- package/dist/esm/modules/excel/stream/workbook-reader.browser.js +16 -2
- package/dist/esm/modules/excel/stream/workbook-reader.js +18 -0
- package/dist/esm/modules/excel/stream/worksheet-writer.js +5 -24
- package/dist/esm/modules/excel/utils/cell-format.js +38 -0
- package/dist/esm/modules/excel/utils/font-data.js +719 -0
- package/dist/esm/modules/excel/utils/sheet-protection.js +35 -0
- package/dist/esm/modules/excel/utils/text-metrics.js +556 -0
- package/dist/esm/modules/excel/workbook.browser.js +3 -1
- package/dist/esm/modules/excel/worksheet.js +197 -60
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +66 -33
- package/dist/esm/modules/pdf/core/encryption.js +310 -0
- package/dist/esm/modules/pdf/core/pdf-object.js +180 -0
- package/dist/esm/modules/pdf/core/pdf-stream.js +456 -0
- package/dist/esm/modules/pdf/core/pdf-writer.js +452 -0
- package/dist/esm/modules/pdf/errors.js +46 -0
- package/dist/esm/modules/pdf/excel-bridge.js +423 -0
- package/dist/esm/modules/pdf/font/font-embedder.js +559 -0
- package/dist/esm/modules/pdf/font/font-manager.js +357 -0
- package/dist/esm/modules/pdf/font/metrics.js +244 -0
- package/dist/esm/modules/pdf/font/ttf-parser.js +531 -0
- package/dist/esm/modules/pdf/index.js +41 -0
- package/dist/esm/modules/pdf/pdf.js +255 -0
- package/dist/esm/modules/pdf/render/layout-engine.js +649 -0
- package/dist/esm/modules/pdf/render/page-renderer.js +637 -0
- package/dist/esm/modules/pdf/render/pdf-exporter.js +484 -0
- package/dist/esm/modules/pdf/render/png-decoder.js +295 -0
- package/dist/esm/modules/pdf/render/style-converter.js +308 -0
- package/dist/esm/modules/pdf/types.js +36 -0
- package/dist/iife/excelts.iife.js +12754 -2803
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +56 -34
- package/dist/types/index.browser.d.ts +6 -5
- package/dist/types/index.d.ts +2 -0
- package/dist/types/modules/archive/zip/zip-entry-options.d.ts +9 -9
- package/dist/types/modules/csv/index.d.ts +2 -2
- package/dist/types/modules/csv/worker/worker-script.generated.d.ts +1 -1
- package/dist/types/modules/excel/errors.d.ts +2 -2
- package/dist/types/modules/excel/stream/workbook-reader.browser.d.ts +12 -0
- package/dist/types/modules/excel/utils/cell-format.d.ts +17 -0
- package/dist/types/modules/excel/utils/font-data.d.ts +90 -0
- package/dist/types/modules/excel/utils/sheet-protection.d.ts +26 -0
- package/dist/types/modules/excel/utils/text-metrics.d.ts +167 -0
- package/dist/types/modules/excel/worksheet.d.ts +34 -0
- package/dist/types/modules/excel/xlsx/xform/sheet/cf-ext/conditional-formatting-ext-xform.d.ts +1 -1
- package/dist/types/modules/excel/xlsx/xform/sheet/cf-ext/conditional-formattings-ext-xform.d.ts +1 -1
- package/dist/types/modules/excel/xlsx/xform/sheet/cf-ext/databar-ext-xform.d.ts +1 -1
- package/dist/types/modules/excel/xlsx/xform/sheet/cf-ext/icon-set-ext-xform.d.ts +1 -1
- package/dist/types/modules/pdf/core/encryption.d.ts +77 -0
- package/dist/types/modules/pdf/core/pdf-object.d.ts +65 -0
- package/dist/types/modules/pdf/core/pdf-stream.d.ts +195 -0
- package/dist/types/modules/pdf/core/pdf-writer.d.ts +84 -0
- package/dist/types/modules/pdf/errors.d.ts +33 -0
- package/dist/types/modules/pdf/excel-bridge.d.ts +29 -0
- package/dist/types/modules/pdf/font/font-embedder.d.ts +49 -0
- package/dist/types/modules/pdf/font/font-manager.d.ts +119 -0
- package/dist/types/modules/pdf/font/metrics.d.ts +59 -0
- package/dist/types/modules/pdf/font/ttf-parser.d.ts +73 -0
- package/dist/types/modules/pdf/index.d.ts +37 -0
- package/dist/types/modules/pdf/pdf.d.ts +121 -0
- package/dist/types/modules/pdf/render/layout-engine.d.ts +25 -0
- package/dist/types/modules/pdf/render/page-renderer.d.ts +42 -0
- package/dist/types/modules/pdf/render/pdf-exporter.d.ts +19 -0
- package/dist/types/modules/pdf/render/png-decoder.d.ts +26 -0
- package/dist/types/modules/pdf/render/style-converter.d.ts +67 -0
- package/dist/types/modules/pdf/types.d.ts +510 -0
- package/package.json +17 -14
package/README.md
CHANGED
|
@@ -6,15 +6,12 @@ Modern TypeScript Excel Workbook Manager - Read, manipulate and write spreadshee
|
|
|
6
6
|
|
|
7
7
|
## About This Project
|
|
8
8
|
|
|
9
|
-
ExcelTS is a
|
|
9
|
+
ExcelTS is a zero-dependency TypeScript toolkit for spreadsheets and documents:
|
|
10
10
|
|
|
11
|
-
- 🚀 **Zero Runtime Dependencies**
|
|
12
|
-
-
|
|
13
|
-
- ✅ **
|
|
14
|
-
- ✅ **
|
|
15
|
-
- ✅ **Enhanced Testing** - Migrated to Vitest with browser testing support
|
|
16
|
-
- ✅ **ESM First** - Native ES Module support with CommonJS compatibility
|
|
17
|
-
- ✅ **Named Exports** - All exports are named for better tree-shaking
|
|
11
|
+
- 🚀 **Zero Runtime Dependencies** — Pure TypeScript, no external packages
|
|
12
|
+
- 📦 **Five Modules** — Excel (XLSX/JSON), PDF (standalone engine + Excel bridge), CSV (RFC 4180), Archive (ZIP/TAR), Stream (cross-platform)
|
|
13
|
+
- ✅ **Cross-Platform** — Node.js 22+, Bun, Chrome 89+, Firefox 102+, Safari 14.1+
|
|
14
|
+
- ✅ **ESM First** — Native ES Modules with CommonJS compatibility and full tree-shaking
|
|
18
15
|
|
|
19
16
|
## Translations
|
|
20
17
|
|
|
@@ -103,6 +100,16 @@ cell.fill = {
|
|
|
103
100
|
- Hyperlinks
|
|
104
101
|
- Pivot tables
|
|
105
102
|
|
|
103
|
+
- **PDF Export**
|
|
104
|
+
- Full-featured, zero-dependency PDF engine (standalone or with Excel)
|
|
105
|
+
- Full cell styling (fonts, colors, borders, fills, alignment)
|
|
106
|
+
- Automatic pagination with repeat header rows
|
|
107
|
+
- TrueType font embedding for Unicode/CJK text
|
|
108
|
+
- JPEG and PNG image embedding with transparency
|
|
109
|
+
- Password protection and encryption
|
|
110
|
+
- Per-worksheet page setup (size, orientation, margins)
|
|
111
|
+
- Tree-shakeable (not imported = not bundled)
|
|
112
|
+
|
|
106
113
|
- **Advanced Features**
|
|
107
114
|
- Streaming for large files
|
|
108
115
|
- CSV import/export
|
|
@@ -131,10 +138,107 @@ import { Readable, pipeline, createTransform } from "@cj-tech-master/excelts/str
|
|
|
131
138
|
|
|
132
139
|
Each subpath supports `browser`, `import` (ESM), and `require` (CJS) conditions. See the module READMEs for details:
|
|
133
140
|
|
|
141
|
+
- [PDF Module](src/modules/pdf/README.md) - Full-featured zero-dependency PDF engine with encryption and font embedding
|
|
134
142
|
- [CSV Module](src/modules/csv/README.md) - RFC 4180 parser/formatter, streaming, data generation
|
|
135
143
|
- [Archive Module](src/modules/archive/README.md) - ZIP/TAR create/read/edit, compression, encryption
|
|
136
144
|
- [Stream Module](src/modules/stream/README.md) - Cross-platform Readable/Writable/Transform/Duplex
|
|
137
145
|
|
|
146
|
+
## PDF Export
|
|
147
|
+
|
|
148
|
+
Export any workbook to PDF with zero external dependencies:
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
import { Workbook, excelToPdf } from "@cj-tech-master/excelts";
|
|
152
|
+
|
|
153
|
+
const workbook = new Workbook();
|
|
154
|
+
const sheet = workbook.addWorksheet("Report");
|
|
155
|
+
sheet.columns = [
|
|
156
|
+
{ header: "Product", key: "product", width: 20 },
|
|
157
|
+
{ header: "Revenue", key: "revenue", width: 15 }
|
|
158
|
+
];
|
|
159
|
+
sheet.addRow({ product: "Widget", revenue: 1000 });
|
|
160
|
+
sheet.getColumn("revenue").numFmt = "$#,##0.00";
|
|
161
|
+
|
|
162
|
+
// One-line export
|
|
163
|
+
const pdf = excelToPdf(workbook, {
|
|
164
|
+
showGridLines: true,
|
|
165
|
+
showPageNumbers: true,
|
|
166
|
+
title: "Sales Report"
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Node.js: write to file
|
|
170
|
+
import { writeFileSync } from "fs";
|
|
171
|
+
writeFileSync("report.pdf", pdf);
|
|
172
|
+
|
|
173
|
+
// Browser: download
|
|
174
|
+
const blob = new Blob([pdf], { type: "application/pdf" });
|
|
175
|
+
const url = URL.createObjectURL(blob);
|
|
176
|
+
window.open(url);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Convert Existing XLSX to PDF
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
const workbook = new Workbook();
|
|
183
|
+
await workbook.xlsx.readFile("input.xlsx");
|
|
184
|
+
const pdf = excelToPdf(workbook);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Encryption
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
const pdf = excelToPdf(workbook, {
|
|
191
|
+
encryption: {
|
|
192
|
+
ownerPassword: "admin",
|
|
193
|
+
userPassword: "reader",
|
|
194
|
+
permissions: { print: true, copy: false }
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Unicode / CJK
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
import { readFileSync } from "fs";
|
|
203
|
+
|
|
204
|
+
const pdf = excelToPdf(workbook, {
|
|
205
|
+
font: readFileSync("NotoSansSC-Regular.ttf") // TrueType font for CJK text
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Standalone PDF (No Excel)
|
|
210
|
+
|
|
211
|
+
Generate PDFs from plain data — no workbook, no Map objects, no boilerplate:
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
import { pdf } from "@cj-tech-master/excelts/pdf";
|
|
215
|
+
|
|
216
|
+
// Simplest — pass a 2D array
|
|
217
|
+
const bytes = pdf([
|
|
218
|
+
["Product", "Revenue"],
|
|
219
|
+
["Widget", 1000],
|
|
220
|
+
["Gadget", 2500]
|
|
221
|
+
]);
|
|
222
|
+
|
|
223
|
+
// With column widths and styled cells
|
|
224
|
+
const bytes = pdf(
|
|
225
|
+
{
|
|
226
|
+
name: "Report",
|
|
227
|
+
columns: [
|
|
228
|
+
{ width: 25, header: "Product" },
|
|
229
|
+
{ width: 15, header: "Revenue" }
|
|
230
|
+
],
|
|
231
|
+
data: [
|
|
232
|
+
["Widget", 1000],
|
|
233
|
+
["Gadget", 2500]
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{ showGridLines: true }
|
|
237
|
+
);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
For the full API reference and all options, see the [PDF Module documentation](src/modules/pdf/README.md).
|
|
241
|
+
|
|
138
242
|
## Archive Utilities (ZIP/TAR)
|
|
139
243
|
|
|
140
244
|
ExcelTS includes internal ZIP/TAR utilities used by the XLSX pipeline. If you use the
|
|
@@ -395,6 +499,7 @@ Then open `http://localhost:3000/src/modules/excel/examples/browser-smoke.html`.
|
|
|
395
499
|
|
|
396
500
|
### Browser-Specific Notes
|
|
397
501
|
|
|
502
|
+
- **PDF export is fully supported** in browsers with zero configuration
|
|
398
503
|
- **CSV operations are supported** using native RFC 4180 implementation
|
|
399
504
|
- Use `await workbook.readCsv(input)` to read CSV
|
|
400
505
|
- Use `workbook.writeCsv()` or `await workbook.writeCsvBuffer()` to write CSV
|
|
@@ -428,6 +533,16 @@ import {
|
|
|
428
533
|
xmlEncode,
|
|
429
534
|
xmlDecode,
|
|
430
535
|
|
|
536
|
+
// PDF export
|
|
537
|
+
pdf, // Simplest: pdf([["A", 1], ["B", 2]]) → Uint8Array
|
|
538
|
+
excelToPdf, // Workbook -> Uint8Array (Excel-to-PDF)
|
|
539
|
+
PageSizes, // Built-in page size definitions
|
|
540
|
+
PdfError, // Base PDF error
|
|
541
|
+
PdfRenderError, // Layout/rendering failures
|
|
542
|
+
PdfFontError, // Font parsing/embedding failures
|
|
543
|
+
PdfStructureError, // PDF structure assembly failures
|
|
544
|
+
isPdfError, // Type guard for PDF errors
|
|
545
|
+
|
|
431
546
|
// Error infrastructure
|
|
432
547
|
BaseError, // Base class for all library errors
|
|
433
548
|
ExcelError, // Base Excel error (instanceof checks)
|
|
@@ -490,6 +605,7 @@ For detailed API documentation, please refer to the comprehensive documentation
|
|
|
490
605
|
- Data Validation
|
|
491
606
|
- Conditional Formatting
|
|
492
607
|
- File I/O
|
|
608
|
+
- [PDF Export](src/modules/pdf/README.md)
|
|
493
609
|
|
|
494
610
|
## Contributing Guidelines
|
|
495
611
|
|
package/README_zh.md
CHANGED
|
@@ -6,15 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
## 关于本项目
|
|
8
8
|
|
|
9
|
-
ExcelTS
|
|
9
|
+
ExcelTS 是零依赖的 TypeScript 电子表格与文档工具包:
|
|
10
10
|
|
|
11
|
-
- 🚀 **零运行时依赖**
|
|
12
|
-
-
|
|
13
|
-
- ✅
|
|
14
|
-
- ✅
|
|
15
|
-
- ✅ **增强的测试** - 迁移到 Vitest 并支持浏览器测试
|
|
16
|
-
- ✅ **ESM 优先** - 原生 ES Module 支持,兼容 CommonJS
|
|
17
|
-
- ✅ **命名导出** - 所有导出都是命名导出,更好的 tree-shaking
|
|
11
|
+
- 🚀 **零运行时依赖** — 纯 TypeScript 实现,无任何外部包依赖
|
|
12
|
+
- 📦 **五大模块** — Excel(XLSX/JSON)、PDF(独立引擎 + Excel 桥接)、CSV(RFC 4180)、Archive(ZIP/TAR)、Stream(跨平台)
|
|
13
|
+
- ✅ **跨平台** — Node.js 22+、Bun、Chrome 89+、Firefox 102+、Safari 14.1+
|
|
14
|
+
- ✅ **ESM 优先** — 原生 ES Modules,兼容 CommonJS,完整 tree-shaking 支持
|
|
18
15
|
|
|
19
16
|
## 翻译
|
|
20
17
|
|
|
@@ -103,6 +100,16 @@ cell.fill = {
|
|
|
103
100
|
- 超链接
|
|
104
101
|
- 数据透视表
|
|
105
102
|
|
|
103
|
+
- **PDF 导出**
|
|
104
|
+
- 零依赖 Excel 转 PDF
|
|
105
|
+
- 完整的单元格样式支持(字体、颜色、边框、填充、对齐)
|
|
106
|
+
- 自动分页与重复表头行
|
|
107
|
+
- TrueType 字体嵌入,支持 Unicode/CJK 中文文本
|
|
108
|
+
- JPEG 和 PNG 图片嵌入,支持透明度
|
|
109
|
+
- 密码保护和加密
|
|
110
|
+
- 每个工作表独立的页面设置(纸张大小、方向、页边距)
|
|
111
|
+
- 支持 Tree-shaking(不导入 = 不打包)
|
|
112
|
+
|
|
106
113
|
- **高级功能**
|
|
107
114
|
- 大文件流式处理
|
|
108
115
|
- CSV 导入/导出
|
|
@@ -131,10 +138,107 @@ import { Readable, pipeline, createTransform } from "@cj-tech-master/excelts/str
|
|
|
131
138
|
|
|
132
139
|
每个子路径支持 `browser`、`import`(ESM)和 `require`(CJS)条件。详见各模块文档:
|
|
133
140
|
|
|
141
|
+
- [PDF 模块](src/modules/pdf/README.md) - 零依赖 Excel 转 PDF,支持加密和字体嵌入
|
|
134
142
|
- [CSV 模块](src/modules/csv/README.md) - RFC 4180 解析/格式化、流式处理、数据生成
|
|
135
143
|
- [归档模块](src/modules/archive/README.md) - ZIP/TAR 创建/读取/编辑、压缩、加密
|
|
136
144
|
- [流模块](src/modules/stream/README.md) - 跨平台 Readable/Writable/Transform/Duplex
|
|
137
145
|
|
|
146
|
+
## PDF 导出
|
|
147
|
+
|
|
148
|
+
零依赖将任意工作簿导出为 PDF:
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
import { Workbook, excelToPdf } from "@cj-tech-master/excelts";
|
|
152
|
+
|
|
153
|
+
const workbook = new Workbook();
|
|
154
|
+
const sheet = workbook.addWorksheet("报告");
|
|
155
|
+
sheet.columns = [
|
|
156
|
+
{ header: "产品", key: "product", width: 20 },
|
|
157
|
+
{ header: "收入", key: "revenue", width: 15 }
|
|
158
|
+
];
|
|
159
|
+
sheet.addRow({ product: "组件A", revenue: 1000 });
|
|
160
|
+
sheet.getColumn("revenue").numFmt = "¥#,##0.00";
|
|
161
|
+
|
|
162
|
+
// 一行导出
|
|
163
|
+
const pdf = excelToPdf(workbook, {
|
|
164
|
+
showGridLines: true,
|
|
165
|
+
showPageNumbers: true,
|
|
166
|
+
title: "销售报告"
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// Node.js:写入文件
|
|
170
|
+
import { writeFileSync } from "fs";
|
|
171
|
+
writeFileSync("report.pdf", pdf);
|
|
172
|
+
|
|
173
|
+
// 浏览器:下载
|
|
174
|
+
const blob = new Blob([pdf], { type: "application/pdf" });
|
|
175
|
+
const url = URL.createObjectURL(blob);
|
|
176
|
+
window.open(url);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 将现有 XLSX 转换为 PDF
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
const workbook = new Workbook();
|
|
183
|
+
await workbook.xlsx.readFile("input.xlsx");
|
|
184
|
+
const pdf = excelToPdf(workbook);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 加密
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
const pdf = excelToPdf(workbook, {
|
|
191
|
+
encryption: {
|
|
192
|
+
ownerPassword: "admin",
|
|
193
|
+
userPassword: "reader",
|
|
194
|
+
permissions: { print: true, copy: false }
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Unicode / CJK 中文支持
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
import { readFileSync } from "fs";
|
|
203
|
+
|
|
204
|
+
const pdf = excelToPdf(workbook, {
|
|
205
|
+
font: readFileSync("NotoSansSC-Regular.ttf") // 嵌入 TrueType 字体以支持中文
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 独立 PDF 生成(无需 Excel)
|
|
210
|
+
|
|
211
|
+
无需工作簿,直接从数组数据生成 PDF:
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
import { pdf } from "@cj-tech-master/excelts/pdf";
|
|
215
|
+
|
|
216
|
+
// 最简方式 — 传入二维数组
|
|
217
|
+
const bytes = pdf([
|
|
218
|
+
["产品", "收入"],
|
|
219
|
+
["组件A", 1000],
|
|
220
|
+
["组件B", 2500]
|
|
221
|
+
]);
|
|
222
|
+
|
|
223
|
+
// 带列宽和样式
|
|
224
|
+
const bytes = pdf(
|
|
225
|
+
{
|
|
226
|
+
name: "报告",
|
|
227
|
+
columns: [
|
|
228
|
+
{ width: 25, header: "产品" },
|
|
229
|
+
{ width: 15, header: "收入" }
|
|
230
|
+
],
|
|
231
|
+
data: [
|
|
232
|
+
["组件A", 1000],
|
|
233
|
+
["组件B", 2500]
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{ showGridLines: true }
|
|
237
|
+
);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
完整 API 参考和所有选项请查看 [PDF 模块文档](src/modules/pdf/README.md)。
|
|
241
|
+
|
|
138
242
|
## 归档工具(ZIP/TAR)
|
|
139
243
|
|
|
140
244
|
ExcelTS 内置 ZIP/TAR 归档工具(用于 XLSX 管线)。若直接使用归档相关 API,
|
|
@@ -393,6 +497,7 @@ npx serve .
|
|
|
393
497
|
|
|
394
498
|
### 浏览器版本注意事项
|
|
395
499
|
|
|
500
|
+
- **完全支持 PDF 导出**(浏览器端零配置即可使用)
|
|
396
501
|
- **支持 CSV 操作**(使用原生 RFC 4180 标准实现)
|
|
397
502
|
- 使用 `await workbook.readCsv(input)` 读取 CSV
|
|
398
503
|
- 使用 `workbook.writeCsv()` 或 `await workbook.writeCsvBuffer()` 写入 CSV
|
|
@@ -426,6 +531,16 @@ import {
|
|
|
426
531
|
xmlEncode,
|
|
427
532
|
xmlDecode,
|
|
428
533
|
|
|
534
|
+
// PDF 导出
|
|
535
|
+
pdf, // 最简单:pdf([["A", 1], ["B", 2]]) → Uint8Array
|
|
536
|
+
excelToPdf, // Workbook -> Uint8Array(Excel 转 PDF)
|
|
537
|
+
PageSizes, // 内置页面尺寸定义
|
|
538
|
+
PdfError, // PDF 基础错误
|
|
539
|
+
PdfRenderError, // 布局/渲染错误
|
|
540
|
+
PdfFontError, // 字体解析/嵌入错误
|
|
541
|
+
PdfStructureError, // PDF 结构组装错误
|
|
542
|
+
isPdfError, // PDF 错误类型守卫
|
|
543
|
+
|
|
429
544
|
// 错误基础设施
|
|
430
545
|
BaseError, // 所有库错误的基类
|
|
431
546
|
ExcelError, // Excel 基础错误(支持 instanceof 检查)
|
|
@@ -488,6 +603,7 @@ import {
|
|
|
488
603
|
- 数据验证
|
|
489
604
|
- 条件格式
|
|
490
605
|
- 文件输入输出
|
|
606
|
+
- [PDF 导出](src/modules/pdf/README.md)
|
|
491
607
|
|
|
492
608
|
## 贡献指南
|
|
493
609
|
|
|
@@ -17,11 +17,10 @@ export * from "./modules/excel/enums.js";
|
|
|
17
17
|
export * from "./modules/excel/types.js";
|
|
18
18
|
export type { PivotTable, PivotTableModel, PivotTableValue, PivotTableSource, CacheField, SharedItemValue, DataField, PivotTableSubtotal, RecordValue, ParsedCacheDefinition, ParsedCacheRecords } from "./modules/excel/pivot-table.js";
|
|
19
19
|
export type { FormCheckboxModel, FormCheckboxOptions, FormControlRange, FormControlAnchor } from "./modules/excel/form-control.js";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export { WorkbookWriter, WorkbookReader, WorksheetWriter, WorksheetReader };
|
|
20
|
+
export { WorkbookWriter } from "./modules/excel/stream/workbook-writer.browser.js";
|
|
21
|
+
export { WorkbookReader } from "./modules/excel/stream/workbook-reader.browser.js";
|
|
22
|
+
export { WorksheetWriter } from "./modules/excel/stream/worksheet-writer.js";
|
|
23
|
+
export { WorksheetReader } from "./modules/excel/stream/worksheet-reader.js";
|
|
25
24
|
export type { CsvOptions, CsvInput } from "./modules/excel/workbook.js";
|
|
26
25
|
export { CsvParserStream, CsvFormatterStream, createCsvParserStream, createCsvFormatterStream } from "./modules/csv/stream/index.js";
|
|
27
26
|
export { DefinedNames, type DefinedNameModel } from "./modules/excel/defined-names.js";
|
|
@@ -38,4 +37,6 @@ export { xmlEncode, xmlDecode } from "./utils/utils.base.js";
|
|
|
38
37
|
export { DateParser, DateFormatter, getSupportedFormats, type DateFormat } from "./utils/datetime.js";
|
|
39
38
|
export { BaseError, type BaseErrorOptions, toError, errorToJSON, getErrorChain, getRootCause } from "./utils/errors.js";
|
|
40
39
|
export { concatUint8Arrays, toUint8Array, stringToUint8Array, uint8ArrayToString } from "./utils/binary.js";
|
|
40
|
+
export { pdf, excelToPdf, PageSizes, PdfError, PdfRenderError, PdfFontError, PdfStructureError, isPdfError } from "./modules/pdf/index.js";
|
|
41
|
+
export type { PdfExportOptions, PdfPageSize, PdfOrientation, PdfMargins, PageSizeName, PdfColor } from "./modules/pdf/index.js";
|
|
41
42
|
export { ExcelError, isExcelError, ExcelFileError, ExcelDownloadError, ExcelNotSupportedError, ExcelStreamStateError, InvalidAddressError, ColumnOutOfBoundsError, RowOutOfBoundsError, MergeConflictError, InvalidValueTypeError, XmlParseError, WorksheetNameError, PivotTableError, TableError, ImageError, MaxItemsExceededError } from "./modules/excel/errors.js";
|
|
@@ -29,11 +29,10 @@ export * from "./modules/excel/types.js";
|
|
|
29
29
|
// Streaming Writer (Browser-compatible)
|
|
30
30
|
// Uses cross-platform base implementation without Node.js fs
|
|
31
31
|
// =============================================================================
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export { WorkbookWriter, WorkbookReader, WorksheetWriter, WorksheetReader };
|
|
32
|
+
export { WorkbookWriter } from "./modules/excel/stream/workbook-writer.browser.js";
|
|
33
|
+
export { WorkbookReader } from "./modules/excel/stream/workbook-reader.browser.js";
|
|
34
|
+
export { WorksheetWriter } from "./modules/excel/stream/worksheet-writer.js";
|
|
35
|
+
export { WorksheetReader } from "./modules/excel/stream/worksheet-reader.js";
|
|
37
36
|
export { CsvParserStream, CsvFormatterStream, createCsvParserStream, createCsvFormatterStream } from "./modules/csv/stream/index.js";
|
|
38
37
|
// =============================================================================
|
|
39
38
|
// Additional Classes & Types
|
|
@@ -57,6 +56,10 @@ export { BaseError, toError, errorToJSON, getErrorChain, getRootCause } from "./
|
|
|
57
56
|
// Binary utilities (cross-platform)
|
|
58
57
|
export { concatUint8Arrays, toUint8Array, stringToUint8Array, uint8ArrayToString } from "./utils/binary.js";
|
|
59
58
|
// =============================================================================
|
|
59
|
+
// PDF Export (Browser-compatible, zero external dependencies)
|
|
60
|
+
// =============================================================================
|
|
61
|
+
export { pdf, excelToPdf, PageSizes, PdfError, PdfRenderError, PdfFontError, PdfStructureError, isPdfError } from "./modules/pdf/index.js";
|
|
62
|
+
// =============================================================================
|
|
60
63
|
// Errors
|
|
61
64
|
// =============================================================================
|
|
62
65
|
export { ExcelError, isExcelError, ExcelFileError, ExcelDownloadError, ExcelNotSupportedError, ExcelStreamStateError, InvalidAddressError, ColumnOutOfBoundsError, RowOutOfBoundsError, MergeConflictError, InvalidValueTypeError, XmlParseError, WorksheetNameError, PivotTableError, TableError, ImageError, MaxItemsExceededError } from "./modules/excel/errors.js";
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -37,4 +37,6 @@ export { xmlEncode, xmlDecode } from "./utils/utils.base.js";
|
|
|
37
37
|
export { DateParser, DateFormatter, getSupportedFormats, type DateFormat } from "./utils/datetime.js";
|
|
38
38
|
export { BaseError, type BaseErrorOptions, toError, errorToJSON, getErrorChain, getRootCause } from "./utils/errors.js";
|
|
39
39
|
export { concatUint8Arrays, toUint8Array, stringToUint8Array, uint8ArrayToString } from "./utils/binary.js";
|
|
40
|
+
export { pdf, excelToPdf, PageSizes, PdfError, PdfRenderError, PdfFontError, PdfStructureError, isPdfError } from "./modules/pdf/index.js";
|
|
41
|
+
export type { PdfExportOptions, PdfPageSize, PdfOrientation, PdfMargins, PageSizeName, PdfColor } from "./modules/pdf/index.js";
|
|
40
42
|
export { ExcelError, isExcelError, ExcelFileError, ExcelDownloadError, ExcelNotSupportedError, ExcelStreamStateError, InvalidAddressError, ColumnOutOfBoundsError, RowOutOfBoundsError, MergeConflictError, InvalidValueTypeError, XmlParseError, WorksheetNameError, PivotTableError, TableError, ImageError, MaxItemsExceededError } from "./modules/excel/errors.js";
|
package/dist/browser/index.js
CHANGED
|
@@ -52,6 +52,10 @@ export { BaseError, toError, errorToJSON, getErrorChain, getRootCause } from "./
|
|
|
52
52
|
// Binary utilities (cross-platform)
|
|
53
53
|
export { concatUint8Arrays, toUint8Array, stringToUint8Array, uint8ArrayToString } from "./utils/binary.js";
|
|
54
54
|
// =============================================================================
|
|
55
|
+
// PDF Export
|
|
56
|
+
// =============================================================================
|
|
57
|
+
export { pdf, excelToPdf, PageSizes, PdfError, PdfRenderError, PdfFontError, PdfStructureError, isPdfError } from "./modules/pdf/index.js";
|
|
58
|
+
// =============================================================================
|
|
55
59
|
// Errors
|
|
56
60
|
// =============================================================================
|
|
57
61
|
export { ExcelError, isExcelError, ExcelFileError, ExcelDownloadError, ExcelNotSupportedError, ExcelStreamStateError, InvalidAddressError, ColumnOutOfBoundsError, RowOutOfBoundsError, MergeConflictError, InvalidValueTypeError, XmlParseError, WorksheetNameError, PivotTableError, TableError, ImageError, MaxItemsExceededError } from "./modules/excel/errors.js";
|
|
@@ -22,6 +22,13 @@ import { collect } from "../io/archive-sink.js";
|
|
|
22
22
|
* Local file header fixed size (30 bytes)
|
|
23
23
|
*/
|
|
24
24
|
export const LOCAL_HEADER_FIXED_SIZE = 30;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum allowed uncompressed entry size for non-streaming extraction (512 MB).
|
|
27
|
+
* This is a pre-decompression check based on the declared size in the ZIP metadata.
|
|
28
|
+
* It prevents memory exhaustion from archives that declare very large output sizes.
|
|
29
|
+
* The streaming extraction path (processEntryDataStream) has its own byte-level checks.
|
|
30
|
+
*/
|
|
31
|
+
const DEFAULT_MAX_ENTRY_SIZE = 512 * 1024 * 1024;
|
|
25
32
|
/**
|
|
26
33
|
* Process compressed (and possibly encrypted) entry data to get the final content.
|
|
27
34
|
*
|
|
@@ -36,6 +43,15 @@ export const LOCAL_HEADER_FIXED_SIZE = 30;
|
|
|
36
43
|
*/
|
|
37
44
|
export async function processEntryData(entry, compressedData, password, checkCrc32 = false, validateEntrySizes = true) {
|
|
38
45
|
let result;
|
|
46
|
+
// Pre-decompression size check: reject entries whose *declared* uncompressed size
|
|
47
|
+
// exceeds the limit. This catches archives that honestly declare very large entries
|
|
48
|
+
// but does NOT protect against ZIP bombs that lie about their size (for that, use
|
|
49
|
+
// the streaming path processEntryDataStream which validates actual output bytes).
|
|
50
|
+
if (validateEntrySizes && entry.uncompressedSize > DEFAULT_MAX_ENTRY_SIZE) {
|
|
51
|
+
throw new Error(`Entry "${entry.path}" declares uncompressed size of ${entry.uncompressedSize} bytes, ` +
|
|
52
|
+
`which exceeds the maximum allowed size of ${DEFAULT_MAX_ENTRY_SIZE} bytes. ` +
|
|
53
|
+
"Use the streaming API for large entries.");
|
|
54
|
+
}
|
|
39
55
|
// Handle encrypted entries
|
|
40
56
|
if (entry.isEncrypted) {
|
|
41
57
|
if (!password) {
|
|
@@ -99,6 +115,12 @@ export async function processEntryData(entry, compressedData, password, checkCrc
|
|
|
99
115
|
*/
|
|
100
116
|
export function processEntryDataSync(entry, compressedData, password, validateEntrySizes = true) {
|
|
101
117
|
let result;
|
|
118
|
+
// Pre-decompression size check (same as async version)
|
|
119
|
+
if (validateEntrySizes && entry.uncompressedSize > DEFAULT_MAX_ENTRY_SIZE) {
|
|
120
|
+
throw new Error(`Entry "${entry.path}" declares uncompressed size of ${entry.uncompressedSize} bytes, ` +
|
|
121
|
+
`which exceeds the maximum allowed size of ${DEFAULT_MAX_ENTRY_SIZE} bytes. ` +
|
|
122
|
+
"Use the streaming API for large entries.");
|
|
123
|
+
}
|
|
102
124
|
// Handle encrypted entries
|
|
103
125
|
if (entry.isEncrypted) {
|
|
104
126
|
if (!password) {
|
|
@@ -31,17 +31,17 @@ export type ZipDeflateFileDefaults = {
|
|
|
31
31
|
export declare function buildZipDeflateFileOptions(entryOptions: ZipDeflateFileEntryOptions | undefined, defaults: ZipDeflateFileDefaults): {
|
|
32
32
|
level: number;
|
|
33
33
|
modTime: Date;
|
|
34
|
-
atime: Date;
|
|
35
|
-
ctime: Date;
|
|
36
|
-
birthTime: Date;
|
|
34
|
+
atime: Date | undefined;
|
|
35
|
+
ctime: Date | undefined;
|
|
36
|
+
birthTime: Date | undefined;
|
|
37
37
|
timestamps: ZipTimestampMode;
|
|
38
|
-
comment: string;
|
|
38
|
+
comment: string | undefined;
|
|
39
39
|
smartStore: boolean;
|
|
40
40
|
zip64: Zip64Mode;
|
|
41
41
|
path: false | ZipPathOptions;
|
|
42
|
-
encoding: ZipStringEncoding;
|
|
43
|
-
mode: number;
|
|
44
|
-
msDosAttributes: number;
|
|
45
|
-
externalAttributes: number;
|
|
46
|
-
versionMadeBy: number;
|
|
42
|
+
encoding: ZipStringEncoding | undefined;
|
|
43
|
+
mode: number | undefined;
|
|
44
|
+
msDosAttributes: number | undefined;
|
|
45
|
+
externalAttributes: number | undefined;
|
|
46
|
+
versionMadeBy: number | undefined;
|
|
47
47
|
};
|
|
@@ -13,6 +13,18 @@ import { CENTRAL_DIR_HEADER_SIG, COMPRESSION_AES, UINT16_MAX, UINT32_MAX, ZIP64_
|
|
|
13
13
|
// -----------------------------------------------------------------------------
|
|
14
14
|
// Constants
|
|
15
15
|
// -----------------------------------------------------------------------------
|
|
16
|
+
const MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);
|
|
17
|
+
/**
|
|
18
|
+
* Convert a BigInt to Number, throwing if the value exceeds Number.MAX_SAFE_INTEGER.
|
|
19
|
+
* This prevents silent precision loss when parsing ZIP64 fields.
|
|
20
|
+
*/
|
|
21
|
+
function safeBigIntToNumber(value, fieldName) {
|
|
22
|
+
if (value > MAX_SAFE) {
|
|
23
|
+
throw new Error(`ZIP64 ${fieldName} value ${value} exceeds Number.MAX_SAFE_INTEGER. ` +
|
|
24
|
+
"The archive may be corrupted or malicious.");
|
|
25
|
+
}
|
|
26
|
+
return Number(value);
|
|
27
|
+
}
|
|
16
28
|
/** Minimum EOCD size (22 bytes fixed + 0-byte comment) */
|
|
17
29
|
export const EOCD_MIN_SIZE = 22;
|
|
18
30
|
/** Maximum comment size (2^16 - 1) */
|
|
@@ -129,7 +141,7 @@ export function parseZIP64EOCDLocator(data, offset) {
|
|
|
129
141
|
return -1;
|
|
130
142
|
}
|
|
131
143
|
reader.skip(4); // disk number with ZIP64 EOCD
|
|
132
|
-
return
|
|
144
|
+
return safeBigIntToNumber(reader.readBigUint64(), "EOCD locator offset");
|
|
133
145
|
}
|
|
134
146
|
/**
|
|
135
147
|
* Parse ZIP64 EOCD.
|
|
@@ -167,16 +179,16 @@ export function parseZIP64EOCD(data, offset) {
|
|
|
167
179
|
*/
|
|
168
180
|
export function applyZIP64ToEOCD(eocd, zip64) {
|
|
169
181
|
if (eocd.totalEntries === UINT16_MAX) {
|
|
170
|
-
eocd.totalEntries =
|
|
182
|
+
eocd.totalEntries = safeBigIntToNumber(zip64.totalEntries, "totalEntries");
|
|
171
183
|
}
|
|
172
184
|
if (eocd.entriesOnDisk === UINT16_MAX) {
|
|
173
|
-
eocd.entriesOnDisk =
|
|
185
|
+
eocd.entriesOnDisk = safeBigIntToNumber(zip64.entriesOnDisk, "entriesOnDisk");
|
|
174
186
|
}
|
|
175
187
|
if (eocd.centralDirSize === UINT32_MAX) {
|
|
176
|
-
eocd.centralDirSize =
|
|
188
|
+
eocd.centralDirSize = safeBigIntToNumber(zip64.centralDirSize, "centralDirSize");
|
|
177
189
|
}
|
|
178
190
|
if (eocd.centralDirOffset === UINT32_MAX) {
|
|
179
|
-
eocd.centralDirOffset =
|
|
191
|
+
eocd.centralDirOffset = safeBigIntToNumber(zip64.centralDirOffset, "centralDirOffset");
|
|
180
192
|
}
|
|
181
193
|
}
|
|
182
194
|
// -----------------------------------------------------------------------------
|
|
@@ -134,7 +134,12 @@ export function formatField(value, regex, ctx) {
|
|
|
134
134
|
// Escape formulae to prevent CSV injection (OWASP recommendation)
|
|
135
135
|
// Prefix dangerous characters with single quote to neutralize them in spreadsheet apps
|
|
136
136
|
// Using single quote (') as recommended by OWASP, which Excel interprets as a text prefix
|
|
137
|
-
|
|
137
|
+
// Skip numeric types: negative numbers like -5.55 are not formula injection vectors
|
|
138
|
+
if (escapeFormulae &&
|
|
139
|
+
transformQuoteHint !== false &&
|
|
140
|
+
typeof value !== "number" &&
|
|
141
|
+
typeof value !== "bigint" &&
|
|
142
|
+
startsWithFormulaChar(str)) {
|
|
138
143
|
str = "'" + str;
|
|
139
144
|
}
|
|
140
145
|
// If quoting is disabled, return raw string
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export type { HeaderArray, RowHashArray, RowArray, RowMap, Row, HeaderTransformFunction, RowTransformCallback, RowTransformFunction, RowValidateCallback, RowValidateFunction, TransformContext, FormattedValue, TransformResult, TypeTransformMap, DynamicTypingConfig, CastDateConfig, ColumnConfig, CsvErrorCode, CsvRecordError, OnSkipCallback, CsvParseOptions, CsvFormatOptions, CsvParseArrayOptions, CsvParseObjectOptions, ChunkMeta, CsvParseMeta, RecordInfo, RecordWithInfo, CsvParseResult, CsvParseResultWithObjname, ColumnMismatchConfig, ColumnMismatchLess, ColumnMismatchMore } from "./types.js";
|
|
13
13
|
export { isFormattedValue, quoted, unquoted } from "./types.js";
|
|
14
|
-
export { parseCsv } from "./parse/
|
|
15
|
-
export { parseCsvAsync, parseCsvRows, parseCsvWithProgress } from "./parse/
|
|
14
|
+
export { parseCsv } from "./parse/sync.js";
|
|
15
|
+
export { parseCsvAsync, parseCsvRows, parseCsvWithProgress } from "./parse/async.js";
|
|
16
16
|
export { formatCsv } from "./format/index.js";
|
|
17
17
|
export { CsvParserStream, CsvFormatterStream, createCsvParserStream, createCsvFormatterStream } from "./stream/index.js";
|
|
18
18
|
export { detectDelimiter, detectLinebreak, stripBom } from "./utils/detect.js";
|
|
@@ -14,10 +14,10 @@ export { isFormattedValue, quoted, unquoted } from "./types.js";
|
|
|
14
14
|
// =============================================================================
|
|
15
15
|
// Core Functions
|
|
16
16
|
// =============================================================================
|
|
17
|
-
// Synchronous parser
|
|
18
|
-
export { parseCsv } from "./parse/
|
|
17
|
+
// Synchronous parser (direct import to avoid barrel pulling in async -> stream)
|
|
18
|
+
export { parseCsv } from "./parse/sync.js";
|
|
19
19
|
// Async parser
|
|
20
|
-
export { parseCsvAsync, parseCsvRows, parseCsvWithProgress } from "./parse/
|
|
20
|
+
export { parseCsvAsync, parseCsvRows, parseCsvWithProgress } from "./parse/async.js";
|
|
21
21
|
// Formatter
|
|
22
22
|
export { formatCsv } from "./format/index.js";
|
|
23
23
|
// =============================================================================
|
|
@@ -401,7 +401,7 @@ export function parseCsv(input, options = {}) {
|
|
|
401
401
|
// Handle objname option
|
|
402
402
|
const { objname } = options;
|
|
403
403
|
if (objname && state.headerRow) {
|
|
404
|
-
const objResult =
|
|
404
|
+
const objResult = Object.create(null);
|
|
405
405
|
for (const item of objectRows) {
|
|
406
406
|
const rec = config.infoOption
|
|
407
407
|
? item.record
|
|
@@ -409,6 +409,11 @@ export function parseCsv(input, options = {}) {
|
|
|
409
409
|
const key = rec[objname];
|
|
410
410
|
// Convert undefined/null to empty string, otherwise convert to string
|
|
411
411
|
const keyStr = key === undefined || key === null ? "" : String(key);
|
|
412
|
+
// Skip __proto__ to prevent prototype pollution via JSON.
|
|
413
|
+
// Note: constructor/prototype are safe on Object.create(null) objects.
|
|
414
|
+
if (keyStr === "__proto__") {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
412
417
|
objResult[keyStr] = item;
|
|
413
418
|
}
|
|
414
419
|
return {
|