@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
|
@@ -18,25 +18,37 @@ import { decodePng } from "./png-decoder.js";
|
|
|
18
18
|
import { PdfError, PdfRenderError } from "../errors.js";
|
|
19
19
|
import { PageSizes } from "../types.js";
|
|
20
20
|
import { argbToPdfColor } from "./style-converter.js";
|
|
21
|
+
import { yieldToEventLoop } from "../../../utils/utils.base.js";
|
|
21
22
|
// =============================================================================
|
|
22
23
|
// Public API
|
|
23
24
|
// =============================================================================
|
|
24
25
|
/**
|
|
25
26
|
* Export a PdfWorkbook to PDF format.
|
|
27
|
+
* Yields to the event loop between each output page during layout and rendering.
|
|
26
28
|
*
|
|
27
29
|
* @param workbook - The workbook data to export
|
|
28
30
|
* @param options - Export options controlling layout, pagination, and appearance
|
|
29
|
-
* @returns PDF file as a Uint8Array
|
|
31
|
+
* @returns Promise of PDF file as a Uint8Array
|
|
30
32
|
* @throws {PdfError} If the workbook has no sheets or export fails
|
|
31
33
|
*/
|
|
32
|
-
export function exportPdf(workbook, options) {
|
|
34
|
+
export async function exportPdf(workbook, options) {
|
|
35
|
+
const ctx = prepareExport(workbook, options);
|
|
36
|
+
for (const sheet of ctx.sheets) {
|
|
37
|
+
await layoutSheetInto(ctx, sheet, options);
|
|
38
|
+
}
|
|
39
|
+
return finishExport(ctx, workbook, options);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Shared setup: validate sheets, create font manager and writer,
|
|
43
|
+
* register embedded font.
|
|
44
|
+
*/
|
|
45
|
+
function prepareExport(workbook, options) {
|
|
33
46
|
const sheets = selectSheets(workbook, options?.sheets);
|
|
34
47
|
if (sheets.length === 0) {
|
|
35
48
|
throw new PdfError("No sheets to export. The workbook is empty or no sheets matched.");
|
|
36
49
|
}
|
|
37
50
|
const fontManager = new FontManager();
|
|
38
51
|
const writer = new PdfWriter();
|
|
39
|
-
// --- Step 0: Register embedded font if provided ---
|
|
40
52
|
if (options?.font) {
|
|
41
53
|
try {
|
|
42
54
|
const ttf = parseTtf(options.font);
|
|
@@ -46,21 +58,37 @@ export function exportPdf(workbook, options) {
|
|
|
46
58
|
throw new PdfRenderError("Failed to parse TrueType font", { cause: err });
|
|
47
59
|
}
|
|
48
60
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
return { sheets, fontManager, writer, allPages: [] };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Layout a single sheet and append its pages to the context.
|
|
65
|
+
*/
|
|
66
|
+
async function layoutSheetInto(ctx, sheet, options) {
|
|
67
|
+
try {
|
|
68
|
+
const resolved = resolveOptions(options, sheet);
|
|
69
|
+
const pages = await layoutSheet(sheet, resolved, ctx.fontManager);
|
|
70
|
+
ctx.allPages.push(...pages);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
throw new PdfRenderError(`Failed to layout sheet "${sheet.name}"`, { cause: err });
|
|
60
74
|
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* After layout: fix page numbers, track fonts, write resources,
|
|
78
|
+
* render pages, and build the final PDF binary.
|
|
79
|
+
*/
|
|
80
|
+
async function finishExport(ctx, workbook, options) {
|
|
81
|
+
const { allPages, fontManager, writer, sheets } = ctx;
|
|
61
82
|
const documentOptions = resolveOptions(options, sheets[0]);
|
|
83
|
+
ensureAtLeastOnePage(allPages, documentOptions, sheets);
|
|
84
|
+
fixPageNumbers(allPages);
|
|
85
|
+
trackFontsForHeaders(allPages, fontManager);
|
|
86
|
+
const fontObjectMap = fontManager.writeFontResources(writer);
|
|
87
|
+
const { pageObjNums, sheetFirstPage, pagesTreeObjNum } = await renderAllPages(allPages, fontManager, writer, fontObjectMap);
|
|
88
|
+
return buildFinalPdf(writer, pageObjNums, pagesTreeObjNum, sheetFirstPage, documentOptions, workbook, options);
|
|
89
|
+
}
|
|
90
|
+
function ensureAtLeastOnePage(allPages, documentOptions, sheets) {
|
|
62
91
|
if (allPages.length === 0) {
|
|
63
|
-
// Create at least one empty page
|
|
64
92
|
allPages.push({
|
|
65
93
|
pageNumber: 1,
|
|
66
94
|
options: documentOptions,
|
|
@@ -74,15 +102,17 @@ export function exportPdf(workbook, options) {
|
|
|
74
102
|
sheetRows: [],
|
|
75
103
|
rowYPositions: [],
|
|
76
104
|
rowHeights: [],
|
|
77
|
-
images: []
|
|
105
|
+
images: [],
|
|
106
|
+
scaleFactor: 1
|
|
78
107
|
});
|
|
79
108
|
}
|
|
80
|
-
|
|
109
|
+
}
|
|
110
|
+
function fixPageNumbers(allPages) {
|
|
81
111
|
for (let i = 0; i < allPages.length; i++) {
|
|
82
112
|
allPages[i].pageNumber = i + 1;
|
|
83
113
|
}
|
|
84
|
-
|
|
85
|
-
|
|
114
|
+
}
|
|
115
|
+
function trackFontsForHeaders(allPages, fontManager) {
|
|
86
116
|
if (fontManager.hasEmbeddedFont()) {
|
|
87
117
|
for (const page of allPages) {
|
|
88
118
|
if (page.options.showSheetNames) {
|
|
@@ -102,99 +132,102 @@ export function exportPdf(workbook, options) {
|
|
|
102
132
|
}
|
|
103
133
|
}
|
|
104
134
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
// --- Step 3: Render pages and build PDF structure ---
|
|
135
|
+
}
|
|
136
|
+
async function renderAllPages(allPages, fontManager, writer, fontObjectMap) {
|
|
108
137
|
const pageObjNums = [];
|
|
109
|
-
const pagesTreeObjNum = writer.allocObject();
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
for (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// Add resources dictionary object
|
|
133
|
-
const resourcesObjNum = writer.allocObject();
|
|
134
|
-
const fontDictStr = fontManager.buildFontDictString(fontObjectMap);
|
|
135
|
-
const resourcesDict = new PdfDict().set("Font", fontDictStr);
|
|
136
|
-
// Add XObject resources for images
|
|
137
|
-
if (imageXObjects.size > 0) {
|
|
138
|
-
const xobjParts = ["<<"];
|
|
139
|
-
for (const [name, objNum] of imageXObjects) {
|
|
140
|
-
xobjParts.push(`/${name} ${pdfRef(objNum)}`);
|
|
141
|
-
}
|
|
142
|
-
xobjParts.push(">>");
|
|
143
|
-
resourcesDict.set("XObject", xobjParts.join("\n"));
|
|
138
|
+
const pagesTreeObjNum = writer.allocObject();
|
|
139
|
+
const sheetFirstPage = new Map();
|
|
140
|
+
const totalPages = allPages.length;
|
|
141
|
+
for (let i = 0; i < allPages.length; i++) {
|
|
142
|
+
renderSinglePage(allPages[i], fontManager, writer, fontObjectMap, totalPages, pageObjNums, pagesTreeObjNum, sheetFirstPage);
|
|
143
|
+
if (i < allPages.length - 1) {
|
|
144
|
+
await yieldToEventLoop();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return { pageObjNums, sheetFirstPage, pagesTreeObjNum };
|
|
148
|
+
}
|
|
149
|
+
function renderSinglePage(page, fontManager, writer, fontObjectMap, totalPages, pageObjNums, pagesTreeObjNum, sheetFirstPage) {
|
|
150
|
+
try {
|
|
151
|
+
const { stream: contentStream, alphaValues } = renderPage(page, page.options, fontManager, totalPages);
|
|
152
|
+
// Handle images: create XObject Image entries and draw them
|
|
153
|
+
const imageXObjects = new Map();
|
|
154
|
+
if (page.images.length > 0) {
|
|
155
|
+
for (let imgIdx = 0; imgIdx < page.images.length; imgIdx++) {
|
|
156
|
+
const img = page.images[imgIdx];
|
|
157
|
+
const imgName = `Im${imgIdx + 1}`;
|
|
158
|
+
const imgObjNum = writeImageXObject(writer, img.data, img.format);
|
|
159
|
+
imageXObjects.set(imgName, imgObjNum);
|
|
160
|
+
contentStream.drawImage(imgName, img.rect.x, img.rect.y, img.rect.width, img.rect.height);
|
|
144
161
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
resourcesDict.set("ExtGState", gsParts.join("\n"));
|
|
162
|
+
}
|
|
163
|
+
// Add content stream object
|
|
164
|
+
const contentObjNum = writer.allocObject();
|
|
165
|
+
const contentDict = new PdfDict();
|
|
166
|
+
writer.addStreamObject(contentObjNum, contentDict, contentStream);
|
|
167
|
+
// Add resources dictionary object
|
|
168
|
+
const resourcesObjNum = writer.allocObject();
|
|
169
|
+
const fontDictStr = fontManager.buildFontDictString(fontObjectMap);
|
|
170
|
+
const resourcesDict = new PdfDict().set("Font", fontDictStr);
|
|
171
|
+
if (imageXObjects.size > 0) {
|
|
172
|
+
const xobjParts = ["<<"];
|
|
173
|
+
for (const [name, objNum] of imageXObjects) {
|
|
174
|
+
xobjParts.push(`/${name} ${pdfRef(objNum)}`);
|
|
159
175
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
writer.addObject(annotObjNum, annotDict);
|
|
174
|
-
annotRefs.push(annotObjNum);
|
|
175
|
-
}
|
|
176
|
+
xobjParts.push(">>");
|
|
177
|
+
resourcesDict.set("XObject", xobjParts.join("\n"));
|
|
178
|
+
}
|
|
179
|
+
if (alphaValues.size > 0) {
|
|
180
|
+
const gsParts = ["<<"];
|
|
181
|
+
for (const alpha of alphaValues) {
|
|
182
|
+
const gsObjNum = writer.allocObject();
|
|
183
|
+
const gsDict = new PdfDict()
|
|
184
|
+
.set("Type", "/ExtGState")
|
|
185
|
+
.set("ca", pdfNumber(alpha))
|
|
186
|
+
.set("CA", pdfNumber(alpha));
|
|
187
|
+
writer.addObject(gsObjNum, gsDict);
|
|
188
|
+
gsParts.push(`/${alphaGsName(alpha)} ${pdfRef(gsObjNum)}`);
|
|
176
189
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
+
gsParts.push(">>");
|
|
191
|
+
resourcesDict.set("ExtGState", gsParts.join("\n"));
|
|
192
|
+
}
|
|
193
|
+
writer.addObject(resourcesObjNum, resourcesDict);
|
|
194
|
+
// Create link annotations for hyperlinks
|
|
195
|
+
const annotRefs = [];
|
|
196
|
+
for (const cell of page.cells) {
|
|
197
|
+
if (cell.hyperlink) {
|
|
198
|
+
const annotObjNum = writer.allocObject();
|
|
199
|
+
const rect = `[${pdfNumber(cell.rect.x)} ${pdfNumber(cell.rect.y)} ${pdfNumber(cell.rect.x + cell.rect.width)} ${pdfNumber(cell.rect.y + cell.rect.height)}]`;
|
|
200
|
+
const annotDict = new PdfDict()
|
|
201
|
+
.set("Type", "/Annot")
|
|
202
|
+
.set("Subtype", "/Link")
|
|
203
|
+
.set("Rect", rect)
|
|
204
|
+
.set("Border", "[0 0 0]")
|
|
205
|
+
.set("A", `<< /Type /Action /S /URI /URI (${cell.hyperlink.replace(/[()\\]/g, "\\$&")}) >>`);
|
|
206
|
+
writer.addObject(annotObjNum, annotDict);
|
|
207
|
+
annotRefs.push(annotObjNum);
|
|
190
208
|
}
|
|
191
209
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
210
|
+
// Add page object
|
|
211
|
+
const pageObjNum = writer.addPage({
|
|
212
|
+
parentRef: pagesTreeObjNum,
|
|
213
|
+
width: page.width,
|
|
214
|
+
height: page.height,
|
|
215
|
+
contentsRef: contentObjNum,
|
|
216
|
+
resourcesRef: resourcesObjNum,
|
|
217
|
+
annotRefs: annotRefs.length > 0 ? annotRefs : undefined
|
|
218
|
+
});
|
|
219
|
+
pageObjNums.push(pageObjNum);
|
|
220
|
+
if (!sheetFirstPage.has(page.sheetName)) {
|
|
221
|
+
sheetFirstPage.set(page.sheetName, pageObjNums.length - 1);
|
|
196
222
|
}
|
|
197
223
|
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
throw new PdfRenderError(`Failed to render page ${page.pageNumber} of "${page.sheetName}"`, {
|
|
226
|
+
cause: err
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function buildFinalPdf(writer, pageObjNums, pagesTreeObjNum, sheetFirstPage, documentOptions, workbook, options) {
|
|
198
231
|
// --- Step 4: Build page tree ---
|
|
199
232
|
const pagesKids = "[" + pageObjNums.map(n => pdfRef(n)).join(" ") + "]";
|
|
200
233
|
const pagesDict = new PdfDict()
|
|
@@ -286,7 +319,14 @@ function resolveOptions(options, sheet) {
|
|
|
286
319
|
orientation,
|
|
287
320
|
margins,
|
|
288
321
|
fitToPage: options?.fitToPage !== undefined ? options.fitToPage : true,
|
|
289
|
-
scale: Math.max(0.1, Math.min(3.0, options?.scale ??
|
|
322
|
+
scale: Math.max(0.1, Math.min(3.0, options?.scale ??
|
|
323
|
+
// When fitToPage is active (default), ignore sheet's pageSetup.scale
|
|
324
|
+
// to avoid double-scaling. Only apply sheet scale when fitToPage is off.
|
|
325
|
+
((options?.fitToPage !== undefined ? options.fitToPage : true)
|
|
326
|
+
? 1.0
|
|
327
|
+
: ps?.scale
|
|
328
|
+
? ps.scale / 100
|
|
329
|
+
: 1.0))),
|
|
290
330
|
showGridLines: options?.showGridLines ?? ps?.showGridLines ?? false,
|
|
291
331
|
gridLineColor,
|
|
292
332
|
repeatRows,
|
|
@@ -79,18 +79,18 @@ export function excelColorToPdf(color) {
|
|
|
79
79
|
* These are the default Office theme colors.
|
|
80
80
|
*/
|
|
81
81
|
function themeColorToPdf(themeIndex) {
|
|
82
|
-
// Default Office theme color palette
|
|
82
|
+
// Default Office 2019+ theme color palette (hex values verified)
|
|
83
83
|
const themeColors = [
|
|
84
|
-
{ r: 1, g: 1, b: 1 }, // 0: lt1 (white / window background)
|
|
85
|
-
{ r: 0, g: 0, b: 0 }, // 1: dk1 (black / window text)
|
|
86
|
-
{ r: 0.
|
|
87
|
-
{ r: 0.267, g: 0.
|
|
88
|
-
{ r: 0.
|
|
89
|
-
{ r: 0.
|
|
90
|
-
{ r: 0.
|
|
91
|
-
{ r: 1, g: 0.753, b: 0 }, // 7: accent4 (gold)
|
|
92
|
-
{ r: 0.
|
|
93
|
-
{ r: 0.439, g: 0.678, b: 0.278 } // 9: accent6 (green)
|
|
84
|
+
{ r: 1, g: 1, b: 1 }, // 0: lt1 — #FFFFFF (white / window background)
|
|
85
|
+
{ r: 0, g: 0, b: 0 }, // 1: dk1 — #000000 (black / window text)
|
|
86
|
+
{ r: 0.906, g: 0.902, b: 0.902 }, // 2: lt2 — #E7E6E6
|
|
87
|
+
{ r: 0.267, g: 0.329, b: 0.416 }, // 3: dk2 — #44546A
|
|
88
|
+
{ r: 0.267, g: 0.447, b: 0.769 }, // 4: accent1 — #4472C4 (blue)
|
|
89
|
+
{ r: 0.929, g: 0.49, b: 0.192 }, // 5: accent2 — #ED7D31 (orange)
|
|
90
|
+
{ r: 0.647, g: 0.647, b: 0.647 }, // 6: accent3 — #A5A5A5 (gray)
|
|
91
|
+
{ r: 1, g: 0.753, b: 0 }, // 7: accent4 — #FFC000 (gold)
|
|
92
|
+
{ r: 0.357, g: 0.608, b: 0.835 }, // 8: accent5 — #5B9BD5 (light blue)
|
|
93
|
+
{ r: 0.439, g: 0.678, b: 0.278 } // 9: accent6 — #70AD47 (green)
|
|
94
94
|
];
|
|
95
95
|
if (themeIndex >= 0 && themeIndex < themeColors.length) {
|
|
96
96
|
return themeColors[themeIndex];
|
|
@@ -182,33 +182,33 @@ export function excelFillToPdfColor(fill) {
|
|
|
182
182
|
function borderStyleToLineWidth(style) {
|
|
183
183
|
switch (style) {
|
|
184
184
|
case "thin":
|
|
185
|
-
return 0.
|
|
185
|
+
return 0.25;
|
|
186
186
|
case "medium":
|
|
187
|
-
return
|
|
187
|
+
return 0.5;
|
|
188
188
|
case "thick":
|
|
189
|
-
return 1
|
|
189
|
+
return 1;
|
|
190
190
|
case "double":
|
|
191
|
-
return 0.5;
|
|
192
|
-
case "hair":
|
|
193
191
|
return 0.25;
|
|
192
|
+
case "hair":
|
|
193
|
+
return 0.1;
|
|
194
194
|
case "dotted":
|
|
195
|
-
return 0.
|
|
195
|
+
return 0.25;
|
|
196
196
|
case "dashed":
|
|
197
|
-
return 0.
|
|
197
|
+
return 0.25;
|
|
198
198
|
case "dashDot":
|
|
199
|
-
return 0.
|
|
199
|
+
return 0.25;
|
|
200
200
|
case "dashDotDot":
|
|
201
|
-
return 0.
|
|
201
|
+
return 0.25;
|
|
202
202
|
case "slantDashDot":
|
|
203
|
-
return 0.
|
|
203
|
+
return 0.25;
|
|
204
204
|
case "mediumDashed":
|
|
205
|
-
return
|
|
205
|
+
return 0.5;
|
|
206
206
|
case "mediumDashDot":
|
|
207
|
-
return
|
|
207
|
+
return 0.5;
|
|
208
208
|
case "mediumDashDotDot":
|
|
209
|
-
return 1;
|
|
210
|
-
default:
|
|
211
209
|
return 0.5;
|
|
210
|
+
default:
|
|
211
|
+
return 0.25;
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
@@ -246,7 +246,8 @@ function convertBorder(border) {
|
|
|
246
246
|
return {
|
|
247
247
|
width: borderStyleToLineWidth(border.style),
|
|
248
248
|
color: excelColorToPdf(border.color) ?? DEFAULT_COLORS.black,
|
|
249
|
-
dashPattern: borderStyleToDashPattern(border.style)
|
|
249
|
+
dashPattern: borderStyleToDashPattern(border.style),
|
|
250
|
+
isDouble: border.style === "double"
|
|
250
251
|
};
|
|
251
252
|
}
|
|
252
253
|
/**
|
|
@@ -335,3 +335,13 @@ export function stringToUtf16Le(str) {
|
|
|
335
335
|
}
|
|
336
336
|
return bytes;
|
|
337
337
|
}
|
|
338
|
+
// =============================================================================
|
|
339
|
+
// Async utilities
|
|
340
|
+
// =============================================================================
|
|
341
|
+
/**
|
|
342
|
+
* Yield to the event loop via a macrotask.
|
|
343
|
+
* Uses `setTimeout(0)` which works in both Node.js and browsers.
|
|
344
|
+
*/
|
|
345
|
+
export function yieldToEventLoop() {
|
|
346
|
+
return new Promise(resolve => setTimeout(resolve, 0));
|
|
347
|
+
}
|