@cj-tech-master/excelts 9.0.0 → 9.1.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/dist/browser/index.browser.d.ts +2 -0
- package/dist/browser/index.browser.js +2 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/modules/excel/image.d.ts +27 -2
- package/dist/browser/modules/excel/image.js +23 -1
- package/dist/browser/modules/excel/stream/worksheet-writer.d.ts +16 -1
- package/dist/browser/modules/excel/stream/worksheet-writer.js +68 -0
- package/dist/browser/modules/excel/types.d.ts +72 -0
- package/dist/browser/modules/excel/utils/drawing-utils.d.ts +4 -0
- package/dist/browser/modules/excel/utils/drawing-utils.js +5 -0
- package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +4 -0
- package/dist/browser/modules/excel/utils/ooxml-paths.js +15 -0
- package/dist/browser/modules/excel/utils/watermark-image.d.ts +67 -0
- package/dist/browser/modules/excel/utils/watermark-image.js +383 -0
- package/dist/browser/modules/excel/worksheet.d.ts +39 -1
- package/dist/browser/modules/excel/worksheet.js +99 -0
- package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +3 -2
- package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +6 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/blip-fill-xform.d.ts +2 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/blip-fill-xform.js +0 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/blip-xform.d.ts +3 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/blip-xform.js +22 -6
- package/dist/browser/modules/excel/xlsx/xform/drawing/pic-xform.d.ts +3 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/pic-xform.js +5 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/vml-drawing-xform.d.ts +19 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +103 -4
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +135 -8
- package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +1 -0
- package/dist/browser/modules/excel/xlsx/xlsx.browser.js +53 -1
- package/dist/browser/modules/pdf/core/pdf-writer.d.ts +1 -1
- package/dist/browser/modules/pdf/core/pdf-writer.js +2 -1
- package/dist/browser/modules/pdf/index.d.ts +1 -1
- package/dist/browser/modules/pdf/render/page-renderer.d.ts +29 -1
- package/dist/browser/modules/pdf/render/page-renderer.js +394 -25
- package/dist/browser/modules/pdf/render/pdf-exporter.js +84 -47
- package/dist/browser/modules/pdf/types.d.ts +235 -0
- package/dist/cjs/index.js +5 -2
- package/dist/cjs/modules/excel/image.js +23 -1
- package/dist/cjs/modules/excel/stream/worksheet-writer.js +68 -0
- package/dist/cjs/modules/excel/utils/drawing-utils.js +5 -0
- package/dist/cjs/modules/excel/utils/ooxml-paths.js +19 -0
- package/dist/cjs/modules/excel/utils/watermark-image.js +386 -0
- package/dist/cjs/modules/excel/worksheet.js +99 -0
- package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +3 -2
- package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +6 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/blip-fill-xform.js +0 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/blip-xform.js +22 -6
- package/dist/cjs/modules/excel/xlsx/xform/drawing/pic-xform.js +5 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +103 -4
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +134 -7
- package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +52 -0
- package/dist/cjs/modules/pdf/core/pdf-writer.js +2 -1
- package/dist/cjs/modules/pdf/render/page-renderer.js +396 -25
- package/dist/cjs/modules/pdf/render/pdf-exporter.js +83 -46
- package/dist/esm/index.browser.js +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/modules/excel/image.js +23 -1
- package/dist/esm/modules/excel/stream/worksheet-writer.js +68 -0
- package/dist/esm/modules/excel/utils/drawing-utils.js +5 -0
- package/dist/esm/modules/excel/utils/ooxml-paths.js +15 -0
- package/dist/esm/modules/excel/utils/watermark-image.js +383 -0
- package/dist/esm/modules/excel/worksheet.js +99 -0
- package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +3 -2
- package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +6 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/blip-fill-xform.js +0 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/blip-xform.js +22 -6
- package/dist/esm/modules/excel/xlsx/xform/drawing/pic-xform.js +5 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +103 -4
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +135 -8
- package/dist/esm/modules/excel/xlsx/xlsx.browser.js +53 -1
- package/dist/esm/modules/pdf/core/pdf-writer.js +2 -1
- package/dist/esm/modules/pdf/render/page-renderer.js +394 -25
- package/dist/esm/modules/pdf/render/pdf-exporter.js +84 -47
- package/dist/iife/excelts.iife.js +2390 -469
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +47 -47
- package/dist/types/index.browser.d.ts +2 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/modules/excel/image.d.ts +27 -2
- package/dist/types/modules/excel/stream/worksheet-writer.d.ts +16 -1
- package/dist/types/modules/excel/types.d.ts +72 -0
- package/dist/types/modules/excel/utils/drawing-utils.d.ts +4 -0
- package/dist/types/modules/excel/utils/ooxml-paths.d.ts +4 -0
- package/dist/types/modules/excel/utils/watermark-image.d.ts +67 -0
- package/dist/types/modules/excel/worksheet.d.ts +39 -1
- package/dist/types/modules/excel/xlsx/xform/drawing/blip-fill-xform.d.ts +2 -1
- package/dist/types/modules/excel/xlsx/xform/drawing/blip-xform.d.ts +3 -1
- package/dist/types/modules/excel/xlsx/xform/drawing/pic-xform.d.ts +3 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/vml-drawing-xform.d.ts +19 -0
- package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +1 -0
- package/dist/types/modules/pdf/core/pdf-writer.d.ts +1 -1
- package/dist/types/modules/pdf/index.d.ts +1 -1
- package/dist/types/modules/pdf/render/page-renderer.d.ts +29 -1
- package/dist/types/modules/pdf/types.d.ts +235 -0
- package/package.json +1 -1
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
* It is used internally by the public `pdf()` and `excelToPdf()` APIs.
|
|
9
9
|
*/
|
|
10
10
|
import { PdfWriter } from "../core/pdf-writer.js";
|
|
11
|
+
import { PdfContentStream } from "../core/pdf-stream.js";
|
|
11
12
|
import { PdfDict, pdfRef, pdfNumber, pdfString as pdfStr } from "../core/pdf-object.js";
|
|
12
13
|
import { FontManager, resolvePdfFontName } from "../font/font-manager.js";
|
|
13
14
|
import { parseTtf } from "../font/ttf-parser.js";
|
|
14
15
|
import { initEncryption } from "../core/encryption.js";
|
|
15
16
|
import { layoutSheet } from "./layout-engine.js";
|
|
16
|
-
import { renderPage, alphaGsName } from "./page-renderer.js";
|
|
17
|
+
import { renderPage, alphaGsName, renderWatermark, parseImageDimensions } from "./page-renderer.js";
|
|
17
18
|
import { decodePng } from "./png-decoder.js";
|
|
18
19
|
import { PdfError, PdfRenderError } from "../errors.js";
|
|
19
20
|
import { PageSizes } from "../types.js";
|
|
@@ -83,8 +84,21 @@ async function finishExport(ctx, workbook, options) {
|
|
|
83
84
|
ensureAtLeastOnePage(allPages, documentOptions, sheets);
|
|
84
85
|
fixPageNumbers(allPages);
|
|
85
86
|
trackFontsForHeaders(allPages, fontManager);
|
|
87
|
+
// Track watermark fonts
|
|
88
|
+
const watermark = documentOptions.watermark;
|
|
89
|
+
if (watermark && watermark.type === "text") {
|
|
90
|
+
const wmFontFamily = watermark.fontFamily ?? "Helvetica";
|
|
91
|
+
const wmBold = watermark.bold ?? false;
|
|
92
|
+
const wmItalic = watermark.italic ?? false;
|
|
93
|
+
if (fontManager.hasEmbeddedFont()) {
|
|
94
|
+
fontManager.trackText(watermark.text);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
fontManager.ensureFont(resolvePdfFontName(wmFontFamily, wmBold, wmItalic));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
86
100
|
const fontObjectMap = fontManager.writeFontResources(writer);
|
|
87
|
-
const { pageObjNums, sheetFirstPage, pagesTreeObjNum } = await renderAllPages(allPages, fontManager, writer, fontObjectMap);
|
|
101
|
+
const { pageObjNums, sheetFirstPage, pagesTreeObjNum } = await renderAllPages(allPages, fontManager, writer, fontObjectMap, watermark);
|
|
88
102
|
return buildFinalPdf(writer, pageObjNums, pagesTreeObjNum, sheetFirstPage, documentOptions, workbook, options);
|
|
89
103
|
}
|
|
90
104
|
function ensureAtLeastOnePage(allPages, documentOptions, sheets) {
|
|
@@ -133,20 +147,20 @@ function trackFontsForHeaders(allPages, fontManager) {
|
|
|
133
147
|
}
|
|
134
148
|
}
|
|
135
149
|
}
|
|
136
|
-
async function renderAllPages(allPages, fontManager, writer, fontObjectMap) {
|
|
150
|
+
async function renderAllPages(allPages, fontManager, writer, fontObjectMap, watermark) {
|
|
137
151
|
const pageObjNums = [];
|
|
138
152
|
const pagesTreeObjNum = writer.allocObject();
|
|
139
153
|
const sheetFirstPage = new Map();
|
|
140
154
|
const totalPages = allPages.length;
|
|
141
155
|
for (let i = 0; i < allPages.length; i++) {
|
|
142
|
-
renderSinglePage(allPages[i], fontManager, writer, fontObjectMap, totalPages, pageObjNums, pagesTreeObjNum, sheetFirstPage);
|
|
156
|
+
renderSinglePage(allPages[i], fontManager, writer, fontObjectMap, totalPages, pageObjNums, pagesTreeObjNum, sheetFirstPage, watermark);
|
|
143
157
|
if (i < allPages.length - 1) {
|
|
144
158
|
await yieldToEventLoop();
|
|
145
159
|
}
|
|
146
160
|
}
|
|
147
161
|
return { pageObjNums, sheetFirstPage, pagesTreeObjNum };
|
|
148
162
|
}
|
|
149
|
-
function renderSinglePage(page, fontManager, writer, fontObjectMap, totalPages, pageObjNums, pagesTreeObjNum, sheetFirstPage) {
|
|
163
|
+
function renderSinglePage(page, fontManager, writer, fontObjectMap, totalPages, pageObjNums, pagesTreeObjNum, sheetFirstPage, watermark) {
|
|
150
164
|
try {
|
|
151
165
|
const { stream: contentStream, alphaValues } = renderPage(page, page.options, fontManager, totalPages);
|
|
152
166
|
// Handle images: create XObject Image entries and draw them
|
|
@@ -160,10 +174,46 @@ function renderSinglePage(page, fontManager, writer, fontObjectMap, totalPages,
|
|
|
160
174
|
contentStream.drawImage(imgName, img.rect.x, img.rect.y, img.rect.width, img.rect.height);
|
|
161
175
|
}
|
|
162
176
|
}
|
|
163
|
-
//
|
|
177
|
+
// --- Render watermark into a separate content stream ---
|
|
178
|
+
// PDF supports Contents as an array of stream references. The watermark stream
|
|
179
|
+
// is placed BEFORE the main content stream so it renders behind everything.
|
|
180
|
+
let watermarkContentObjNum;
|
|
181
|
+
const shouldApplyWatermark = watermark && isWatermarkApplicable(watermark, page);
|
|
182
|
+
if (shouldApplyWatermark) {
|
|
183
|
+
const wmContentStream = new PdfContentStream();
|
|
184
|
+
const wmResult = renderWatermark(wmContentStream, page, watermark, fontManager);
|
|
185
|
+
// Register watermark alpha values in the shared set
|
|
186
|
+
for (const alpha of wmResult.alphaValues) {
|
|
187
|
+
alphaValues.add(alpha);
|
|
188
|
+
}
|
|
189
|
+
// Register watermark image XObjects
|
|
190
|
+
for (const wmImg of wmResult.imageXObjects) {
|
|
191
|
+
const imgObjNum = writeImageXObject(writer, wmImg.data, wmImg.format);
|
|
192
|
+
imageXObjects.set(wmImg.name, imgObjNum);
|
|
193
|
+
}
|
|
194
|
+
// Write watermark content stream object
|
|
195
|
+
watermarkContentObjNum = writer.allocObject();
|
|
196
|
+
writer.addStreamObject(watermarkContentObjNum, new PdfDict(), wmContentStream);
|
|
197
|
+
}
|
|
198
|
+
// Add main content stream object
|
|
164
199
|
const contentObjNum = writer.allocObject();
|
|
165
|
-
|
|
166
|
-
|
|
200
|
+
writer.addStreamObject(contentObjNum, new PdfDict(), contentStream);
|
|
201
|
+
// Build Contents reference — array if watermark exists, single ref otherwise.
|
|
202
|
+
// placement "under" (default): watermark stream first, then content
|
|
203
|
+
// placement "over": content first, then watermark stream on top
|
|
204
|
+
let contentsRef;
|
|
205
|
+
if (watermarkContentObjNum) {
|
|
206
|
+
const placement = watermark?.placement ?? "under";
|
|
207
|
+
if (placement === "over") {
|
|
208
|
+
contentsRef = `[${pdfRef(contentObjNum)} ${pdfRef(watermarkContentObjNum)}]`;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
contentsRef = `[${pdfRef(watermarkContentObjNum)} ${pdfRef(contentObjNum)}]`;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
contentsRef = pdfRef(contentObjNum);
|
|
216
|
+
}
|
|
167
217
|
// Add resources dictionary object
|
|
168
218
|
const resourcesObjNum = writer.allocObject();
|
|
169
219
|
const fontDictStr = fontManager.buildFontDictString(fontObjectMap);
|
|
@@ -212,7 +262,7 @@ function renderSinglePage(page, fontManager, writer, fontObjectMap, totalPages,
|
|
|
212
262
|
parentRef: pagesTreeObjNum,
|
|
213
263
|
width: page.width,
|
|
214
264
|
height: page.height,
|
|
215
|
-
contentsRef:
|
|
265
|
+
contentsRef: contentsRef,
|
|
216
266
|
resourcesRef: resourcesObjNum,
|
|
217
267
|
annotRefs: annotRefs.length > 0 ? annotRefs : undefined
|
|
218
268
|
});
|
|
@@ -337,7 +387,8 @@ function resolveOptions(options, sheet) {
|
|
|
337
387
|
title: options?.title ?? "",
|
|
338
388
|
author: options?.author ?? "",
|
|
339
389
|
subject: options?.subject ?? "",
|
|
340
|
-
creator: options?.creator ?? "excelts"
|
|
390
|
+
creator: options?.creator ?? "excelts",
|
|
391
|
+
watermark: options?.watermark
|
|
341
392
|
};
|
|
342
393
|
}
|
|
343
394
|
/** Map PaperSize enum values to PDF page sizes. */
|
|
@@ -428,6 +479,28 @@ function buildOutlines(writer, sheetFirstPage, pageObjNums) {
|
|
|
428
479
|
return outlinesObjNum;
|
|
429
480
|
}
|
|
430
481
|
// =============================================================================
|
|
482
|
+
// Watermark Filtering
|
|
483
|
+
// =============================================================================
|
|
484
|
+
/**
|
|
485
|
+
* Check if a watermark should be applied to a specific page based on
|
|
486
|
+
* optional page number and sheet name filters.
|
|
487
|
+
*/
|
|
488
|
+
function isWatermarkApplicable(watermark, page) {
|
|
489
|
+
if (watermark.pages && watermark.pages.length > 0) {
|
|
490
|
+
if (!watermark.pages.includes(page.pageNumber)) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (watermark.sheets && watermark.sheets.length > 0) {
|
|
495
|
+
// Case-insensitive sheet name matching, consistent with the rest of the API
|
|
496
|
+
const sheetLower = page.sheetName.toLowerCase();
|
|
497
|
+
if (!watermark.sheets.some(s => s.toLowerCase() === sheetLower)) {
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return true;
|
|
502
|
+
}
|
|
503
|
+
// =============================================================================
|
|
431
504
|
// Image XObject
|
|
432
505
|
// =============================================================================
|
|
433
506
|
/**
|
|
@@ -444,7 +517,7 @@ function writeImageXObject(writer, data, format) {
|
|
|
444
517
|
*/
|
|
445
518
|
function writeJpegImageXObject(writer, data) {
|
|
446
519
|
const objNum = writer.allocObject();
|
|
447
|
-
const dims =
|
|
520
|
+
const dims = parseImageDimensions(data, "jpeg");
|
|
448
521
|
const dict = new PdfDict()
|
|
449
522
|
.set("Type", "/XObject")
|
|
450
523
|
.set("Subtype", "/Image")
|
|
@@ -486,39 +559,3 @@ function writePngImageXObject(writer, data) {
|
|
|
486
559
|
writer.addStreamObject(objNum, dict, png.pixels);
|
|
487
560
|
return objNum;
|
|
488
561
|
}
|
|
489
|
-
/**
|
|
490
|
-
* Extract width and height from a JPEG file header.
|
|
491
|
-
* Scans for SOF markers (SOF0-SOF3, SOF5-SOF7, SOF9-SOF11, SOF13-SOF15)
|
|
492
|
-
* which all share the same frame header layout.
|
|
493
|
-
* Handles 0xFF padding bytes per JPEG spec.
|
|
494
|
-
*/
|
|
495
|
-
function getJpegDimensions(data) {
|
|
496
|
-
let offset = 2; // skip SOI marker (0xFFD8)
|
|
497
|
-
while (offset < data.length - 1) {
|
|
498
|
-
// Skip any 0xFF fill bytes
|
|
499
|
-
while (offset < data.length && data[offset] === 0xff && data[offset + 1] === 0xff) {
|
|
500
|
-
offset++;
|
|
501
|
-
}
|
|
502
|
-
if (offset >= data.length - 1 || data[offset] !== 0xff) {
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
|
-
const marker = data[offset + 1];
|
|
506
|
-
// SOF markers: C0-C3, C5-C7, C9-CB, CD-CF (excluding C4=DHT, C8=JPG, CC=DAC)
|
|
507
|
-
const isSof = marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;
|
|
508
|
-
if (isSof) {
|
|
509
|
-
if (offset + 8 < data.length) {
|
|
510
|
-
const height = (data[offset + 5] << 8) | data[offset + 6];
|
|
511
|
-
const width = (data[offset + 7] << 8) | data[offset + 8];
|
|
512
|
-
return { width, height };
|
|
513
|
-
}
|
|
514
|
-
break;
|
|
515
|
-
}
|
|
516
|
-
// Skip segment: 2 byte marker + segment length (includes the 2 length bytes)
|
|
517
|
-
if (offset + 3 >= data.length) {
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
const segLen = (data[offset + 2] << 8) | data[offset + 3];
|
|
521
|
-
offset += 2 + segLen;
|
|
522
|
-
}
|
|
523
|
-
return { width: 1, height: 1 };
|
|
524
|
-
}
|