@cj-tech-master/excelts 6.2.0 → 7.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 (56) hide show
  1. package/README.md +45 -17
  2. package/README_zh.md +43 -15
  3. package/dist/browser/index.browser.d.ts +1 -1
  4. package/dist/browser/index.browser.js +1 -1
  5. package/dist/browser/index.d.ts +2 -2
  6. package/dist/browser/index.js +1 -1
  7. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +0 -2
  8. package/dist/browser/modules/excel/stream/workbook-writer.d.ts +2 -2
  9. package/dist/browser/modules/excel/types.d.ts +0 -2
  10. package/dist/browser/modules/pdf/excel-bridge.d.ts +29 -0
  11. package/dist/browser/modules/pdf/excel-bridge.js +423 -0
  12. package/dist/browser/modules/pdf/index.d.ts +22 -24
  13. package/dist/browser/modules/pdf/index.js +22 -25
  14. package/dist/browser/modules/pdf/pdf.d.ts +121 -0
  15. package/dist/browser/modules/pdf/pdf.js +255 -0
  16. package/dist/browser/modules/pdf/render/layout-engine.d.ts +10 -8
  17. package/dist/browser/modules/pdf/render/layout-engine.js +115 -209
  18. package/dist/browser/modules/pdf/render/pdf-exporter.d.ts +9 -62
  19. package/dist/browser/modules/pdf/render/pdf-exporter.js +38 -78
  20. package/dist/browser/modules/pdf/render/style-converter.d.ts +20 -18
  21. package/dist/browser/modules/pdf/render/style-converter.js +24 -23
  22. package/dist/browser/modules/pdf/types.d.ts +193 -11
  23. package/dist/browser/modules/pdf/types.js +22 -1
  24. package/dist/cjs/index.js +3 -3
  25. package/dist/cjs/modules/pdf/excel-bridge.js +426 -0
  26. package/dist/cjs/modules/pdf/index.js +25 -28
  27. package/dist/cjs/modules/pdf/pdf.js +258 -0
  28. package/dist/cjs/modules/pdf/render/layout-engine.js +116 -210
  29. package/dist/cjs/modules/pdf/render/pdf-exporter.js +37 -79
  30. package/dist/cjs/modules/pdf/render/style-converter.js +24 -23
  31. package/dist/cjs/modules/pdf/types.js +23 -2
  32. package/dist/esm/index.browser.js +1 -1
  33. package/dist/esm/index.js +1 -1
  34. package/dist/esm/modules/pdf/excel-bridge.js +423 -0
  35. package/dist/esm/modules/pdf/index.js +22 -25
  36. package/dist/esm/modules/pdf/pdf.js +255 -0
  37. package/dist/esm/modules/pdf/render/layout-engine.js +115 -209
  38. package/dist/esm/modules/pdf/render/pdf-exporter.js +38 -78
  39. package/dist/esm/modules/pdf/render/style-converter.js +24 -23
  40. package/dist/esm/modules/pdf/types.js +22 -1
  41. package/dist/iife/excelts.iife.js +728 -251
  42. package/dist/iife/excelts.iife.js.map +1 -1
  43. package/dist/iife/excelts.iife.min.js +34 -34
  44. package/dist/types/index.browser.d.ts +1 -1
  45. package/dist/types/index.d.ts +2 -2
  46. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +0 -2
  47. package/dist/types/modules/excel/stream/workbook-writer.d.ts +2 -2
  48. package/dist/types/modules/excel/types.d.ts +0 -2
  49. package/dist/types/modules/pdf/excel-bridge.d.ts +29 -0
  50. package/dist/types/modules/pdf/index.d.ts +22 -24
  51. package/dist/types/modules/pdf/pdf.d.ts +121 -0
  52. package/dist/types/modules/pdf/render/layout-engine.d.ts +10 -8
  53. package/dist/types/modules/pdf/render/pdf-exporter.d.ts +9 -62
  54. package/dist/types/modules/pdf/render/style-converter.d.ts +20 -18
  55. package/dist/types/modules/pdf/types.d.ts +193 -11
  56. package/package.json +1 -1
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Simplified PDF generation API.
3
+ *
4
+ * Provides a concise way to create PDFs from plain data — no need to manually
5
+ * construct Map objects, compute bounds, or specify cell types.
6
+ *
7
+ * @example Simplest — pass a 2D array:
8
+ * ```typescript
9
+ * import { pdf } from "@cj-tech-master/excelts/pdf";
10
+ *
11
+ * const bytes = pdf([
12
+ * ["Product", "Revenue"],
13
+ * ["Widget", 1000],
14
+ * ["Gadget", 2500]
15
+ * ]);
16
+ * ```
17
+ *
18
+ * @example With options:
19
+ * ```typescript
20
+ * const bytes = pdf([
21
+ * ["Name", "Score"],
22
+ * ["Alice", 95],
23
+ * ["Bob", 87]
24
+ * ], { showGridLines: true, title: "Scores" });
25
+ * ```
26
+ *
27
+ * @example Multiple sheets:
28
+ * ```typescript
29
+ * const bytes = pdf({
30
+ * sheets: [
31
+ * { name: "Sales", data: [["Product", "Revenue"], ["Widget", 1000]] },
32
+ * { name: "Costs", data: [["Item", "Amount"], ["Rent", 500]] }
33
+ * ]
34
+ * });
35
+ * ```
36
+ *
37
+ * @example With column widths and styles:
38
+ * ```typescript
39
+ * const bytes = pdf({
40
+ * name: "Report",
41
+ * columns: [{ width: 25 }, { width: 15 }],
42
+ * data: [
43
+ * ["Product", "Revenue"],
44
+ * ["Widget", "$1,000"]
45
+ * ]
46
+ * });
47
+ * ```
48
+ */
49
+ import { PdfCellType } from "./types.js";
50
+ import { exportPdf } from "./render/pdf-exporter.js";
51
+ // =============================================================================
52
+ // Public API
53
+ // =============================================================================
54
+ /**
55
+ * Generate a PDF.
56
+ *
57
+ * Accepts anything from a plain 2D array to a multi-sheet workbook.
58
+ *
59
+ * @param input - 2D array, sheet object, or workbook object
60
+ * @param options - PDF export options (page size, margins, etc.)
61
+ * @returns PDF file as Uint8Array
62
+ */
63
+ export function pdf(input, options) {
64
+ const workbook = normalizeInput(input);
65
+ return exportPdf(workbook, options);
66
+ }
67
+ // =============================================================================
68
+ // Normalization
69
+ // =============================================================================
70
+ function normalizeInput(input) {
71
+ // 2D array → single sheet
72
+ if (Array.isArray(input)) {
73
+ return {
74
+ sheets: [normalizeSheet({ data: input })]
75
+ };
76
+ }
77
+ // Workbook with sheets array
78
+ if ("sheets" in input) {
79
+ return {
80
+ title: input.title,
81
+ creator: input.author,
82
+ sheets: input.sheets.map((s, i) => normalizeSheet(s, i))
83
+ };
84
+ }
85
+ // Single sheet object
86
+ return {
87
+ sheets: [normalizeSheet(input)]
88
+ };
89
+ }
90
+ function normalizeSheet(sheet, index) {
91
+ const data = sheet.data;
92
+ const sheetName = sheet.name ?? `Sheet${(index ?? 0) + 1}`;
93
+ // Check if columns have headers
94
+ const columnHeaders = sheet.columns?.map(c => (typeof c === "number" ? undefined : c.header));
95
+ const hasHeaders = columnHeaders?.some(h => h !== undefined) ?? false;
96
+ // Determine dimensions — consider data rows, column definitions, and images
97
+ let maxCols = 0;
98
+ for (const row of data) {
99
+ if (row.length > maxCols) {
100
+ maxCols = row.length;
101
+ }
102
+ }
103
+ let colCount = Math.max(maxCols, sheet.columns?.length ?? 0);
104
+ let totalRows = data.length + (hasHeaders ? 1 : 0);
105
+ // Pre-scan images to extend bounds before the empty check
106
+ if (sheet.images) {
107
+ for (const img of sheet.images) {
108
+ const imgCol = img.col + 1; // 0-indexed → 1-indexed
109
+ const imgRow = img.row + 1;
110
+ if (imgCol > colCount) {
111
+ colCount = imgCol;
112
+ }
113
+ if (imgRow > totalRows) {
114
+ totalRows = imgRow;
115
+ }
116
+ }
117
+ }
118
+ if (colCount === 0) {
119
+ return {
120
+ name: sheetName,
121
+ bounds: { top: 0, left: 0, bottom: 0, right: 0 },
122
+ columns: new Map(),
123
+ rows: new Map()
124
+ };
125
+ }
126
+ // Build columns
127
+ const columns = new Map();
128
+ if (sheet.columns) {
129
+ for (let i = 0; i < sheet.columns.length; i++) {
130
+ const col = sheet.columns[i];
131
+ const width = typeof col === "number" ? col : col.width;
132
+ columns.set(i + 1, { width: width ?? 12 });
133
+ }
134
+ }
135
+ // Fill missing columns with default width
136
+ for (let c = 1; c <= colCount; c++) {
137
+ if (!columns.has(c)) {
138
+ columns.set(c, { width: 12 });
139
+ }
140
+ }
141
+ // Build rows
142
+ const rows = new Map();
143
+ let rowOffset = 1;
144
+ // Insert column headers as the first row if provided
145
+ if (hasHeaders && columnHeaders) {
146
+ const cells = new Map();
147
+ for (let c = 0; c < columnHeaders.length; c++) {
148
+ const text = columnHeaders[c];
149
+ if (text === undefined) {
150
+ continue;
151
+ }
152
+ cells.set(c + 1, {
153
+ type: PdfCellType.String,
154
+ value: text,
155
+ text,
156
+ col: c + 1,
157
+ style: { font: { bold: true } }
158
+ });
159
+ }
160
+ rows.set(1, { cells });
161
+ rowOffset = 2;
162
+ }
163
+ // Insert data rows
164
+ for (let r = 0; r < data.length; r++) {
165
+ const rowNum = r + rowOffset;
166
+ const row = data[r];
167
+ const cells = new Map();
168
+ for (let c = 0; c < row.length; c++) {
169
+ const cell = normalizeCell(row[c], c + 1);
170
+ if (cell) {
171
+ cells.set(c + 1, cell);
172
+ }
173
+ }
174
+ rows.set(rowNum, { cells });
175
+ }
176
+ // Normalize images
177
+ let images;
178
+ if (sheet.images && sheet.images.length > 0) {
179
+ images = sheet.images.map(img => ({
180
+ data: img.data,
181
+ format: img.format,
182
+ range: {
183
+ tl: { col: img.col, row: img.row },
184
+ ext: { width: img.width, height: img.height }
185
+ }
186
+ }));
187
+ // Ensure columns and rows exist for the image-extended bounds
188
+ for (let c = 1; c <= colCount; c++) {
189
+ if (!columns.has(c)) {
190
+ columns.set(c, { width: 12 });
191
+ }
192
+ }
193
+ for (let r = 1; r <= totalRows; r++) {
194
+ if (!rows.has(r)) {
195
+ rows.set(r, { cells: new Map() });
196
+ }
197
+ }
198
+ }
199
+ return {
200
+ name: sheetName,
201
+ bounds: { top: 1, left: 1, bottom: totalRows, right: colCount },
202
+ columns,
203
+ rows,
204
+ images
205
+ };
206
+ }
207
+ function normalizeCell(value, col) {
208
+ if (value === null || value === undefined) {
209
+ return null;
210
+ }
211
+ // Styled cell object
212
+ if (typeof value === "object" && !(value instanceof Date) && "value" in value) {
213
+ const cell = value;
214
+ const inner = normalizeCell(cell.value, col);
215
+ if (!inner) {
216
+ return null;
217
+ }
218
+ // Apply style overrides
219
+ const style = {};
220
+ if (cell.bold || cell.italic || cell.fontSize || cell.fontColor) {
221
+ style.font = {
222
+ bold: cell.bold,
223
+ italic: cell.italic,
224
+ size: cell.fontSize,
225
+ color: cell.fontColor ? { argb: cell.fontColor } : undefined
226
+ };
227
+ }
228
+ if (cell.fillColor) {
229
+ style.fill = {
230
+ type: "pattern",
231
+ pattern: "solid",
232
+ fgColor: { argb: cell.fillColor }
233
+ };
234
+ }
235
+ if (cell.align) {
236
+ style.alignment = { horizontal: cell.align };
237
+ }
238
+ inner.style = style;
239
+ return inner;
240
+ }
241
+ // Primitive values
242
+ if (typeof value === "string") {
243
+ return { type: PdfCellType.String, value, text: value, col };
244
+ }
245
+ if (typeof value === "number") {
246
+ return { type: PdfCellType.Number, value, text: String(value), col };
247
+ }
248
+ if (typeof value === "boolean") {
249
+ return { type: PdfCellType.Boolean, value, text: value ? "TRUE" : "FALSE", col };
250
+ }
251
+ if (value instanceof Date) {
252
+ return { type: PdfCellType.Date, value, text: value.toLocaleDateString(), col };
253
+ }
254
+ return null;
255
+ }
@@ -1,23 +1,25 @@
1
1
  /**
2
- * Layout engine for Excel-to-PDF conversion.
2
+ * Layout engine for PDF generation.
3
3
  *
4
- * Takes a worksheet and produces LayoutPage objects that describe exactly
4
+ * Takes a PdfSheetData and produces LayoutPage objects that describe exactly
5
5
  * where each cell, border, and piece of text should be drawn on each PDF page.
6
6
  *
7
+ * This module is fully independent of the Excel module — it works with
8
+ * the PDF module's own data model (PdfSheetData, PdfCellData, etc.).
9
+ *
7
10
  * Key responsibilities:
8
- * - Convert Excel column widths (character units) to PDF points
9
- * - Convert Excel row heights (points already, but may need scaling)
11
+ * - Convert column widths (character units) to PDF points
12
+ * - Convert row heights (points already, but may need scaling)
10
13
  * - Handle merged cells spanning multiple rows/columns
11
14
  * - Paginate content across multiple pages
12
15
  * - Handle fitToPage scaling
13
16
  * - Handle repeated header rows
14
17
  * - Skip hidden rows and columns
15
18
  */
16
- import type { Worksheet } from "../../excel/worksheet.js";
17
- import type { ResolvedPdfOptions, LayoutPage } from "../types.js";
19
+ import type { PdfSheetData, ResolvedPdfOptions, LayoutPage } from "../types.js";
18
20
  import type { FontManager } from "../font/font-manager.js";
19
21
  /**
20
- * Compute the layout for a worksheet across one or more PDF pages.
22
+ * Compute the layout for a sheet across one or more PDF pages.
21
23
  */
22
- export declare function layoutWorksheet(worksheet: Worksheet, options: ResolvedPdfOptions, fontManager: FontManager): LayoutPage[];
24
+ export declare function layoutSheet(sheet: PdfSheetData, options: ResolvedPdfOptions, fontManager: FontManager): LayoutPage[];
23
25
  export declare function paginateRows(rowHeights: number[], availableHeight: number, repeatRowCount: number, rowBreaks: Set<number>): number[][];