@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
|
@@ -15,6 +15,8 @@ export { DataValidations } from "./modules/excel/data-validations.js";
|
|
|
15
15
|
export { FormCheckbox } from "./modules/excel/form-control.js";
|
|
16
16
|
export * from "./modules/excel/enums.js";
|
|
17
17
|
export * from "./modules/excel/types.js";
|
|
18
|
+
export { createTextWatermarkImage } from "./modules/excel/utils/watermark-image.js";
|
|
19
|
+
export type { TextWatermarkImageOptions } from "./modules/excel/utils/watermark-image.js";
|
|
18
20
|
export type { PivotTable, PivotTableModel, PivotTableValue, PivotTableSource, CacheField, SharedItemValue, DataField, PivotTableSubtotal, RecordValue, ParsedCacheDefinition, ParsedCacheRecords } from "./modules/excel/pivot-table.js";
|
|
19
21
|
export type { FormCheckboxModel, FormCheckboxOptions, FormControlRange, FormControlAnchor } from "./modules/excel/form-control.js";
|
|
20
22
|
export { WorkbookWriter } from "./modules/excel/stream/workbook-writer.browser.js";
|
|
@@ -25,6 +25,8 @@ export * from "./modules/excel/enums.js";
|
|
|
25
25
|
// =============================================================================
|
|
26
26
|
// Export all type definitions from types.ts
|
|
27
27
|
export * from "./modules/excel/types.js";
|
|
28
|
+
// Watermark image generator utility
|
|
29
|
+
export { createTextWatermarkImage } from "./modules/excel/utils/watermark-image.js";
|
|
28
30
|
// =============================================================================
|
|
29
31
|
// Streaming Writer (Browser-compatible)
|
|
30
32
|
// Uses cross-platform base implementation without Node.js fs
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export { WorksheetWriter } from "./modules/excel/stream/worksheet-writer.js";
|
|
|
15
15
|
export { WorksheetReader } from "./modules/excel/stream/worksheet-reader.js";
|
|
16
16
|
export * from "./modules/excel/enums.js";
|
|
17
17
|
export * from "./modules/excel/types.js";
|
|
18
|
+
export { createTextWatermarkImage } from "./modules/excel/utils/watermark-image.js";
|
|
19
|
+
export type { TextWatermarkImageOptions } from "./modules/excel/utils/watermark-image.js";
|
|
18
20
|
export type { PivotTable, PivotTableModel, PivotTableValue, PivotTableSource, CacheField, SharedItemValue, DataField, PivotTableSubtotal, RecordValue, ParsedCacheDefinition, ParsedCacheRecords } from "./modules/excel/pivot-table.js";
|
|
19
21
|
export type { FormCheckboxModel, FormCheckboxOptions, FormControlRange, FormControlAnchor } from "./modules/excel/form-control.js";
|
|
20
22
|
export type { WorkbookReaderOptions, ParseEvent, SharedStringEvent, WorksheetReadyEvent, HyperlinksEvent } from "./modules/excel/stream/workbook-reader.js";
|
package/dist/browser/index.js
CHANGED
|
@@ -29,6 +29,8 @@ export * from "./modules/excel/enums.js";
|
|
|
29
29
|
// =============================================================================
|
|
30
30
|
// Export all type definitions from types.ts
|
|
31
31
|
export * from "./modules/excel/types.js";
|
|
32
|
+
// Watermark image generator utility
|
|
33
|
+
export { createTextWatermarkImage } from "./modules/excel/utils/watermark-image.js";
|
|
32
34
|
export { CsvParserStream, CsvFormatterStream, createCsvParserStream, createCsvFormatterStream } from "./modules/csv/stream/index.js";
|
|
33
35
|
// =============================================================================
|
|
34
36
|
// Additional Classes & Types
|
|
@@ -19,6 +19,19 @@ interface BackgroundModel {
|
|
|
19
19
|
type: "background";
|
|
20
20
|
imageId: string;
|
|
21
21
|
}
|
|
22
|
+
interface WatermarkModel {
|
|
23
|
+
type: "watermark";
|
|
24
|
+
imageId: string;
|
|
25
|
+
/** Opacity 0-1 for overlay mode */
|
|
26
|
+
opacity?: number;
|
|
27
|
+
}
|
|
28
|
+
interface HeaderImageModel {
|
|
29
|
+
type: "headerImage";
|
|
30
|
+
imageId: string;
|
|
31
|
+
headerWidth?: number;
|
|
32
|
+
headerHeight?: number;
|
|
33
|
+
applyTo?: "all" | "odd" | "even" | "first";
|
|
34
|
+
}
|
|
22
35
|
interface ImageRangeModel {
|
|
23
36
|
tl: AnchorModel;
|
|
24
37
|
br?: AnchorModel;
|
|
@@ -31,7 +44,7 @@ interface ImageModel {
|
|
|
31
44
|
hyperlinks?: ImageHyperlinks;
|
|
32
45
|
range: ImageRangeModel;
|
|
33
46
|
}
|
|
34
|
-
type Model = BackgroundModel | ImageModel;
|
|
47
|
+
type Model = BackgroundModel | ImageModel | WatermarkModel | HeaderImageModel;
|
|
35
48
|
type ImageModelInput = ModelInput;
|
|
36
49
|
interface RangeInput {
|
|
37
50
|
tl?: AnchorModel | {
|
|
@@ -51,15 +64,27 @@ interface ModelInput {
|
|
|
51
64
|
imageId: string;
|
|
52
65
|
range?: string | RangeInput | ImageRangeModel;
|
|
53
66
|
hyperlinks?: ImageHyperlinks;
|
|
67
|
+
opacity?: number;
|
|
68
|
+
headerWidth?: number;
|
|
69
|
+
headerHeight?: number;
|
|
70
|
+
applyTo?: "all" | "odd" | "even" | "first";
|
|
54
71
|
}
|
|
55
72
|
declare class Image {
|
|
56
73
|
readonly worksheet: Worksheet;
|
|
57
74
|
type?: string;
|
|
58
75
|
imageId?: string;
|
|
59
76
|
range?: ImageRange;
|
|
77
|
+
/** Opacity for watermark overlay mode (0-1). */
|
|
78
|
+
opacity?: number;
|
|
79
|
+
/** Header image width in points. */
|
|
80
|
+
headerWidth?: number;
|
|
81
|
+
/** Header image height in points. */
|
|
82
|
+
headerHeight?: number;
|
|
83
|
+
/** Header watermark applyTo setting. */
|
|
84
|
+
applyTo?: "all" | "odd" | "even" | "first";
|
|
60
85
|
constructor(worksheet: Worksheet, model?: ModelInput);
|
|
61
86
|
get model(): Model;
|
|
62
|
-
set model({ type, imageId, range, hyperlinks }: ModelInput);
|
|
87
|
+
set model({ type, imageId, range, hyperlinks, opacity, headerWidth, headerHeight, applyTo }: ModelInput);
|
|
63
88
|
clone(worksheet?: Worksheet): Image;
|
|
64
89
|
}
|
|
65
90
|
export { Image, type Model as ImageModel, type ImageModelInput };
|
|
@@ -15,6 +15,20 @@ class Image {
|
|
|
15
15
|
type: this.type,
|
|
16
16
|
imageId: this.imageId ?? ""
|
|
17
17
|
};
|
|
18
|
+
case "watermark":
|
|
19
|
+
return {
|
|
20
|
+
type: this.type,
|
|
21
|
+
imageId: this.imageId ?? "",
|
|
22
|
+
opacity: this.opacity
|
|
23
|
+
};
|
|
24
|
+
case "headerImage":
|
|
25
|
+
return {
|
|
26
|
+
type: this.type,
|
|
27
|
+
imageId: this.imageId ?? "",
|
|
28
|
+
headerWidth: this.headerWidth,
|
|
29
|
+
headerHeight: this.headerHeight,
|
|
30
|
+
applyTo: this.applyTo
|
|
31
|
+
};
|
|
18
32
|
case "image": {
|
|
19
33
|
const range = this.range;
|
|
20
34
|
if (!range) {
|
|
@@ -36,9 +50,13 @@ class Image {
|
|
|
36
50
|
throw new ImageError("Invalid Image Type");
|
|
37
51
|
}
|
|
38
52
|
}
|
|
39
|
-
set model({ type, imageId, range, hyperlinks }) {
|
|
53
|
+
set model({ type, imageId, range, hyperlinks, opacity, headerWidth, headerHeight, applyTo }) {
|
|
40
54
|
this.type = type;
|
|
41
55
|
this.imageId = imageId;
|
|
56
|
+
this.opacity = opacity;
|
|
57
|
+
this.headerWidth = headerWidth;
|
|
58
|
+
this.headerHeight = headerHeight;
|
|
59
|
+
this.applyTo = applyTo;
|
|
42
60
|
if (type === "image") {
|
|
43
61
|
if (typeof range === "string") {
|
|
44
62
|
const decoded = colCache.decode(range);
|
|
@@ -67,6 +85,10 @@ class Image {
|
|
|
67
85
|
const cloned = new Image(target);
|
|
68
86
|
cloned.type = this.type;
|
|
69
87
|
cloned.imageId = this.imageId;
|
|
88
|
+
cloned.opacity = this.opacity;
|
|
89
|
+
cloned.headerWidth = this.headerWidth;
|
|
90
|
+
cloned.headerHeight = this.headerHeight;
|
|
91
|
+
cloned.applyTo = this.applyTo;
|
|
70
92
|
if (this.range) {
|
|
71
93
|
cloned.range = {
|
|
72
94
|
tl: this.range.tl.clone(target),
|
|
@@ -3,7 +3,7 @@ import { Row } from "../row.js";
|
|
|
3
3
|
import type { Cell } from "../cell.js";
|
|
4
4
|
import { Column } from "../column.js";
|
|
5
5
|
import { DataValidations } from "../data-validations.js";
|
|
6
|
-
import type { RowBreak, ColBreak, PageSetup, HeaderFooter, WorksheetProperties, WorksheetView, WorksheetState, AutoFilter, WorksheetProtection, ConditionalFormattingOptions, AddImageRange } from "../types.js";
|
|
6
|
+
import type { RowBreak, ColBreak, PageSetup, HeaderFooter, WorksheetProperties, WorksheetView, WorksheetState, AutoFilter, WorksheetProtection, ConditionalFormattingOptions, AddImageRange, WatermarkOptions } from "../types.js";
|
|
7
7
|
interface WorksheetWriterOptions {
|
|
8
8
|
id: number;
|
|
9
9
|
name?: string;
|
|
@@ -97,6 +97,8 @@ declare class WorksheetWriter {
|
|
|
97
97
|
startedData: boolean;
|
|
98
98
|
private _background?;
|
|
99
99
|
private _headerRowCount?;
|
|
100
|
+
/** Watermark configuration */
|
|
101
|
+
private _watermark;
|
|
100
102
|
/** Drawing model — populated during commit if images were added */
|
|
101
103
|
private _drawing?;
|
|
102
104
|
/** Relationship Id - assigned by WorkbookWriter */
|
|
@@ -141,6 +143,19 @@ declare class WorksheetWriter {
|
|
|
141
143
|
* Each entry contains imageId and the normalised range (with native anchors).
|
|
142
144
|
*/
|
|
143
145
|
getImages(): ReadonlyArray<WriterImageModel>;
|
|
146
|
+
/**
|
|
147
|
+
* Add a watermark to the worksheet using an image from `WorkbookWriter.addImage()`.
|
|
148
|
+
* Supports overlay mode (DrawingML with transparency) and header mode (VML behind content).
|
|
149
|
+
*/
|
|
150
|
+
addWatermark(options: WatermarkOptions): void;
|
|
151
|
+
/**
|
|
152
|
+
* Get the current watermark configuration.
|
|
153
|
+
*/
|
|
154
|
+
getWatermark(): WatermarkOptions | null;
|
|
155
|
+
/**
|
|
156
|
+
* Remove the watermark from the worksheet.
|
|
157
|
+
*/
|
|
158
|
+
removeWatermark(): void;
|
|
144
159
|
/**
|
|
145
160
|
* Parse the user-supplied range into a normalised internal model
|
|
146
161
|
* mirroring what the regular Worksheet / Image class does.
|
|
@@ -151,6 +151,8 @@ class WorksheetWriter {
|
|
|
151
151
|
// auto filter
|
|
152
152
|
this.autoFilter = options.autoFilter ?? null;
|
|
153
153
|
this._media = [];
|
|
154
|
+
// watermark
|
|
155
|
+
this._watermark = null;
|
|
154
156
|
// worksheet protection
|
|
155
157
|
this.sheetProtection = null;
|
|
156
158
|
// start writing to stream now
|
|
@@ -448,6 +450,57 @@ class WorksheetWriter {
|
|
|
448
450
|
getImages() {
|
|
449
451
|
return this._media;
|
|
450
452
|
}
|
|
453
|
+
// =========================================================================
|
|
454
|
+
// Watermark
|
|
455
|
+
/**
|
|
456
|
+
* Add a watermark to the worksheet using an image from `WorkbookWriter.addImage()`.
|
|
457
|
+
* Supports overlay mode (DrawingML with transparency) and header mode (VML behind content).
|
|
458
|
+
*/
|
|
459
|
+
addWatermark(options) {
|
|
460
|
+
// Remove existing watermark entries (both stored type tags)
|
|
461
|
+
this._media = this._media.filter(m => m._watermarkTag !== true);
|
|
462
|
+
const opacity = options.opacity !== undefined ? Math.max(0, Math.min(1, options.opacity)) : 0.15;
|
|
463
|
+
this._watermark = {
|
|
464
|
+
imageId: String(options.imageId),
|
|
465
|
+
mode: options.mode ?? "overlay",
|
|
466
|
+
opacity,
|
|
467
|
+
headerWidth: options.headerWidth,
|
|
468
|
+
headerHeight: options.headerHeight,
|
|
469
|
+
applyTo: options.applyTo
|
|
470
|
+
};
|
|
471
|
+
if (this._watermark.mode === "overlay") {
|
|
472
|
+
// Coverage range is computed lazily during commit() via _resolveWatermarkRange()
|
|
473
|
+
const entry = {
|
|
474
|
+
type: "image",
|
|
475
|
+
imageId: String(options.imageId),
|
|
476
|
+
range: {
|
|
477
|
+
tl: { nativeCol: 0, nativeColOff: 0, nativeRow: 0, nativeRowOff: 0 },
|
|
478
|
+
br: { nativeCol: 100, nativeColOff: 0, nativeRow: 200, nativeRowOff: 0 },
|
|
479
|
+
editAs: "absolute"
|
|
480
|
+
},
|
|
481
|
+
// Internal tag for dedup — not part of the WriterImageModel type
|
|
482
|
+
_watermarkTag: true,
|
|
483
|
+
opacity
|
|
484
|
+
};
|
|
485
|
+
this._media.push(entry);
|
|
486
|
+
}
|
|
487
|
+
// Note: header mode for streaming writer is limited — the VML file generation
|
|
488
|
+
// happens in WorkbookWriter.addWorksheets(), which handles worksheet.headerImage.
|
|
489
|
+
// We store the config in _watermark and it's picked up by the commit path.
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Get the current watermark configuration.
|
|
493
|
+
*/
|
|
494
|
+
getWatermark() {
|
|
495
|
+
return this._watermark;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Remove the watermark from the worksheet.
|
|
499
|
+
*/
|
|
500
|
+
removeWatermark() {
|
|
501
|
+
this._watermark = null;
|
|
502
|
+
this._media = this._media.filter(m => m._watermarkTag !== true);
|
|
503
|
+
}
|
|
451
504
|
/**
|
|
452
505
|
* Parse the user-supplied range into a normalised internal model
|
|
453
506
|
* mirroring what the regular Worksheet / Image class does.
|
|
@@ -626,6 +679,21 @@ class WorksheetWriter {
|
|
|
626
679
|
if (this._media.length === 0) {
|
|
627
680
|
return;
|
|
628
681
|
}
|
|
682
|
+
// Resolve watermark coverage range from actual worksheet dimensions
|
|
683
|
+
// (at commit time, all rows have been flushed so _dimensions is accurate)
|
|
684
|
+
for (const entry of this._media) {
|
|
685
|
+
if (entry._watermarkTag) {
|
|
686
|
+
const dims = this._dimensions.model;
|
|
687
|
+
const maxCol = dims ? Math.max(dims.right ?? 100, 100) : 100;
|
|
688
|
+
const maxRow = dims ? Math.max(dims.bottom ?? 200, 200) : 200;
|
|
689
|
+
entry.range.br = {
|
|
690
|
+
nativeCol: maxCol,
|
|
691
|
+
nativeColOff: 0,
|
|
692
|
+
nativeRow: maxRow,
|
|
693
|
+
nativeRowOff: 0
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
}
|
|
629
697
|
// Build the drawing model from the stored images.
|
|
630
698
|
// The drawing XML will be generated later by WorkbookWriterBase.addDrawings().
|
|
631
699
|
const drawingName = `drawing${this.id}`;
|
|
@@ -368,6 +368,78 @@ export interface ImageHyperlinkValue {
|
|
|
368
368
|
hyperlink: string;
|
|
369
369
|
tooltip?: string;
|
|
370
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Watermark placement mode in the Excel worksheet.
|
|
373
|
+
*
|
|
374
|
+
* - `"overlay"` — Places the watermark image as a DrawingML picture on top of cells.
|
|
375
|
+
* Visible on screen AND when printed. Supports transparency via `<a:alphaModFix>`.
|
|
376
|
+
* Users can move/delete the watermark unless the sheet is protected.
|
|
377
|
+
*
|
|
378
|
+
* - `"header"` — Places the watermark image in the page header using VML.
|
|
379
|
+
* Renders behind cell content. Visible in Page Layout view and Print Preview.
|
|
380
|
+
* Cannot be accidentally moved/deleted. The standard "true watermark" approach.
|
|
381
|
+
*/
|
|
382
|
+
export type WatermarkMode = "overlay" | "header";
|
|
383
|
+
/**
|
|
384
|
+
* Options for adding a watermark to a worksheet.
|
|
385
|
+
*
|
|
386
|
+
* @example Overlay watermark (visible on screen + prints):
|
|
387
|
+
* ```typescript
|
|
388
|
+
* const imgId = workbook.addImage({ buffer: pngData, extension: "png" });
|
|
389
|
+
* worksheet.addWatermark({
|
|
390
|
+
* imageId: imgId,
|
|
391
|
+
* mode: "overlay",
|
|
392
|
+
* opacity: 0.15
|
|
393
|
+
* });
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
* @example Header watermark (behind content, prints correctly):
|
|
397
|
+
* ```typescript
|
|
398
|
+
* const imgId = workbook.addImage({ buffer: pngData, extension: "png" });
|
|
399
|
+
* worksheet.addWatermark({
|
|
400
|
+
* imageId: imgId,
|
|
401
|
+
* mode: "header"
|
|
402
|
+
* });
|
|
403
|
+
* ```
|
|
404
|
+
*/
|
|
405
|
+
export interface WatermarkOptions {
|
|
406
|
+
/** Image ID obtained from `workbook.addImage()`. */
|
|
407
|
+
imageId: string | number;
|
|
408
|
+
/**
|
|
409
|
+
* Watermark placement mode.
|
|
410
|
+
* @default "overlay"
|
|
411
|
+
*/
|
|
412
|
+
mode?: WatermarkMode;
|
|
413
|
+
/**
|
|
414
|
+
* Opacity for overlay mode (0 = fully transparent, 1 = fully opaque).
|
|
415
|
+
* Expressed as a percentage in OOXML (e.g. 0.15 = 15000 out of 100000).
|
|
416
|
+
* Only applies to `"overlay"` mode. In `"header"` mode, transparency
|
|
417
|
+
* must be baked into the image itself (use a PNG with alpha channel).
|
|
418
|
+
* @default 0.15
|
|
419
|
+
*/
|
|
420
|
+
opacity?: number;
|
|
421
|
+
/**
|
|
422
|
+
* Image width in points (for "header" mode VML rendering).
|
|
423
|
+
* @default 467.25
|
|
424
|
+
*/
|
|
425
|
+
headerWidth?: number;
|
|
426
|
+
/**
|
|
427
|
+
* Image height in points (for "header" mode VML rendering).
|
|
428
|
+
* @default 311.25
|
|
429
|
+
*/
|
|
430
|
+
headerHeight?: number;
|
|
431
|
+
/**
|
|
432
|
+
* Which header sections to apply the watermark to (only for "header" mode).
|
|
433
|
+
*
|
|
434
|
+
* - `"all"` — applies to oddHeader, evenHeader, and firstHeader
|
|
435
|
+
* - `"odd"` — applies only to oddHeader (standard pages)
|
|
436
|
+
* - `"even"` — applies only to evenHeader
|
|
437
|
+
* - `"first"` — applies only to firstHeader
|
|
438
|
+
*
|
|
439
|
+
* @default "all"
|
|
440
|
+
*/
|
|
441
|
+
applyTo?: "all" | "odd" | "even" | "first";
|
|
442
|
+
}
|
|
371
443
|
export type Location = {
|
|
372
444
|
top: number;
|
|
373
445
|
left: number;
|
|
@@ -12,6 +12,8 @@ interface DrawingAnchor {
|
|
|
12
12
|
tooltip?: string;
|
|
13
13
|
rId: string;
|
|
14
14
|
};
|
|
15
|
+
/** Alpha modulation for transparency (OOXML percentage, e.g. 15000 = 15%). */
|
|
16
|
+
alphaModFix?: number;
|
|
15
17
|
};
|
|
16
18
|
range: any;
|
|
17
19
|
}
|
|
@@ -32,6 +34,8 @@ interface ImageMedium {
|
|
|
32
34
|
hyperlink?: string;
|
|
33
35
|
tooltip?: string;
|
|
34
36
|
};
|
|
37
|
+
/** Opacity 0-1 for watermark overlay mode. */
|
|
38
|
+
opacity?: number;
|
|
35
39
|
}
|
|
36
40
|
/**
|
|
37
41
|
* Resolves a media filename into the drawing-level relative target path.
|
|
@@ -64,6 +64,11 @@ export function buildDrawingAnchorsAndRels(media, existingRels, options) {
|
|
|
64
64
|
},
|
|
65
65
|
range: medium.range
|
|
66
66
|
};
|
|
67
|
+
// Pass through watermark opacity as alphaModFix
|
|
68
|
+
if (medium.opacity !== undefined) {
|
|
69
|
+
const clamped = Math.max(0, Math.min(1, medium.opacity));
|
|
70
|
+
anchor.picture.alphaModFix = Math.round(clamped * 100000);
|
|
71
|
+
}
|
|
67
72
|
// Handle image hyperlinks
|
|
68
73
|
if (medium.hyperlinks && medium.hyperlinks.hyperlink) {
|
|
69
74
|
const rIdHyperlink = options.nextRId(rels);
|
|
@@ -21,6 +21,7 @@ export declare function isBinaryEntryPath(path: string): boolean;
|
|
|
21
21
|
export declare function getDrawingNameFromPath(path: string): string | undefined;
|
|
22
22
|
export declare function getDrawingNameFromRelsPath(path: string): string | undefined;
|
|
23
23
|
export declare function getVmlDrawingNameFromPath(path: string): string | undefined;
|
|
24
|
+
export declare function getVmlDrawingHFNameFromPath(path: string): string | undefined;
|
|
24
25
|
export declare function getCommentsIndexFromPath(path: string): string | undefined;
|
|
25
26
|
export declare function getTableNameFromPath(path: string): string | undefined;
|
|
26
27
|
export declare function getPivotTableNameFromPath(path: string): string | undefined;
|
|
@@ -37,6 +38,8 @@ export declare function worksheetRelTarget(sheetId: number | string): string;
|
|
|
37
38
|
export declare function commentsPath(sheetId: number | string): string;
|
|
38
39
|
export declare function commentsPathFromName(commentName: string): string;
|
|
39
40
|
export declare function vmlDrawingPath(sheetId: number | string): string;
|
|
41
|
+
export declare function vmlDrawingHFPath(sheetId: number | string): string;
|
|
42
|
+
export declare function vmlDrawingHFRelsPath(sheetId: number | string): string;
|
|
40
43
|
export declare function tablePath(target: string): string;
|
|
41
44
|
export declare function drawingPath(drawingName: string): string;
|
|
42
45
|
export declare function drawingRelsPath(drawingName: string): string;
|
|
@@ -56,6 +59,7 @@ export declare const OOXML_REL_TARGETS: {
|
|
|
56
59
|
export declare function pivotCacheDefinitionRelTargetFromWorkbook(n: number | string): string;
|
|
57
60
|
export declare function commentsRelTargetFromWorksheet(sheetId: number | string): string;
|
|
58
61
|
export declare function vmlDrawingRelTargetFromWorksheet(sheetId: number | string): string;
|
|
62
|
+
export declare function vmlDrawingHFRelTargetFromWorksheet(sheetId: number | string): string;
|
|
59
63
|
export declare function drawingRelTargetFromWorksheet(drawingName: string): string;
|
|
60
64
|
export declare function vmlDrawingRelTargetFromWorksheetName(vmlName: string): string;
|
|
61
65
|
export declare function commentsRelTargetFromWorksheetName(commentName: string): string;
|
|
@@ -17,6 +17,7 @@ const mediaFilenameRegex = /^xl\/media\/([a-zA-Z0-9]+[.][a-zA-Z0-9]{3,4})$/;
|
|
|
17
17
|
const drawingXmlRegex = /^xl\/drawings\/(drawing\d+)[.]xml$/;
|
|
18
18
|
const drawingRelsXmlRegex = /^xl\/drawings\/_rels\/(drawing\d+)[.]xml[.]rels$/;
|
|
19
19
|
const vmlDrawingRegex = /^xl\/drawings\/(vmlDrawing\d+)[.]vml$/;
|
|
20
|
+
const vmlDrawingHFRegex = /^xl\/drawings\/(vmlDrawingHF\d+)[.]vml$/;
|
|
20
21
|
const commentsXmlRegex = /^xl\/comments(\d+)[.]xml$/;
|
|
21
22
|
const tableXmlRegex = /^xl\/tables\/(table\d+)[.]xml$/;
|
|
22
23
|
const pivotTableXmlRegex = /^xl\/pivotTables\/(pivotTable\d+)[.]xml$/;
|
|
@@ -72,6 +73,10 @@ export function getVmlDrawingNameFromPath(path) {
|
|
|
72
73
|
const match = vmlDrawingRegex.exec(path);
|
|
73
74
|
return match ? match[1] : undefined;
|
|
74
75
|
}
|
|
76
|
+
export function getVmlDrawingHFNameFromPath(path) {
|
|
77
|
+
const match = vmlDrawingHFRegex.exec(path);
|
|
78
|
+
return match ? match[1] : undefined;
|
|
79
|
+
}
|
|
75
80
|
export function getCommentsIndexFromPath(path) {
|
|
76
81
|
const match = commentsXmlRegex.exec(path);
|
|
77
82
|
return match ? match[1] : undefined;
|
|
@@ -129,6 +134,12 @@ export function commentsPathFromName(commentName) {
|
|
|
129
134
|
export function vmlDrawingPath(sheetId) {
|
|
130
135
|
return `xl/drawings/vmlDrawing${sheetId}.vml`;
|
|
131
136
|
}
|
|
137
|
+
export function vmlDrawingHFPath(sheetId) {
|
|
138
|
+
return `xl/drawings/vmlDrawingHF${sheetId}.vml`;
|
|
139
|
+
}
|
|
140
|
+
export function vmlDrawingHFRelsPath(sheetId) {
|
|
141
|
+
return `xl/drawings/_rels/vmlDrawingHF${sheetId}.vml.rels`;
|
|
142
|
+
}
|
|
132
143
|
export function tablePath(target) {
|
|
133
144
|
return `xl/tables/${target}`;
|
|
134
145
|
}
|
|
@@ -178,6 +189,10 @@ export function vmlDrawingRelTargetFromWorksheet(sheetId) {
|
|
|
178
189
|
// Target inside xl/worksheets/_rels/sheetN.xml.rels (base: xl/worksheets/)
|
|
179
190
|
return `../drawings/vmlDrawing${sheetId}.vml`;
|
|
180
191
|
}
|
|
192
|
+
export function vmlDrawingHFRelTargetFromWorksheet(sheetId) {
|
|
193
|
+
// Target inside xl/worksheets/_rels/sheetN.xml.rels (base: xl/worksheets/)
|
|
194
|
+
return `../drawings/vmlDrawingHF${sheetId}.vml`;
|
|
195
|
+
}
|
|
181
196
|
export function drawingRelTargetFromWorksheet(drawingName) {
|
|
182
197
|
// Target inside xl/worksheets/_rels/sheetN.xml.rels (base: xl/worksheets/)
|
|
183
198
|
return `../drawings/${drawingName}.xml`;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-dependency text-to-PNG watermark image generator.
|
|
3
|
+
*
|
|
4
|
+
* Renders text into a semi-transparent PNG suitable for use as an Excel watermark.
|
|
5
|
+
* Uses a built-in bitmap font for ASCII characters — no Canvas or external fonts required.
|
|
6
|
+
* PNG data is deflate-compressed using the archive module's built-in compressor.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const png = createTextWatermarkImage("CONFIDENTIAL", {
|
|
11
|
+
* fontSize: 48,
|
|
12
|
+
* color: { r: 128, g: 128, b: 128 },
|
|
13
|
+
* opacity: 40,
|
|
14
|
+
* rotation: -45
|
|
15
|
+
* });
|
|
16
|
+
* const imgId = workbook.addImage({ buffer: png, extension: "png" });
|
|
17
|
+
* worksheet.addWatermark({ imageId: imgId });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Options for text watermark image generation.
|
|
22
|
+
*/
|
|
23
|
+
export interface TextWatermarkImageOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Approximate font size in pixels (glyph height).
|
|
26
|
+
* The built-in bitmap font is 8px tall; values larger than 8 are achieved by
|
|
27
|
+
* integer scaling. e.g. fontSize 48 → 6x scale.
|
|
28
|
+
* @default 48
|
|
29
|
+
*/
|
|
30
|
+
fontSize?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Text color as RGB (0-255 each).
|
|
33
|
+
* @default { r: 128, g: 128, b: 128 }
|
|
34
|
+
*/
|
|
35
|
+
color?: {
|
|
36
|
+
r: number;
|
|
37
|
+
g: number;
|
|
38
|
+
b: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Opacity as a percentage (0 = fully transparent, 100 = fully opaque).
|
|
42
|
+
*
|
|
43
|
+
* Note: this is a **0–100 percentage** used when rendering the PNG image pixels.
|
|
44
|
+
* It is different from `WatermarkOptions.opacity` (which is 0–1) used by
|
|
45
|
+
* `worksheet.addWatermark()` for DrawingML `alphaModFix`.
|
|
46
|
+
*
|
|
47
|
+
* @default 40
|
|
48
|
+
*/
|
|
49
|
+
opacity?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Rotation in degrees (positive = counter-clockwise).
|
|
52
|
+
* @default -45
|
|
53
|
+
*/
|
|
54
|
+
rotation?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Padding in pixels around the text (before rotation).
|
|
57
|
+
* @default 20
|
|
58
|
+
*/
|
|
59
|
+
padding?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Generate a PNG image containing watermark text.
|
|
63
|
+
*
|
|
64
|
+
* The image has an alpha channel so the watermark is semi-transparent.
|
|
65
|
+
* Works in both Node.js and browsers with zero dependencies.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createTextWatermarkImage(text: string, options?: TextWatermarkImageOptions): Uint8Array;
|