image-exporter 1.2.2 → 1.3.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 +32 -3
- package/dist/capture/capture-element.d.ts +2 -1
- package/dist/capture/capture-element.d.ts.map +1 -1
- package/dist/capture/capture.dom.test.d.ts +2 -0
- package/dist/capture/capture.dom.test.d.ts.map +1 -0
- package/dist/capture/copy-to-clipboard.d.ts +13 -0
- package/dist/capture/copy-to-clipboard.d.ts.map +1 -0
- package/dist/capture/copy-to-clipboard.dom.test.d.ts +2 -0
- package/dist/capture/copy-to-clipboard.dom.test.d.ts.map +1 -0
- package/dist/capture/cors-cleanup.dom.test.d.ts +2 -0
- package/dist/capture/cors-cleanup.dom.test.d.ts.map +1 -0
- package/dist/capture/data-url-to-blob.d.ts +9 -0
- package/dist/capture/data-url-to-blob.d.ts.map +1 -0
- package/dist/capture/data-url-to-blob.node.test.d.ts +2 -0
- package/dist/capture/data-url-to-blob.node.test.d.ts.map +1 -0
- package/dist/capture/dedup-consistency.node.test.d.ts +2 -0
- package/dist/capture/dedup-consistency.node.test.d.ts.map +1 -0
- package/dist/capture/determine-total-elements.d.ts +7 -3
- package/dist/capture/determine-total-elements.d.ts.map +1 -1
- package/dist/capture/determine-total-elements.dom.test.d.ts +2 -0
- package/dist/capture/determine-total-elements.dom.test.d.ts.map +1 -0
- package/dist/capture/download-images.d.ts +8 -0
- package/dist/capture/download-images.d.ts.map +1 -1
- package/dist/capture/get-image-options.dom.test.d.ts +2 -0
- package/dist/capture/get-image-options.dom.test.d.ts.map +1 -0
- package/dist/capture/handle-filenames.d.ts +5 -6
- package/dist/capture/handle-filenames.d.ts.map +1 -1
- package/dist/capture/index.d.ts.map +1 -1
- package/dist/capture/make-unique.d.ts +14 -0
- package/dist/capture/make-unique.d.ts.map +1 -0
- package/dist/capture/make-unique.node.test.d.ts +2 -0
- package/dist/capture/make-unique.node.test.d.ts.map +1 -0
- package/dist/index.browser.js +16 -16
- package/dist/index.browser.js.map +20 -17
- package/dist/index.cjs +198 -125
- package/dist/index.cjs.map +20 -17
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +198 -125
- package/dist/index.js.map +20 -17
- package/dist/logger.d.ts +5 -5
- package/dist/logger.d.ts.map +1 -1
- package/dist/types.d.ts +81 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +27 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { capture } from "./capture";
|
|
2
2
|
import { downloadImages } from "./capture/download-images";
|
|
3
|
+
import { copyImageToClipboard } from "./capture/copy-to-clipboard";
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
imageExporter: typeof capture;
|
|
7
|
+
imageExporterDownload: typeof downloadImages;
|
|
8
|
+
imageExporterCopyToClipboard: typeof copyImageToClipboard;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
3
11
|
/** Exports for use as an imported package */
|
|
4
|
-
export { capture, downloadImages };
|
|
12
|
+
export { capture, downloadImages, copyImageToClipboard };
|
|
5
13
|
/** Type exports */
|
|
6
|
-
export type { ImageOptions, Config, ParsedImageOptions, Image, Label, Format, Scale, Quality, IncludeScaleInLabel, LoggingLevel, } from "./types";
|
|
14
|
+
export type { ImageOptions, Config, ParsedImageOptions, Image, Output, Label, Format, Scale, Quality, IncludeScaleInLabel, LoggingLevel, } from "./types";
|
|
7
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,aAAa,EAAE,OAAO,OAAO,CAAC;QAC9B,qBAAqB,EAAE,OAAO,cAAc,CAAC;QAC7C,4BAA4B,EAAE,OAAO,oBAAoB,CAAC;KAC3D;CACF;AASD,6CAA6C;AAC7C,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;AAEzD,mBAAmB;AACnB,YAAY,EACV,YAAY,EACZ,MAAM,EACN,kBAAkB,EAClB,KAAK,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,KAAK,EACL,OAAO,EACP,mBAAmB,EACnB,YAAY,GACb,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,39 +4,60 @@ var __defProp = Object.defineProperty;
|
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
function __accessProp(key) {
|
|
8
|
+
return this[key];
|
|
9
|
+
}
|
|
10
|
+
var __toESMCache_node;
|
|
11
|
+
var __toESMCache_esm;
|
|
7
12
|
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
+
var canCache = mod != null && typeof mod === "object";
|
|
14
|
+
if (canCache) {
|
|
15
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
+
var cached = cache.get(mod);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
8
20
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
21
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
22
|
for (let key of __getOwnPropNames(mod))
|
|
11
23
|
if (!__hasOwnProp.call(to, key))
|
|
12
24
|
__defProp(to, key, {
|
|
13
|
-
get: (
|
|
25
|
+
get: __accessProp.bind(mod, key),
|
|
14
26
|
enumerable: true
|
|
15
27
|
});
|
|
28
|
+
if (canCache)
|
|
29
|
+
cache.set(mod, to);
|
|
16
30
|
return to;
|
|
17
31
|
};
|
|
18
|
-
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
19
32
|
var __toCommonJS = (from) => {
|
|
20
|
-
var entry = __moduleCache.get(from), desc;
|
|
33
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
21
34
|
if (entry)
|
|
22
35
|
return entry;
|
|
23
36
|
entry = __defProp({}, "__esModule", { value: true });
|
|
24
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
38
|
+
for (var key of __getOwnPropNames(from))
|
|
39
|
+
if (!__hasOwnProp.call(entry, key))
|
|
40
|
+
__defProp(entry, key, {
|
|
41
|
+
get: __accessProp.bind(from, key),
|
|
42
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
43
|
+
});
|
|
44
|
+
}
|
|
29
45
|
__moduleCache.set(from, entry);
|
|
30
46
|
return entry;
|
|
31
47
|
};
|
|
48
|
+
var __moduleCache;
|
|
32
49
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
50
|
+
var __returnValue = (v) => v;
|
|
51
|
+
function __exportSetter(name, newValue) {
|
|
52
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
53
|
+
}
|
|
33
54
|
var __export = (target, all) => {
|
|
34
55
|
for (var name in all)
|
|
35
56
|
__defProp(target, name, {
|
|
36
57
|
get: all[name],
|
|
37
58
|
enumerable: true,
|
|
38
59
|
configurable: true,
|
|
39
|
-
set: (
|
|
60
|
+
set: __exportSetter.bind(all, name)
|
|
40
61
|
});
|
|
41
62
|
};
|
|
42
63
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
@@ -53,7 +74,7 @@ __export(exports_buffer, {
|
|
|
53
74
|
default: () => buffer_default,
|
|
54
75
|
constants: () => constants,
|
|
55
76
|
btoa: () => btoa,
|
|
56
|
-
atob: () =>
|
|
77
|
+
atob: () => atob2,
|
|
57
78
|
INSPECT_MAX_BYTES: () => INSPECT_MAX_BYTES,
|
|
58
79
|
File: () => File,
|
|
59
80
|
Buffer: () => Buffer2,
|
|
@@ -726,7 +747,7 @@ function notimpl(name) {
|
|
|
726
747
|
throw Error(name + " is not implemented for node:buffer browser polyfill");
|
|
727
748
|
};
|
|
728
749
|
}
|
|
729
|
-
var lookup, revLookup, code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", i, len, customInspectSymbol, INSPECT_MAX_BYTES = 50, kMaxLength = 2147483647, kStringMaxLength = 536870888, btoa,
|
|
750
|
+
var lookup, revLookup, code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", i, len, customInspectSymbol, INSPECT_MAX_BYTES = 50, kMaxLength = 2147483647, kStringMaxLength = 536870888, btoa, atob2, File, Blob2, constants, ERR_BUFFER_OUT_OF_BOUNDS, ERR_INVALID_ARG_TYPE, ERR_OUT_OF_RANGE, MAX_ARGUMENTS_LENGTH = 4096, INVALID_BASE64_RE, hexSliceLookupTable, resolveObjectURL, isUtf8, isAscii = (str) => {
|
|
730
751
|
for (let char of str)
|
|
731
752
|
if (char.charCodeAt(0) > 127)
|
|
732
753
|
return false;
|
|
@@ -741,7 +762,7 @@ var init_buffer = __esm(() => {
|
|
|
741
762
|
revLookup[95] = 63;
|
|
742
763
|
customInspectSymbol = typeof Symbol === "function" && typeof Symbol.for === "function" ? Symbol.for("nodejs.util.inspect.custom") : null;
|
|
743
764
|
btoa = globalThis.btoa;
|
|
744
|
-
|
|
765
|
+
atob2 = globalThis.atob;
|
|
745
766
|
File = globalThis.File;
|
|
746
767
|
Blob2 = globalThis.Blob;
|
|
747
768
|
constants = { MAX_LENGTH: kMaxLength, MAX_STRING_LENGTH: kStringMaxLength };
|
|
@@ -12532,7 +12553,7 @@ var require_zipEntries = __commonJS((exports, module) => {
|
|
|
12532
12553
|
if (this.centralDirRecords !== this.files.length) {
|
|
12533
12554
|
if (this.centralDirRecords !== 0 && this.files.length === 0) {
|
|
12534
12555
|
throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length);
|
|
12535
|
-
}
|
|
12556
|
+
}
|
|
12536
12557
|
}
|
|
12537
12558
|
},
|
|
12538
12559
|
readEndOfCentral: function() {
|
|
@@ -12705,38 +12726,38 @@ var require_lib = __commonJS((exports, module) => {
|
|
|
12705
12726
|
module.exports = JSZip;
|
|
12706
12727
|
});
|
|
12707
12728
|
|
|
12729
|
+
// src/capture/make-unique.ts
|
|
12730
|
+
function makeUnique(fileName, seen) {
|
|
12731
|
+
if (!seen.has(fileName)) {
|
|
12732
|
+
seen.add(fileName);
|
|
12733
|
+
return fileName;
|
|
12734
|
+
}
|
|
12735
|
+
const lastDot = fileName.lastIndexOf(".");
|
|
12736
|
+
const base = lastDot !== -1 ? fileName.slice(0, lastDot) : fileName;
|
|
12737
|
+
const extension = lastDot !== -1 ? fileName.slice(lastDot) : "";
|
|
12738
|
+
const match = base.match(/-(\d+)$/);
|
|
12739
|
+
let stem = base;
|
|
12740
|
+
let counter = 2;
|
|
12741
|
+
if (match) {
|
|
12742
|
+
stem = base.slice(0, -match[0].length);
|
|
12743
|
+
counter = parseInt(match[1], 10) + 1;
|
|
12744
|
+
}
|
|
12745
|
+
let candidate = `${stem}-${counter}${extension}`;
|
|
12746
|
+
while (seen.has(candidate)) {
|
|
12747
|
+
counter++;
|
|
12748
|
+
candidate = `${stem}-${counter}${extension}`;
|
|
12749
|
+
}
|
|
12750
|
+
seen.add(candidate);
|
|
12751
|
+
return candidate;
|
|
12752
|
+
}
|
|
12753
|
+
|
|
12708
12754
|
// src/capture/handle-filenames.ts
|
|
12709
|
-
function handleFileNames(imageOptions,
|
|
12755
|
+
function handleFileNames(imageOptions, seen) {
|
|
12710
12756
|
let proposedFilename = imageOptions.label;
|
|
12711
12757
|
if (imageOptions.includeScaleInLabel)
|
|
12712
12758
|
proposedFilename += `_@${imageOptions.scale}x`;
|
|
12713
|
-
|
|
12714
|
-
proposedFilename
|
|
12715
|
-
if (!filenames.includes(proposedFilename)) {
|
|
12716
|
-
filenames.push(proposedFilename);
|
|
12717
|
-
return proposedFilename;
|
|
12718
|
-
}
|
|
12719
|
-
const numberPattern = /-(\d+)$/;
|
|
12720
|
-
const match = proposedFilename.match(numberPattern);
|
|
12721
|
-
if (match) {
|
|
12722
|
-
const baseFilename = proposedFilename.replace(numberPattern, "");
|
|
12723
|
-
let counter = parseInt(match[1], 10);
|
|
12724
|
-
while (filenames.includes(`${baseFilename}-${counter}${extension}`)) {
|
|
12725
|
-
counter++;
|
|
12726
|
-
}
|
|
12727
|
-
const newFilename = `${baseFilename}-${counter}${extension}`;
|
|
12728
|
-
filenames.push(newFilename);
|
|
12729
|
-
return newFilename;
|
|
12730
|
-
} else {
|
|
12731
|
-
const baseFilename = proposedFilename.replace(extension, "");
|
|
12732
|
-
let counter = 2;
|
|
12733
|
-
while (filenames.includes(`${baseFilename}-${counter}${extension}`)) {
|
|
12734
|
-
counter++;
|
|
12735
|
-
}
|
|
12736
|
-
const newFilename = `${baseFilename}-${counter}${extension}`;
|
|
12737
|
-
filenames.push(newFilename);
|
|
12738
|
-
return newFilename;
|
|
12739
|
-
}
|
|
12759
|
+
proposedFilename += `.${imageOptions.format}`;
|
|
12760
|
+
return makeUnique(proposedFilename, seen);
|
|
12740
12761
|
}
|
|
12741
12762
|
|
|
12742
12763
|
// node_modules/modern-screenshot/dist/index.mjs
|
|
@@ -14238,18 +14259,20 @@ async function domToWebp(node, options) {
|
|
|
14238
14259
|
}
|
|
14239
14260
|
|
|
14240
14261
|
// src/capture/capture-element.ts
|
|
14241
|
-
async function captureElement(element, imageOptions,
|
|
14262
|
+
async function captureElement(element, imageOptions, seen, screenshotOptions) {
|
|
14263
|
+
let cleanUpBackground = false;
|
|
14242
14264
|
try {
|
|
14243
14265
|
let dataURL = "";
|
|
14244
|
-
|
|
14266
|
+
const userFilter = screenshotOptions?.filter;
|
|
14267
|
+
const htmlToImageOptions = {
|
|
14268
|
+
...screenshotOptions,
|
|
14245
14269
|
quality: imageOptions.quality,
|
|
14246
14270
|
scale: imageOptions.scale,
|
|
14247
|
-
filter
|
|
14271
|
+
filter: (node) => filter(node) && (userFilter ? userFilter(node) : true)
|
|
14248
14272
|
};
|
|
14249
14273
|
const styles = getComputedStyle(element);
|
|
14250
14274
|
const backgroundColor = styles.backgroundColor;
|
|
14251
14275
|
const backgroundImage = styles.backgroundImage;
|
|
14252
|
-
let cleanUpBackground = false;
|
|
14253
14276
|
if (backgroundColor === "rgba(0, 0, 0, 0)" && backgroundImage === "none" && imageOptions.format === "jpg") {
|
|
14254
14277
|
element.style.backgroundColor = "#FFFFFF";
|
|
14255
14278
|
cleanUpBackground = true;
|
|
@@ -14268,17 +14291,17 @@ async function captureElement(element, imageOptions, filenames) {
|
|
|
14268
14291
|
dataURL = await domToWebp(element, htmlToImageOptions);
|
|
14269
14292
|
break;
|
|
14270
14293
|
}
|
|
14271
|
-
if (cleanUpBackground) {
|
|
14272
|
-
element.style.backgroundColor = "";
|
|
14273
|
-
element.style.backgroundImage = "";
|
|
14274
|
-
}
|
|
14275
14294
|
return {
|
|
14276
14295
|
dataURL,
|
|
14277
|
-
fileName: handleFileNames(imageOptions,
|
|
14296
|
+
fileName: handleFileNames(imageOptions, seen)
|
|
14278
14297
|
};
|
|
14279
14298
|
} catch (error) {
|
|
14280
|
-
|
|
14281
|
-
|
|
14299
|
+
throw new Error(`ImageExporter: failed to capture element as ${imageOptions.format}`, { cause: error });
|
|
14300
|
+
} finally {
|
|
14301
|
+
if (cleanUpBackground) {
|
|
14302
|
+
element.style.backgroundColor = "";
|
|
14303
|
+
element.style.backgroundImage = "";
|
|
14304
|
+
}
|
|
14282
14305
|
}
|
|
14283
14306
|
}
|
|
14284
14307
|
var filter = (node) => {
|
|
@@ -14315,7 +14338,7 @@ async function downloadImages(images, userConfig = defaultConfig) {
|
|
|
14315
14338
|
const uniqueImages = ensureUniqueFileNames(images);
|
|
14316
14339
|
if (uniqueImages.length === 1) {
|
|
14317
14340
|
const image = uniqueImages[0];
|
|
14318
|
-
triggerDownload(image.dataURL, image.fileName);
|
|
14341
|
+
triggerDownload(image.blob ?? image.dataURL, image.fileName);
|
|
14319
14342
|
} else if (uniqueImages.length > 1) {
|
|
14320
14343
|
const imagesBlob = await zipUpImages(uniqueImages);
|
|
14321
14344
|
if (imagesBlob)
|
|
@@ -14339,8 +14362,12 @@ async function zipUpImages(images) {
|
|
|
14339
14362
|
const zip = new import_jszip.default;
|
|
14340
14363
|
try {
|
|
14341
14364
|
images.forEach((image) => {
|
|
14342
|
-
|
|
14343
|
-
|
|
14365
|
+
if (image.blob) {
|
|
14366
|
+
zip.file(image.fileName, image.blob);
|
|
14367
|
+
} else {
|
|
14368
|
+
const content = image.dataURL.split(",")[1];
|
|
14369
|
+
zip.file(image.fileName, content, { base64: true });
|
|
14370
|
+
}
|
|
14344
14371
|
});
|
|
14345
14372
|
} catch (error) {
|
|
14346
14373
|
console.error("Image Exporter - Error adding images to ZIP:", error);
|
|
@@ -14365,27 +14392,15 @@ function parseLabel(config) {
|
|
|
14365
14392
|
}
|
|
14366
14393
|
}
|
|
14367
14394
|
function ensureUniqueFileNames(images) {
|
|
14368
|
-
const
|
|
14395
|
+
const seen = new Set;
|
|
14369
14396
|
return images.map((image) => {
|
|
14370
|
-
const
|
|
14371
|
-
|
|
14372
|
-
const baseName = lastDotIndex !== -1 ? fileName.substring(0, lastDotIndex) : fileName;
|
|
14373
|
-
const extension = lastDotIndex !== -1 ? fileName.substring(lastDotIndex) : "";
|
|
14374
|
-
if (!fileNameMap.has(fileName)) {
|
|
14375
|
-
fileNameMap.set(fileName, 1);
|
|
14376
|
-
return image;
|
|
14377
|
-
}
|
|
14378
|
-
const count = fileNameMap.get(fileName) + 1;
|
|
14379
|
-
fileNameMap.set(fileName, count);
|
|
14380
|
-
const newFileName = `${baseName}-${count}${extension}`;
|
|
14381
|
-
return {
|
|
14382
|
-
...image,
|
|
14383
|
-
fileName: newFileName
|
|
14384
|
-
};
|
|
14397
|
+
const fileName = makeUnique(image.fileName, seen);
|
|
14398
|
+
return fileName === image.fileName ? image : { ...image, fileName };
|
|
14385
14399
|
});
|
|
14386
14400
|
}
|
|
14387
14401
|
|
|
14388
14402
|
// src/logger.ts
|
|
14403
|
+
var hasWindow = typeof window !== "undefined";
|
|
14389
14404
|
var log = {
|
|
14390
14405
|
info: (...messages) => logAction(messages, "info"),
|
|
14391
14406
|
error: (...messages) => logAction(messages, "error"),
|
|
@@ -14421,16 +14436,18 @@ async function logAction(messages, type = "info") {
|
|
|
14421
14436
|
console.groupEnd();
|
|
14422
14437
|
break;
|
|
14423
14438
|
}
|
|
14424
|
-
if (windowLogging)
|
|
14439
|
+
if (windowLogging && hasWindow)
|
|
14425
14440
|
window.imageExporterLogs.push({ message: combinedMessage, type });
|
|
14426
14441
|
}
|
|
14427
14442
|
async function logProgress(progress, total) {
|
|
14428
|
-
if (windowLogging) {
|
|
14443
|
+
if (windowLogging && hasWindow) {
|
|
14429
14444
|
window.imageExporterProgress.push([progress, total]);
|
|
14430
14445
|
}
|
|
14431
14446
|
}
|
|
14432
|
-
|
|
14433
|
-
window.
|
|
14447
|
+
if (hasWindow) {
|
|
14448
|
+
window.imageExporterLogs = [];
|
|
14449
|
+
window.imageExporterProgress = [];
|
|
14450
|
+
}
|
|
14434
14451
|
|
|
14435
14452
|
// src/cors-proxy/is-valid-url.ts
|
|
14436
14453
|
function isValidUrl(string) {
|
|
@@ -14443,7 +14460,7 @@ function isValidUrl(string) {
|
|
|
14443
14460
|
return false;
|
|
14444
14461
|
}
|
|
14445
14462
|
return true;
|
|
14446
|
-
} catch
|
|
14463
|
+
} catch {
|
|
14447
14464
|
return false;
|
|
14448
14465
|
}
|
|
14449
14466
|
}
|
|
@@ -14452,7 +14469,7 @@ function isValidUrl(string) {
|
|
|
14452
14469
|
async function proxyCSS(config) {
|
|
14453
14470
|
const stylesheetElements = document.querySelectorAll('link[rel="stylesheet"]');
|
|
14454
14471
|
log.verbose("stylesheet elements to proxy", stylesheetElements.length);
|
|
14455
|
-
for (
|
|
14472
|
+
for (const stylesheetElement of stylesheetElements) {
|
|
14456
14473
|
const stylesheetURL = stylesheetElement.getAttribute("href");
|
|
14457
14474
|
if (!stylesheetURL)
|
|
14458
14475
|
continue;
|
|
@@ -14466,7 +14483,7 @@ async function proxyCSS(config) {
|
|
|
14466
14483
|
const proxiedURL = config.corsProxyBaseUrl + encodeURIComponent(stylesheetURL);
|
|
14467
14484
|
try {
|
|
14468
14485
|
const response = await fetch(proxiedURL);
|
|
14469
|
-
|
|
14486
|
+
const cssContent = await response.text();
|
|
14470
14487
|
const styleElement = document.createElement("style");
|
|
14471
14488
|
styleElement.textContent = cssContent;
|
|
14472
14489
|
styleElement.setAttribute("original-link-element", encodeURIComponent(stylesheetElement.outerHTML));
|
|
@@ -14522,7 +14539,7 @@ async function cleanUpCorsProxy() {
|
|
|
14522
14539
|
}
|
|
14523
14540
|
async function restoreCSS() {
|
|
14524
14541
|
const styleElements = document.querySelectorAll("style[original-link-element]");
|
|
14525
|
-
for (
|
|
14542
|
+
for (const styleElement of styleElements) {
|
|
14526
14543
|
const originalLinkElementHTML = decodeURIComponent(styleElement.getAttribute("original-link-element"));
|
|
14527
14544
|
const tempContainer = document.createElement("div");
|
|
14528
14545
|
tempContainer.innerHTML = originalLinkElementHTML;
|
|
@@ -14533,7 +14550,7 @@ async function restoreCSS() {
|
|
|
14533
14550
|
}
|
|
14534
14551
|
async function restoreImages() {
|
|
14535
14552
|
const imageElements = document.querySelectorAll("img[original-src]");
|
|
14536
|
-
for (
|
|
14553
|
+
for (const imageElement of imageElements) {
|
|
14537
14554
|
const originalSrc = imageElement.getAttribute("original-src");
|
|
14538
14555
|
imageElement.src = originalSrc;
|
|
14539
14556
|
imageElement.removeAttribute("original-src");
|
|
@@ -14547,6 +14564,23 @@ var corsProxy = {
|
|
|
14547
14564
|
cleanUp: cleanUpCorsProxy
|
|
14548
14565
|
};
|
|
14549
14566
|
|
|
14567
|
+
// src/capture/data-url-to-blob.ts
|
|
14568
|
+
function dataUrlToBlob(dataURL) {
|
|
14569
|
+
const commaIndex = dataURL.indexOf(",");
|
|
14570
|
+
const meta = dataURL.slice(0, commaIndex);
|
|
14571
|
+
const data = dataURL.slice(commaIndex + 1);
|
|
14572
|
+
const mimeMatch = meta.match(/^data:([^;]+)/);
|
|
14573
|
+
const mime = mimeMatch ? mimeMatch[1] : "";
|
|
14574
|
+
if (meta.includes(";base64")) {
|
|
14575
|
+
const binary = atob(data);
|
|
14576
|
+
const bytes = new Uint8Array(binary.length);
|
|
14577
|
+
for (let i2 = 0;i2 < binary.length; i2++)
|
|
14578
|
+
bytes[i2] = binary.charCodeAt(i2);
|
|
14579
|
+
return new Blob([bytes], { type: mime });
|
|
14580
|
+
}
|
|
14581
|
+
return new Blob([decodeURIComponent(data)], { type: mime });
|
|
14582
|
+
}
|
|
14583
|
+
|
|
14550
14584
|
// src/capture/get-image-options.ts
|
|
14551
14585
|
async function getImageOptions(element, config) {
|
|
14552
14586
|
return {
|
|
@@ -14588,7 +14622,7 @@ async function getImageOptions(element, config) {
|
|
|
14588
14622
|
throw new Error(`ImageExporter: provided format is not valid.
|
|
14589
14623
|
Provided: ${format}
|
|
14590
14624
|
Element: ${element}
|
|
14591
|
-
Accepted values: jpg, png, svg,
|
|
14625
|
+
Accepted values: jpg, png, svg, webp
|
|
14592
14626
|
Defaulting to: ${config.format}`);
|
|
14593
14627
|
}
|
|
14594
14628
|
} catch (error) {
|
|
@@ -14679,32 +14713,35 @@ function isVisible(element) {
|
|
|
14679
14713
|
}
|
|
14680
14714
|
|
|
14681
14715
|
// src/capture/determine-total-elements.ts
|
|
14682
|
-
async function determineTotalElements(elements) {
|
|
14716
|
+
async function determineTotalElements(elements, config) {
|
|
14683
14717
|
try {
|
|
14684
14718
|
let totalElements = 0;
|
|
14685
|
-
for (const element of elements) {
|
|
14686
|
-
|
|
14687
|
-
if (!scaleAsString)
|
|
14688
|
-
continue;
|
|
14689
|
-
if (scaleAsString.includes(",")) {
|
|
14690
|
-
const scales = scaleAsString.trim().split(",").map((scale) => parseFloat(scale));
|
|
14691
|
-
if (scales.some((scale) => isNaN(scale)))
|
|
14692
|
-
continue;
|
|
14693
|
-
totalElements += scales.length;
|
|
14694
|
-
} else {
|
|
14695
|
-
const scaleAsNumber = parseFloat(scaleAsString.trim());
|
|
14696
|
-
if (isNaN(scaleAsNumber)) {
|
|
14697
|
-
continue;
|
|
14698
|
-
} else {
|
|
14699
|
-
totalElements++;
|
|
14700
|
-
}
|
|
14701
|
-
}
|
|
14719
|
+
for (const element of Array.from(elements)) {
|
|
14720
|
+
totalElements += countScalesForElement(element, config);
|
|
14702
14721
|
}
|
|
14703
14722
|
return totalElements;
|
|
14704
|
-
} catch
|
|
14723
|
+
} catch {
|
|
14705
14724
|
return 1;
|
|
14706
14725
|
}
|
|
14707
14726
|
}
|
|
14727
|
+
function countScalesForElement(element, config) {
|
|
14728
|
+
const scaleAsString = element.dataset.scale;
|
|
14729
|
+
if (!scaleAsString)
|
|
14730
|
+
return countConfigScale(config);
|
|
14731
|
+
if (scaleAsString.includes(",")) {
|
|
14732
|
+
const scales = scaleAsString.trim().split(",").map((scale) => parseFloat(scale));
|
|
14733
|
+
if (scales.some((scale) => isNaN(scale)))
|
|
14734
|
+
return countConfigScale(config);
|
|
14735
|
+
return scales.length;
|
|
14736
|
+
}
|
|
14737
|
+
const scaleAsNumber = parseFloat(scaleAsString.trim());
|
|
14738
|
+
if (isNaN(scaleAsNumber))
|
|
14739
|
+
return countConfigScale(config);
|
|
14740
|
+
return 1;
|
|
14741
|
+
}
|
|
14742
|
+
function countConfigScale(config) {
|
|
14743
|
+
return Array.isArray(config.scale) ? config.scale.length : 1;
|
|
14744
|
+
}
|
|
14708
14745
|
|
|
14709
14746
|
// src/capture/index.ts
|
|
14710
14747
|
var windowLogging = true;
|
|
@@ -14720,54 +14757,90 @@ async function capture(elements, userConfig = defaultConfig) {
|
|
|
14720
14757
|
elements = [elements];
|
|
14721
14758
|
const originalLength = elements.length;
|
|
14722
14759
|
elements = removeHiddenElements(elements);
|
|
14723
|
-
const totalElements = await determineTotalElements(elements);
|
|
14760
|
+
const totalElements = await determineTotalElements(elements, config);
|
|
14724
14761
|
if (originalLength !== elements.length)
|
|
14725
14762
|
log.verbose("Skipping capture of hidden elements: ", originalLength - elements.length);
|
|
14726
14763
|
log.verbose("Element to capture", elements.length);
|
|
14727
14764
|
if (userConfig.corsProxyBaseUrl)
|
|
14728
14765
|
await corsProxy.run(config, elements);
|
|
14729
|
-
|
|
14730
|
-
|
|
14766
|
+
const images = [];
|
|
14767
|
+
const seen = new Set;
|
|
14731
14768
|
let imageNumber = 1;
|
|
14732
|
-
|
|
14733
|
-
|
|
14734
|
-
|
|
14735
|
-
|
|
14736
|
-
|
|
14737
|
-
|
|
14738
|
-
|
|
14739
|
-
|
|
14740
|
-
|
|
14741
|
-
|
|
14742
|
-
|
|
14743
|
-
|
|
14744
|
-
|
|
14745
|
-
|
|
14746
|
-
|
|
14747
|
-
|
|
14748
|
-
|
|
14749
|
-
|
|
14750
|
-
|
|
14769
|
+
const tryCapture = async (element, options) => {
|
|
14770
|
+
try {
|
|
14771
|
+
const image = await captureElement(element, options, seen, config.screenshotOptions);
|
|
14772
|
+
images.push(applyOutput(image, config.output));
|
|
14773
|
+
} catch (error) {
|
|
14774
|
+
log.error(error);
|
|
14775
|
+
} finally {
|
|
14776
|
+
const completed = imageNumber++;
|
|
14777
|
+
log.progress(completed, totalElements);
|
|
14778
|
+
config.onProgress?.(completed, totalElements);
|
|
14779
|
+
}
|
|
14780
|
+
};
|
|
14781
|
+
captureLoop:
|
|
14782
|
+
for (const element of elements) {
|
|
14783
|
+
if (config.signal?.aborted)
|
|
14784
|
+
break;
|
|
14785
|
+
const imageOptions = await getImageOptions(element, config);
|
|
14786
|
+
log.verbose("Image options", imageOptions);
|
|
14787
|
+
if (imageOptions.scale instanceof Array) {
|
|
14788
|
+
log.verbose("Multi-scale capture");
|
|
14789
|
+
imageOptions.includeScaleInLabel = true;
|
|
14790
|
+
for (const scale of imageOptions.scale) {
|
|
14791
|
+
if (config.signal?.aborted)
|
|
14792
|
+
break captureLoop;
|
|
14793
|
+
await tryCapture(element, {
|
|
14794
|
+
...imageOptions,
|
|
14795
|
+
scale
|
|
14796
|
+
});
|
|
14797
|
+
}
|
|
14798
|
+
} else if (typeof imageOptions.scale === "number") {
|
|
14799
|
+
log.verbose("Single-scale capture");
|
|
14800
|
+
await tryCapture(element, imageOptions);
|
|
14801
|
+
}
|
|
14802
|
+
}
|
|
14803
|
+
if (config.signal?.aborted) {
|
|
14804
|
+
log.verbose("Capture aborted; returning", images.length, "image(s)");
|
|
14805
|
+
return images;
|
|
14806
|
+
}
|
|
14807
|
+
if (config.downloadImages)
|
|
14751
14808
|
await downloadImages(images, config);
|
|
14752
|
-
if (userConfig.corsProxyBaseUrl)
|
|
14753
|
-
await corsProxy.cleanUp();
|
|
14754
14809
|
return images;
|
|
14755
14810
|
} catch (error) {
|
|
14756
14811
|
log.error(error);
|
|
14757
14812
|
return null;
|
|
14758
14813
|
} finally {
|
|
14814
|
+
if (userConfig.corsProxyBaseUrl)
|
|
14815
|
+
await corsProxy.cleanUp();
|
|
14759
14816
|
log.group.close();
|
|
14760
14817
|
}
|
|
14761
14818
|
}
|
|
14819
|
+
function applyOutput(image, output) {
|
|
14820
|
+
if (!output || output === "dataurl")
|
|
14821
|
+
return image;
|
|
14822
|
+
const blob = dataUrlToBlob(image.dataURL);
|
|
14823
|
+
if (output === "blob")
|
|
14824
|
+
return { ...image, dataURL: "", blob };
|
|
14825
|
+
return { ...image, blob };
|
|
14826
|
+
}
|
|
14827
|
+
|
|
14828
|
+
// src/capture/copy-to-clipboard.ts
|
|
14829
|
+
async function copyImageToClipboard(image) {
|
|
14830
|
+
const blob = image.blob ?? dataUrlToBlob(image.dataURL);
|
|
14831
|
+
await navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);
|
|
14832
|
+
}
|
|
14762
14833
|
|
|
14763
14834
|
// src/index.ts
|
|
14764
14835
|
if (typeof window !== "undefined") {
|
|
14765
14836
|
window.imageExporter = capture;
|
|
14766
14837
|
window.imageExporterDownload = downloadImages;
|
|
14838
|
+
window.imageExporterCopyToClipboard = copyImageToClipboard;
|
|
14767
14839
|
}
|
|
14768
14840
|
export {
|
|
14769
14841
|
downloadImages,
|
|
14842
|
+
copyImageToClipboard,
|
|
14770
14843
|
capture
|
|
14771
14844
|
};
|
|
14772
14845
|
|
|
14773
|
-
//# debugId=
|
|
14846
|
+
//# debugId=5968FC6C897FE80D64756E2164756E21
|