@polotno/pdf-export 0.1.37 → 0.1.39

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 (52) hide show
  1. package/README.md +61 -8
  2. package/lib/index.d.ts +66 -8
  3. package/lib/index.js +25 -145
  4. package/package.json +17 -18
  5. package/lib/browser-entry.d.ts +0 -7
  6. package/lib/browser-entry.js +0 -11
  7. package/lib/compare-render.d.ts +0 -1
  8. package/lib/compare-render.js +0 -185
  9. package/lib/core/index.d.ts +0 -26
  10. package/lib/core/index.js +0 -87
  11. package/lib/figure.d.ts +0 -10
  12. package/lib/figure.js +0 -54
  13. package/lib/filters.d.ts +0 -2
  14. package/lib/filters.js +0 -163
  15. package/lib/ghostscript.d.ts +0 -21
  16. package/lib/ghostscript.js +0 -132
  17. package/lib/group.d.ts +0 -5
  18. package/lib/group.js +0 -5
  19. package/lib/image.d.ts +0 -38
  20. package/lib/image.js +0 -279
  21. package/lib/line.d.ts +0 -10
  22. package/lib/line.js +0 -66
  23. package/lib/platform/adapter.d.ts +0 -37
  24. package/lib/platform/adapter.js +0 -13
  25. package/lib/platform/browser-polyfill.d.ts +0 -1
  26. package/lib/platform/browser-polyfill.js +0 -5
  27. package/lib/platform/browser.d.ts +0 -7
  28. package/lib/platform/browser.js +0 -145
  29. package/lib/platform/node.d.ts +0 -7
  30. package/lib/platform/node.js +0 -142
  31. package/lib/spot-colors.d.ts +0 -38
  32. package/lib/spot-colors.js +0 -141
  33. package/lib/svg-render.d.ts +0 -9
  34. package/lib/svg-render.js +0 -63
  35. package/lib/svg.d.ts +0 -12
  36. package/lib/svg.js +0 -224
  37. package/lib/text/fonts.d.ts +0 -16
  38. package/lib/text/fonts.js +0 -82
  39. package/lib/text/index.d.ts +0 -8
  40. package/lib/text/index.js +0 -42
  41. package/lib/text/layout.d.ts +0 -22
  42. package/lib/text/layout.js +0 -522
  43. package/lib/text/parser.d.ts +0 -46
  44. package/lib/text/parser.js +0 -415
  45. package/lib/text/render.d.ts +0 -8
  46. package/lib/text/render.js +0 -237
  47. package/lib/text/types.d.ts +0 -91
  48. package/lib/text/types.js +0 -1
  49. package/lib/text.d.ts +0 -49
  50. package/lib/text.js +0 -1277
  51. package/lib/utils.d.ts +0 -16
  52. package/lib/utils.js +0 -124
package/lib/group.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export interface GroupElement {
2
- children: any[];
3
- [key: string]: any;
4
- }
5
- export declare function renderGroup(doc: any, element: GroupElement, renderElement: Function, fonts: Record<string, boolean>, attrs: any, cache: any): Promise<void>;
package/lib/group.js DELETED
@@ -1,5 +0,0 @@
1
- export async function renderGroup(doc, element, renderElement, fonts, attrs, cache) {
2
- for (const child of element.children) {
3
- await renderElement({ doc, element: child, fonts, attrs, cache });
4
- }
5
- }
package/lib/image.d.ts DELETED
@@ -1,38 +0,0 @@
1
- import { ImageCache } from './utils.js';
2
- export interface ImageElement {
3
- src: string;
4
- width: number;
5
- height: number;
6
- cropX: number;
7
- cropY: number;
8
- cropWidth: number;
9
- cropHeight: number;
10
- clipSrc?: string;
11
- type?: string;
12
- opacity?: number;
13
- flipX?: boolean;
14
- flipY?: boolean;
15
- borderSize?: number;
16
- borderColor?: string;
17
- brightnessEnabled: boolean;
18
- brightness: number;
19
- grayscaleEnabled: boolean;
20
- sepiaEnabled: boolean;
21
- blurEnabled: boolean;
22
- blurRadius: number;
23
- filters: Record<string, ShapeFilter>;
24
- shadowEnabled?: boolean;
25
- shadowBlur?: number;
26
- shadowOffsetX?: number;
27
- shadowOffsetY?: number;
28
- shadowColor?: string;
29
- shadowOpacity?: number;
30
- }
31
- type ShapeFilter = {
32
- intensity: number;
33
- };
34
- export declare function getProcessedImageKey(element: ImageElement): string;
35
- export declare function cropImage(src: string, element: ImageElement, cache?: ImageCache | null): Promise<string>;
36
- export declare function clipImage(src: string, element: ImageElement, cache?: ImageCache | null): Promise<string>;
37
- export declare function renderImage(doc: PDFKit.PDFDocument, element: ImageElement, cache?: ImageCache | null): Promise<void>;
38
- export {};
package/lib/image.js DELETED
@@ -1,279 +0,0 @@
1
- import { loadImage, PIXEL_RATIO, srcToBuffer, parseColor, } from './utils.js';
2
- import Canvas from 'canvas';
3
- import fs from 'fs';
4
- import path from 'path';
5
- import os from 'os';
6
- import crypto from 'crypto';
7
- import Konva from 'konva';
8
- import { elementFilterToKonva } from './filters.js';
9
- async function applyFlip(image, element) {
10
- const { flipX, flipY } = element;
11
- if (!flipX && !flipY) {
12
- return image;
13
- }
14
- if (!image || !image.width || !image.height) {
15
- return null;
16
- }
17
- const canvas = new Canvas.Canvas(image.width, image.height);
18
- const ctx = canvas.getContext('2d');
19
- let x = flipX ? -canvas.width : 0;
20
- let y = flipY ? -canvas.height : 0;
21
- ctx.scale(flipX ? -1 : 1, flipY ? -1 : 1);
22
- ctx.drawImage(image, x, y, canvas.width, canvas.height);
23
- return canvas;
24
- }
25
- // Helper to create cache key for processed images
26
- export function getProcessedImageKey(element) {
27
- return JSON.stringify({
28
- src: element.src,
29
- width: element.width,
30
- height: element.height,
31
- cropX: element.cropX,
32
- cropY: element.cropY,
33
- cropWidth: element.cropWidth,
34
- cropHeight: element.cropHeight,
35
- clipSrc: element.clipSrc,
36
- brightnessEnabled: element.brightnessEnabled,
37
- brightness: element.brightness,
38
- grayscaleEnabled: element.grayscaleEnabled,
39
- sepiaEnabled: element.sepiaEnabled,
40
- blurEnabled: element.blurEnabled,
41
- blurRadius: element.blurRadius,
42
- filters: element.filters,
43
- });
44
- }
45
- export async function cropImage(src, element, cache = null) {
46
- let image = await loadImage(src);
47
- // Apply flip transformations first
48
- image = await applyFlip(image, element);
49
- if (!image) {
50
- return null;
51
- }
52
- const canvas = Canvas.createCanvas(element.width * PIXEL_RATIO, element.height * PIXEL_RATIO);
53
- const ctx = canvas.getContext('2d');
54
- let { cropX, cropY } = element;
55
- const availableWidth = image.width * element.cropWidth;
56
- const availableHeight = image.height * element.cropHeight;
57
- const aspectRatio = element.width / element.height;
58
- let cropAbsoluteWidth;
59
- let cropAbsoluteHeight;
60
- const imageRatio = availableWidth / availableHeight;
61
- const allowScale = element.type === 'svg';
62
- if (allowScale) {
63
- cropAbsoluteWidth = availableWidth;
64
- cropAbsoluteHeight = availableHeight;
65
- }
66
- else if (aspectRatio >= imageRatio) {
67
- cropAbsoluteWidth = availableWidth;
68
- cropAbsoluteHeight = availableWidth / aspectRatio;
69
- }
70
- else {
71
- cropAbsoluteWidth = availableHeight * aspectRatio;
72
- cropAbsoluteHeight = availableHeight;
73
- }
74
- ctx.drawImage(image, cropX * image.width, cropY * image.height, cropAbsoluteWidth, cropAbsoluteHeight, 0, 0, canvas.width, canvas.height);
75
- return canvas.toDataURL('image/png');
76
- }
77
- export async function clipImage(src, element, cache = null) {
78
- const image = await loadImage(src, cache);
79
- const clipImage = await loadImage(element.clipSrc, cache);
80
- const canvas = Canvas.createCanvas(element.width, element.height);
81
- const ctx = canvas.getContext('2d');
82
- ctx.drawImage(image, 0, 0, element.width, element.height);
83
- const clipCanvas = Canvas.createCanvas(element.width, element.height);
84
- const clipCtx = clipCanvas.getContext('2d');
85
- clipCtx.drawImage(clipImage, 0, 0, element.width, element.height);
86
- ctx.globalCompositeOperation = 'destination-in';
87
- ctx.drawImage(clipCanvas, 0, 0);
88
- ctx.globalCompositeOperation = 'source-over';
89
- return canvas.toDataURL('image/png');
90
- }
91
- async function applyFilter(src, element, cache = null) {
92
- const image = await loadImage(src, cache);
93
- const canvas = Canvas.createCanvas(element.width * PIXEL_RATIO, element.height * PIXEL_RATIO);
94
- const ctx = canvas.getContext('2d');
95
- ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
96
- const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
97
- const data = imageData.data;
98
- if (element.brightnessEnabled) {
99
- Konva.Filters.Brighten.bind({
100
- brightness: () => element.brightness,
101
- })({ data });
102
- }
103
- // grayscale
104
- if (element.grayscaleEnabled) {
105
- Konva.Filters.Grayscale.bind({})({ data });
106
- }
107
- // sepia
108
- if (element.sepiaEnabled) {
109
- Konva.Filters.Sepia.bind({})({ data });
110
- }
111
- // blur
112
- if (element.blurEnabled) {
113
- Konva.Filters.Blur.bind({
114
- blurRadius: () => element.blurRadius,
115
- })({ data });
116
- }
117
- // filters
118
- if (element.filters) {
119
- Object.entries(element.filters).forEach(([type, effect]) => {
120
- const filter = elementFilterToKonva[type];
121
- if (filter) {
122
- filter(effect.intensity).bind({})({ data });
123
- }
124
- });
125
- }
126
- ctx.putImageData(imageData, 0, 0);
127
- return canvas.toDataURL('image/png');
128
- }
129
- function applyBorder(doc, element) {
130
- if (element.borderSize > 0) {
131
- const borderColor = parseColor(element.borderColor).keyword || 'black';
132
- doc
133
- .rect(element.borderSize / 2, element.borderSize / 2, element.width - element.borderSize, element.height - element.borderSize)
134
- .lineWidth(element.borderSize)
135
- .strokeColor(borderColor)
136
- .stroke();
137
- }
138
- }
139
- function saveToTempFile(buffer, key, cache) {
140
- if (cache) {
141
- if (!cache.imageFiles) {
142
- cache.imageFiles = new Map();
143
- }
144
- if (!cache.tempDir) {
145
- cache.tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pdfkit-images-'));
146
- }
147
- // Create a unique filename based on cache key hash
148
- const hash = crypto.createHash('md5').update(key).digest('hex');
149
- const filePath = path.join(cache.tempDir, `${hash}.png`);
150
- // Write buffer to file
151
- fs.writeFileSync(filePath, buffer);
152
- cache.imageFiles.set(key, filePath);
153
- return filePath;
154
- }
155
- else {
156
- return buffer;
157
- }
158
- }
159
- async function getShadowImage(src, element, cache) {
160
- const image = await loadImage(src, cache);
161
- const { shadowBlur, shadowColor, shadowOpacity } = element;
162
- // Shadow blur in Konva is standard. In Canvas it is standard.
163
- // We need to scale it by PIXEL_RATIO as our canvas is scaled.
164
- const ratio = PIXEL_RATIO;
165
- const blur = (shadowBlur || 0) * ratio;
166
- // Padding.
167
- const padding = blur * 4 + 20; // Sufficient padding
168
- const width = image.width + padding * 2;
169
- const height = image.height + padding * 2;
170
- const canvas = Canvas.createCanvas(width, height);
171
- const ctx = canvas.getContext('2d');
172
- // Parse color
173
- const parsed = parseColor(shadowColor || 'black');
174
- const opacity = shadowOpacity !== undefined ? shadowOpacity : 1;
175
- const r = parsed.rgb[0];
176
- const g = parsed.rgb[1];
177
- const b = parsed.rgb[2];
178
- const a = opacity;
179
- const colorString = `rgba(${r},${g},${b},${a})`;
180
- ctx.shadowColor = colorString;
181
- ctx.shadowBlur = blur;
182
- // We want the shadow to appear at (padding, padding) relative to canvas.
183
- // We draw the image at (padding - OFFSET, padding - OFFSET)
184
- // And set shadowOffset to (OFFSET, OFFSET).
185
- // OFFSET should be large enough to move image out of view.
186
- const OFFSET = 10000;
187
- ctx.shadowOffsetX = OFFSET;
188
- ctx.shadowOffsetY = OFFSET;
189
- // Draw image
190
- ctx.drawImage(image, padding - OFFSET, padding - OFFSET, image.width, image.height);
191
- return {
192
- src: canvas.toDataURL('image/png'),
193
- padding: padding / ratio, // return padding in original units (points)
194
- width: width / ratio,
195
- height: height / ratio,
196
- };
197
- }
198
- export async function renderImage(doc, element, cache = null) {
199
- // Check if we have a cached processed version
200
- const cacheKey = getProcessedImageKey(element);
201
- let src = null;
202
- const hasCachedFile = cache && cache.imageFiles && cache.imageFiles.has(cacheKey);
203
- if (hasCachedFile) {
204
- src = cache.imageFiles.get(cacheKey);
205
- }
206
- else if (cache && cache.processedImages.has(cacheKey)) {
207
- src = cache.processedImages.get(cacheKey);
208
- }
209
- else {
210
- src = await cropImage(element.src, element, cache);
211
- if (element.clipSrc) {
212
- src = await clipImage(src, element, cache);
213
- }
214
- src = await applyFilter(src, element, cache);
215
- // Cache the processed result
216
- if (cache && src) {
217
- cache.processedImages.set(cacheKey, src);
218
- }
219
- }
220
- if (element.shadowEnabled && src) {
221
- const shadowKey = cacheKey +
222
- '_shadow_' +
223
- JSON.stringify({
224
- blur: element.shadowBlur,
225
- color: element.shadowColor,
226
- opacity: element.shadowOpacity,
227
- });
228
- let shadowPadding = 0;
229
- let shadowW = 0;
230
- let shadowH = 0;
231
- if (cache && cache.imageFiles && cache.imageFiles.has(shadowKey)) {
232
- const filePath = cache.imageFiles.get(shadowKey);
233
- // Recalculate padding/dimensions as we don't cache them
234
- const ratio = PIXEL_RATIO;
235
- const blur = (element.shadowBlur || 0) * ratio;
236
- shadowPadding = (blur * 4 + 20) / ratio;
237
- shadowW = element.width + shadowPadding * 2;
238
- shadowH = element.height + shadowPadding * 2;
239
- console.log('✓ Using cached shadow file:', path.basename(filePath));
240
- doc.image(filePath, (element.shadowOffsetX || 0) - shadowPadding, (element.shadowOffsetY || 0) - shadowPadding, {
241
- width: shadowW,
242
- height: shadowH,
243
- });
244
- }
245
- else {
246
- const shadowResult = await getShadowImage(src, element, cache);
247
- const shadowSrc = shadowResult.src;
248
- shadowPadding = shadowResult.padding;
249
- shadowW = shadowResult.width;
250
- shadowH = shadowResult.height;
251
- if (shadowSrc) {
252
- const buffer = await srcToBuffer(shadowSrc, cache);
253
- const filePath = saveToTempFile(buffer, shadowKey, cache);
254
- doc.image(filePath, (element.shadowOffsetX || 0) - shadowPadding, (element.shadowOffsetY || 0) - shadowPadding, {
255
- width: shadowW,
256
- height: shadowH,
257
- });
258
- }
259
- }
260
- }
261
- if (src) {
262
- if (hasCachedFile) {
263
- console.log('✓ Using cached image file:', path.basename(src));
264
- doc.image(src, 0, 0, {
265
- width: element.width,
266
- height: element.height,
267
- });
268
- }
269
- else {
270
- const buffer = await srcToBuffer(src, cache);
271
- const filePath = saveToTempFile(buffer, cacheKey, cache);
272
- doc.image(filePath, 0, 0, {
273
- width: element.width,
274
- height: element.height,
275
- });
276
- }
277
- applyBorder(doc, element);
278
- }
279
- }
package/lib/line.d.ts DELETED
@@ -1,10 +0,0 @@
1
- export interface LineElement {
2
- height: number;
3
- width: number;
4
- color: string;
5
- opacity: number;
6
- dash?: number[];
7
- startHead?: string;
8
- endHead?: string;
9
- }
10
- export declare function lineToPDF(doc: any, element: LineElement): void;
package/lib/line.js DELETED
@@ -1,66 +0,0 @@
1
- import { Util } from 'konva/lib/Util.js';
2
- function rgbToHex({ r, g, b }) {
3
- // Ensure each value is within the valid range
4
- r = Math.max(0, Math.min(255, r));
5
- g = Math.max(0, Math.min(255, g));
6
- b = Math.max(0, Math.min(255, b));
7
- // Convert each value to a 2-digit hexadecimal string
8
- const hexR = r.toString(16).padStart(2, '0');
9
- const hexG = g.toString(16).padStart(2, '0');
10
- const hexB = b.toString(16).padStart(2, '0');
11
- // Return the concatenated hex string
12
- return `#${hexR}${hexG}${hexB}`;
13
- }
14
- function getLineHead({ element, type, doc }) {
15
- doc.lineWidth(element.height);
16
- doc.lineCap('round');
17
- doc.lineJoin('round');
18
- doc.opacity(element.opacity);
19
- const rgba = Util.colorToRGBA(element.color);
20
- const fillColor = rgbToHex(rgba);
21
- if (type === 'arrow') {
22
- doc
23
- .moveTo(element.height * 3, -element.height * 2)
24
- .lineTo(0, 0)
25
- .lineTo(element.height * 3, element.height * 2);
26
- doc.stroke();
27
- return;
28
- }
29
- else if (type === 'triangle') {
30
- doc.polygon([element.height * 3, -element.height * 2], [0, 0], [element.height * 3, element.height * 2]);
31
- }
32
- else if (type === 'bar') {
33
- doc.polygon([0, -element.height * 2], [0, 0], [0, element.height * 2]);
34
- }
35
- else if (type === 'circle') {
36
- doc.circle(element.height * 2, 0, element.height * 2);
37
- }
38
- else if (type === 'square') {
39
- doc.rect(0, -element.height * 2, element.height * 4, element.height * 4);
40
- }
41
- else {
42
- return;
43
- }
44
- doc.fillAndStroke(fillColor, fillColor);
45
- }
46
- export function lineToPDF(doc, element) {
47
- doc.translate(0, element.height / 2);
48
- doc.lineWidth(element.height);
49
- doc.moveTo(0, 0);
50
- doc.lineTo(element.width, 0);
51
- if (element.dash && element.dash.length > 0) {
52
- doc.dash(element.dash.map((dash) => dash * element.height));
53
- }
54
- const rgba = Util.colorToRGBA(element.color);
55
- doc.strokeColor(rgbToHex(rgba));
56
- doc.stroke();
57
- if (element.dash && element.dash.length > 0) {
58
- doc.undash();
59
- }
60
- getLineHead({ element, doc: doc, type: element.startHead });
61
- getLineHead({
62
- element,
63
- doc: doc.translate(element.width, 0).rotate(180),
64
- type: element.endHead,
65
- });
66
- }
@@ -1,37 +0,0 @@
1
- export interface FetchResponse {
2
- ok: boolean;
3
- status: number;
4
- statusText: string;
5
- headers: Headers;
6
- arrayBuffer(): Promise<ArrayBuffer>;
7
- text(): Promise<string>;
8
- json(): Promise<any>;
9
- }
10
- export interface CanvasLike {
11
- width: number;
12
- height: number;
13
- getContext(type: '2d'): any;
14
- toDataURL(type?: string, quality?: any): string;
15
- }
16
- export interface ImageLike {
17
- width: number;
18
- height: number;
19
- [key: string]: any;
20
- }
21
- export interface PDFContext<TOutput = unknown, TFinalizeOptions = unknown> {
22
- doc: any;
23
- finalize(options?: TFinalizeOptions): Promise<TOutput>;
24
- }
25
- export interface PlatformAdapter<TOutput = unknown, TFinalizeOptions = unknown> {
26
- fetch(input: string, init?: RequestInit): Promise<FetchResponse>;
27
- loadImage(src: string): Promise<ImageLike>;
28
- createCanvas(width: number, height: number): CanvasLike;
29
- createPDFContext(options: any): PDFContext<TOutput, TFinalizeOptions>;
30
- registerFont(doc: any, name: string, data: Uint8Array): void | Promise<void>;
31
- encodeBase64(data: Uint8Array): string;
32
- decodeBase64(value: string): Uint8Array;
33
- embedImage(doc: any, data: Uint8Array | string, x: number, y: number, options: any, mimeType?: string): void | Promise<void>;
34
- }
35
- export declare function setPlatformAdapter(adapter: PlatformAdapter): void;
36
- export declare function hasPlatformAdapter(): boolean;
37
- export declare function getPlatformAdapter(): PlatformAdapter;
@@ -1,13 +0,0 @@
1
- let currentAdapter = null;
2
- export function setPlatformAdapter(adapter) {
3
- currentAdapter = adapter;
4
- }
5
- export function hasPlatformAdapter() {
6
- return currentAdapter !== null;
7
- }
8
- export function getPlatformAdapter() {
9
- if (!currentAdapter) {
10
- throw new Error('Platform adapter is not configured.');
11
- }
12
- return currentAdapter;
13
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,5 +0,0 @@
1
- const globalScope = globalThis;
2
- if (typeof globalScope.global === 'undefined') {
3
- globalScope.global = globalScope;
4
- }
5
- export {};
@@ -1,7 +0,0 @@
1
- import type { PlatformAdapter } from './adapter.js';
2
- interface FinalizeOptions {
3
- fileName?: string;
4
- attrs?: any;
5
- }
6
- export declare function createBrowserAdapter(): PlatformAdapter<Blob, FinalizeOptions>;
7
- export {};
@@ -1,145 +0,0 @@
1
- import PDFDocument from 'pdfkit/js/pdfkit.standalone.js';
2
- import SVGtoPDF from 'svg-to-pdfkit';
3
- import { Buffer } from 'buffer';
4
- function attachAddSVG(doc) {
5
- const existing = doc.addSVG;
6
- if (!existing) {
7
- doc.addSVG = function (svg, x, y, options) {
8
- SVGtoPDF(this, svg, x, y, options);
9
- return this;
10
- };
11
- }
12
- }
13
- function arrayBufferToBase64(buffer) {
14
- let binary = '';
15
- const chunkSize = 8192;
16
- for (let i = 0; i < buffer.length; i += chunkSize) {
17
- const chunk = buffer.subarray(i, i + chunkSize);
18
- binary += String.fromCharCode(...chunk);
19
- }
20
- return btoa(binary);
21
- }
22
- function base64ToUint8Array(value) {
23
- const binary = atob(value);
24
- const bytes = new Uint8Array(binary.length);
25
- for (let i = 0; i < binary.length; i++) {
26
- bytes[i] = binary.charCodeAt(i);
27
- }
28
- return bytes;
29
- }
30
- function loadImageElement(src) {
31
- return new Promise((resolve, reject) => {
32
- const img = new Image();
33
- if (!src.startsWith('data:')) {
34
- img.crossOrigin = 'anonymous';
35
- }
36
- img.onload = () => resolve(img);
37
- img.onerror = (error) => reject(error);
38
- img.src = src;
39
- });
40
- }
41
- async function loadImageFromSource(src) {
42
- if (src.startsWith('data:')) {
43
- return loadImageElement(src);
44
- }
45
- const fetchImpl = globalThis.fetch?.bind(globalThis);
46
- if (!fetchImpl) {
47
- throw new Error('Global fetch is not available in this environment.');
48
- }
49
- const response = await fetchImpl(src, { mode: 'cors' });
50
- if (!response.ok) {
51
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
52
- }
53
- const blob = await response.blob();
54
- const objectUrl = URL.createObjectURL(blob);
55
- try {
56
- return await loadImageElement(objectUrl);
57
- }
58
- finally {
59
- URL.revokeObjectURL(objectUrl);
60
- }
61
- }
62
- export function createBrowserAdapter() {
63
- return {
64
- async fetch(input, init) {
65
- const fetchImpl = globalThis.fetch?.bind(globalThis);
66
- if (!fetchImpl) {
67
- throw new Error('Global fetch is not available in this environment.');
68
- }
69
- return (await fetchImpl(input, init));
70
- },
71
- async loadImage(src) {
72
- return loadImageFromSource(src);
73
- },
74
- createCanvas(width, height) {
75
- const canvas = document.createElement('canvas');
76
- canvas.width = width;
77
- canvas.height = height;
78
- return canvas;
79
- },
80
- createPDFContext(options) {
81
- const doc = new PDFDocument(options);
82
- attachAddSVG(doc);
83
- const blobParts = [];
84
- const appendTypedArray = (view) => {
85
- blobParts.push(view.slice());
86
- };
87
- doc.on('data', (chunk) => {
88
- if (chunk instanceof Uint8Array) {
89
- appendTypedArray(chunk);
90
- }
91
- else if (Array.isArray(chunk)) {
92
- appendTypedArray(new Uint8Array(chunk));
93
- }
94
- else if (typeof chunk === 'string') {
95
- const encoder = new TextEncoder();
96
- appendTypedArray(encoder.encode(chunk));
97
- }
98
- else if (chunk?.buffer instanceof ArrayBuffer) {
99
- appendTypedArray(new Uint8Array(chunk.buffer));
100
- }
101
- });
102
- const resultPromise = new Promise((resolve, reject) => {
103
- doc.on('end', () => {
104
- try {
105
- resolve(new Blob(blobParts, { type: 'application/pdf' }));
106
- }
107
- catch (error) {
108
- reject(error);
109
- }
110
- });
111
- doc.on('error', reject);
112
- });
113
- const finalize = async (options) => {
114
- if (options?.attrs?.pdfx1a) {
115
- console.warn('PDF/X-1a conversion is not supported in the browser runtime.');
116
- }
117
- return resultPromise;
118
- };
119
- return {
120
- doc,
121
- finalize,
122
- };
123
- },
124
- registerFont(doc, name, data) {
125
- const buffer = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
126
- doc.registerFont(name, buffer);
127
- },
128
- encodeBase64(data) {
129
- return arrayBufferToBase64(data);
130
- },
131
- decodeBase64(value) {
132
- return base64ToUint8Array(value);
133
- },
134
- embedImage(doc, data, x, y, options, mimeType) {
135
- if (typeof data === 'string') {
136
- doc.image(data, x, y, options);
137
- return;
138
- }
139
- const mime = mimeType || 'image/png';
140
- const base64 = arrayBufferToBase64(data);
141
- const dataUrl = `data:${mime};base64,${base64}`;
142
- doc.image(dataUrl, x, y, options);
143
- },
144
- };
145
- }
@@ -1,7 +0,0 @@
1
- import type { PlatformAdapter } from './adapter.js';
2
- interface FinalizeOptions {
3
- fileName?: string;
4
- attrs?: any;
5
- }
6
- export declare function createNodeAdapter(): PlatformAdapter<Uint8Array, FinalizeOptions>;
7
- export {};