image-exporter 1.0.1 → 1.0.3
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 +1 -1
- package/dist/image-exporter.es.js +20 -14
- package/dist/image-exporter.umd.js +20 -14
- package/package.json +1 -1
- package/src/capture/capture-element.ts +0 -2
- package/src/capture/index.ts +9 -6
- package/src/cors-proxy/proxy-css.ts +0 -11
- package/src/logger.ts +11 -1
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ import { capture } from "image-exporter";
|
|
|
50
50
|
/** Default label for images. Does not include file extension or scale. */
|
|
51
51
|
defaultImageLabel: string;
|
|
52
52
|
/** Label for zip file. Does not include file extension or scale. */
|
|
53
|
-
zipLabel:
|
|
53
|
+
zipLabel: string;
|
|
54
54
|
/** Base URL for CORS proxy used when fetching external images. */
|
|
55
55
|
corsProxyBaseUrl: string;
|
|
56
56
|
/** Enable window logging for use by external scripts */
|
|
@@ -3338,7 +3338,11 @@ const log = {
|
|
|
3338
3338
|
info: (...messages) => logAction(messages, "info"),
|
|
3339
3339
|
error: (...messages) => logAction(messages, "error"),
|
|
3340
3340
|
verbose: (...messages) => logAction(messages, "verbose"),
|
|
3341
|
-
progress: (progress, total) => logProgress(progress, total)
|
|
3341
|
+
progress: (progress, total) => logProgress(progress, total),
|
|
3342
|
+
group: {
|
|
3343
|
+
open: (...messages) => logAction(messages, "group"),
|
|
3344
|
+
close: (...messages) => logAction(messages, "groupEnd")
|
|
3345
|
+
}
|
|
3342
3346
|
};
|
|
3343
3347
|
async function logAction(messages, type = "info") {
|
|
3344
3348
|
const combinedMessage = messages.map((msg) => typeof msg === "object" ? JSON.stringify(msg) : msg).join(" ");
|
|
@@ -3358,6 +3362,12 @@ async function logAction(messages, type = "info") {
|
|
|
3358
3362
|
console.log(...messages);
|
|
3359
3363
|
}
|
|
3360
3364
|
break;
|
|
3365
|
+
case "group":
|
|
3366
|
+
console.group(...messages);
|
|
3367
|
+
break;
|
|
3368
|
+
case "groupEnd":
|
|
3369
|
+
console.groupEnd();
|
|
3370
|
+
break;
|
|
3361
3371
|
}
|
|
3362
3372
|
if (windowLogging) window.imageExporterLogs.push({ message: combinedMessage, type });
|
|
3363
3373
|
}
|
|
@@ -3396,13 +3406,6 @@ async function proxyCSS(config) {
|
|
|
3396
3406
|
try {
|
|
3397
3407
|
const response = await fetch(proxiedURL);
|
|
3398
3408
|
let cssContent = await response.text();
|
|
3399
|
-
cssContent = cssContent.replace(
|
|
3400
|
-
/url\(['"]?(https?:\/\/[^'")\s]+)['"]?\)/g,
|
|
3401
|
-
(match, url) => {
|
|
3402
|
-
if (url.startsWith(config.corsProxyBaseUrl)) return match;
|
|
3403
|
-
return `url("${config.corsProxyBaseUrl}${encodeURIComponent(url)}")`;
|
|
3404
|
-
}
|
|
3405
|
-
);
|
|
3406
3409
|
const styleElement = document.createElement("style");
|
|
3407
3410
|
styleElement.textContent = cssContent;
|
|
3408
3411
|
styleElement.setAttribute(
|
|
@@ -3645,6 +3648,7 @@ async function determineTotalElements(elements) {
|
|
|
3645
3648
|
let windowLogging = true;
|
|
3646
3649
|
let loggingLevel = "none";
|
|
3647
3650
|
async function capture(elements, userConfig = defaultConfig) {
|
|
3651
|
+
log.group.open("image-exporter");
|
|
3648
3652
|
try {
|
|
3649
3653
|
const config = { ...defaultConfig, ...userConfig };
|
|
3650
3654
|
windowLogging = config.enableWindowLogging;
|
|
@@ -3656,19 +3660,19 @@ async function capture(elements, userConfig = defaultConfig) {
|
|
|
3656
3660
|
const totalElements = await determineTotalElements(elements);
|
|
3657
3661
|
if (originalLength !== elements.length)
|
|
3658
3662
|
log.verbose(
|
|
3659
|
-
"
|
|
3663
|
+
"Skipping capture of hidden elements: ",
|
|
3660
3664
|
originalLength - elements.length
|
|
3661
3665
|
);
|
|
3662
|
-
log.verbose("
|
|
3666
|
+
log.verbose("Element to capture", elements.length);
|
|
3663
3667
|
if (userConfig.corsProxyBaseUrl) await corsProxy.run(config, elements);
|
|
3664
3668
|
let images = [];
|
|
3665
3669
|
let filenames = [];
|
|
3666
3670
|
let imageNumber = 1;
|
|
3667
3671
|
for (const element of elements) {
|
|
3668
3672
|
const imageOptions = await getImageOptions(element, config);
|
|
3669
|
-
log.verbose("
|
|
3673
|
+
log.verbose("Image options", imageOptions);
|
|
3670
3674
|
if (imageOptions.scale instanceof Array) {
|
|
3671
|
-
log.verbose("
|
|
3675
|
+
log.verbose("Multi-scale capture");
|
|
3672
3676
|
imageOptions.includeScaleInLabel = true;
|
|
3673
3677
|
for (const scale of imageOptions.scale) {
|
|
3674
3678
|
log.progress(imageNumber++, totalElements);
|
|
@@ -3681,7 +3685,7 @@ async function capture(elements, userConfig = defaultConfig) {
|
|
|
3681
3685
|
}
|
|
3682
3686
|
} else if (typeof imageOptions.scale === "number") {
|
|
3683
3687
|
log.progress(imageNumber++, totalElements);
|
|
3684
|
-
log.verbose("
|
|
3688
|
+
log.verbose("Single-scale capture");
|
|
3685
3689
|
const image = await captureElement(
|
|
3686
3690
|
element,
|
|
3687
3691
|
imageOptions,
|
|
@@ -3690,12 +3694,14 @@ async function capture(elements, userConfig = defaultConfig) {
|
|
|
3690
3694
|
images.push(image);
|
|
3691
3695
|
}
|
|
3692
3696
|
}
|
|
3693
|
-
if (userConfig.downloadImages) downloadImages(images, config);
|
|
3697
|
+
if (userConfig.downloadImages) await downloadImages(images, config);
|
|
3694
3698
|
if (userConfig.corsProxyBaseUrl) await corsProxy.cleanUp();
|
|
3695
3699
|
return images;
|
|
3696
3700
|
} catch (error) {
|
|
3697
3701
|
log.error(error);
|
|
3698
3702
|
return null;
|
|
3703
|
+
} finally {
|
|
3704
|
+
log.group.close();
|
|
3699
3705
|
}
|
|
3700
3706
|
}
|
|
3701
3707
|
if (typeof window !== "undefined") {
|
|
@@ -3343,7 +3343,11 @@
|
|
|
3343
3343
|
info: (...messages) => logAction(messages, "info"),
|
|
3344
3344
|
error: (...messages) => logAction(messages, "error"),
|
|
3345
3345
|
verbose: (...messages) => logAction(messages, "verbose"),
|
|
3346
|
-
progress: (progress, total) => logProgress(progress, total)
|
|
3346
|
+
progress: (progress, total) => logProgress(progress, total),
|
|
3347
|
+
group: {
|
|
3348
|
+
open: (...messages) => logAction(messages, "group"),
|
|
3349
|
+
close: (...messages) => logAction(messages, "groupEnd")
|
|
3350
|
+
}
|
|
3347
3351
|
};
|
|
3348
3352
|
async function logAction(messages, type = "info") {
|
|
3349
3353
|
const combinedMessage = messages.map((msg) => typeof msg === "object" ? JSON.stringify(msg) : msg).join(" ");
|
|
@@ -3363,6 +3367,12 @@
|
|
|
3363
3367
|
console.log(...messages);
|
|
3364
3368
|
}
|
|
3365
3369
|
break;
|
|
3370
|
+
case "group":
|
|
3371
|
+
console.group(...messages);
|
|
3372
|
+
break;
|
|
3373
|
+
case "groupEnd":
|
|
3374
|
+
console.groupEnd();
|
|
3375
|
+
break;
|
|
3366
3376
|
}
|
|
3367
3377
|
if (windowLogging) window.imageExporterLogs.push({ message: combinedMessage, type });
|
|
3368
3378
|
}
|
|
@@ -3401,13 +3411,6 @@
|
|
|
3401
3411
|
try {
|
|
3402
3412
|
const response = await fetch(proxiedURL);
|
|
3403
3413
|
let cssContent = await response.text();
|
|
3404
|
-
cssContent = cssContent.replace(
|
|
3405
|
-
/url\(['"]?(https?:\/\/[^'")\s]+)['"]?\)/g,
|
|
3406
|
-
(match, url) => {
|
|
3407
|
-
if (url.startsWith(config.corsProxyBaseUrl)) return match;
|
|
3408
|
-
return `url("${config.corsProxyBaseUrl}${encodeURIComponent(url)}")`;
|
|
3409
|
-
}
|
|
3410
|
-
);
|
|
3411
3414
|
const styleElement = document.createElement("style");
|
|
3412
3415
|
styleElement.textContent = cssContent;
|
|
3413
3416
|
styleElement.setAttribute(
|
|
@@ -3650,6 +3653,7 @@
|
|
|
3650
3653
|
let windowLogging = true;
|
|
3651
3654
|
let loggingLevel = "none";
|
|
3652
3655
|
async function capture(elements, userConfig = defaultConfig) {
|
|
3656
|
+
log.group.open("image-exporter");
|
|
3653
3657
|
try {
|
|
3654
3658
|
const config = { ...defaultConfig, ...userConfig };
|
|
3655
3659
|
windowLogging = config.enableWindowLogging;
|
|
@@ -3661,19 +3665,19 @@
|
|
|
3661
3665
|
const totalElements = await determineTotalElements(elements);
|
|
3662
3666
|
if (originalLength !== elements.length)
|
|
3663
3667
|
log.verbose(
|
|
3664
|
-
"
|
|
3668
|
+
"Skipping capture of hidden elements: ",
|
|
3665
3669
|
originalLength - elements.length
|
|
3666
3670
|
);
|
|
3667
|
-
log.verbose("
|
|
3671
|
+
log.verbose("Element to capture", elements.length);
|
|
3668
3672
|
if (userConfig.corsProxyBaseUrl) await corsProxy.run(config, elements);
|
|
3669
3673
|
let images = [];
|
|
3670
3674
|
let filenames = [];
|
|
3671
3675
|
let imageNumber = 1;
|
|
3672
3676
|
for (const element of elements) {
|
|
3673
3677
|
const imageOptions = await getImageOptions(element, config);
|
|
3674
|
-
log.verbose("
|
|
3678
|
+
log.verbose("Image options", imageOptions);
|
|
3675
3679
|
if (imageOptions.scale instanceof Array) {
|
|
3676
|
-
log.verbose("
|
|
3680
|
+
log.verbose("Multi-scale capture");
|
|
3677
3681
|
imageOptions.includeScaleInLabel = true;
|
|
3678
3682
|
for (const scale of imageOptions.scale) {
|
|
3679
3683
|
log.progress(imageNumber++, totalElements);
|
|
@@ -3686,7 +3690,7 @@
|
|
|
3686
3690
|
}
|
|
3687
3691
|
} else if (typeof imageOptions.scale === "number") {
|
|
3688
3692
|
log.progress(imageNumber++, totalElements);
|
|
3689
|
-
log.verbose("
|
|
3693
|
+
log.verbose("Single-scale capture");
|
|
3690
3694
|
const image = await captureElement(
|
|
3691
3695
|
element,
|
|
3692
3696
|
imageOptions,
|
|
@@ -3695,12 +3699,14 @@
|
|
|
3695
3699
|
images.push(image);
|
|
3696
3700
|
}
|
|
3697
3701
|
}
|
|
3698
|
-
if (userConfig.downloadImages) downloadImages(images, config);
|
|
3702
|
+
if (userConfig.downloadImages) await downloadImages(images, config);
|
|
3699
3703
|
if (userConfig.corsProxyBaseUrl) await corsProxy.cleanUp();
|
|
3700
3704
|
return images;
|
|
3701
3705
|
} catch (error) {
|
|
3702
3706
|
log.error(error);
|
|
3703
3707
|
return null;
|
|
3708
|
+
} finally {
|
|
3709
|
+
log.group.close();
|
|
3704
3710
|
}
|
|
3705
3711
|
}
|
|
3706
3712
|
if (typeof window !== "undefined") {
|
package/package.json
CHANGED
|
@@ -2,8 +2,6 @@ import * as htmlToImage from "html-to-image";
|
|
|
2
2
|
import { Image, ParsedImageOptions } from "../types";
|
|
3
3
|
import { handleFileNames } from "./handle-filenames";
|
|
4
4
|
import { Options } from "html-to-image/lib/types";
|
|
5
|
-
import { get } from "http";
|
|
6
|
-
|
|
7
5
|
/**
|
|
8
6
|
* captureElement
|
|
9
7
|
*
|
package/src/capture/index.ts
CHANGED
|
@@ -20,6 +20,7 @@ export async function capture(
|
|
|
20
20
|
elements: HTMLElement[] | NodeListOf<HTMLElement> | HTMLElement,
|
|
21
21
|
userConfig: Partial<Config> = defaultConfig
|
|
22
22
|
): Promise<Image[] | null> {
|
|
23
|
+
log.group.open("image-exporter");
|
|
23
24
|
try {
|
|
24
25
|
/* --------------------------------- Config --------------------------------- */
|
|
25
26
|
const config = { ...defaultConfig, ...userConfig };
|
|
@@ -36,10 +37,10 @@ export async function capture(
|
|
|
36
37
|
|
|
37
38
|
if (originalLength !== elements.length)
|
|
38
39
|
log.verbose(
|
|
39
|
-
"
|
|
40
|
+
"Skipping capture of hidden elements: ",
|
|
40
41
|
originalLength - elements.length
|
|
41
42
|
);
|
|
42
|
-
log.verbose("
|
|
43
|
+
log.verbose("Element to capture", elements.length);
|
|
43
44
|
|
|
44
45
|
/* ------------------------------- CORS proxy ------------------------------- */
|
|
45
46
|
if (userConfig.corsProxyBaseUrl) await corsProxy.run(config, elements);
|
|
@@ -51,11 +52,11 @@ export async function capture(
|
|
|
51
52
|
|
|
52
53
|
for (const element of elements) {
|
|
53
54
|
const imageOptions = await getImageOptions(element, config);
|
|
54
|
-
log.verbose("
|
|
55
|
+
log.verbose("Image options", imageOptions);
|
|
55
56
|
|
|
56
57
|
if (imageOptions.scale instanceof Array) {
|
|
57
58
|
/* --------------------------- Multi-scale capture -------------------------- */
|
|
58
|
-
log.verbose("
|
|
59
|
+
log.verbose("Multi-scale capture");
|
|
59
60
|
|
|
60
61
|
imageOptions.includeScaleInLabel = true;
|
|
61
62
|
|
|
@@ -72,7 +73,7 @@ export async function capture(
|
|
|
72
73
|
} else if (typeof imageOptions.scale === "number") {
|
|
73
74
|
log.progress(imageNumber++, totalElements);
|
|
74
75
|
/* -------------------------- Single scale capture -------------------------- */
|
|
75
|
-
log.verbose("
|
|
76
|
+
log.verbose("Single-scale capture");
|
|
76
77
|
|
|
77
78
|
const image = await captureElement(
|
|
78
79
|
element,
|
|
@@ -85,7 +86,7 @@ export async function capture(
|
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
/* -------------------------------- Download -------------------------------- */
|
|
88
|
-
if (userConfig.downloadImages) downloadImages(images, config);
|
|
89
|
+
if (userConfig.downloadImages) await downloadImages(images, config);
|
|
89
90
|
|
|
90
91
|
/* --------------------------- Clean up CORS proxy -------------------------- */
|
|
91
92
|
if (userConfig.corsProxyBaseUrl) await corsProxy.cleanUp();
|
|
@@ -95,5 +96,7 @@ export async function capture(
|
|
|
95
96
|
} catch (error) {
|
|
96
97
|
log.error(error);
|
|
97
98
|
return null;
|
|
99
|
+
} finally {
|
|
100
|
+
log.group.close();
|
|
98
101
|
}
|
|
99
102
|
}
|
|
@@ -29,17 +29,6 @@ export async function proxyCSS(config: Config) {
|
|
|
29
29
|
const response = await fetch(proxiedURL);
|
|
30
30
|
let cssContent = await response.text();
|
|
31
31
|
|
|
32
|
-
// Proxy absolute URLs (http/https) within the CSS content
|
|
33
|
-
cssContent = cssContent.replace(
|
|
34
|
-
/url\(['"]?(https?:\/\/[^'")\s]+)['"]?\)/g,
|
|
35
|
-
(match, url) => {
|
|
36
|
-
// Skip if already proxied
|
|
37
|
-
if (url.startsWith(config.corsProxyBaseUrl)) return match;
|
|
38
|
-
// Otherwise return proxied URL
|
|
39
|
-
return `url("${config.corsProxyBaseUrl}${encodeURIComponent(url)}")`;
|
|
40
|
-
}
|
|
41
|
-
);
|
|
42
|
-
|
|
43
32
|
// Insert the parsed CSS content into a <style> element
|
|
44
33
|
const styleElement = document.createElement("style");
|
|
45
34
|
styleElement.textContent = cssContent;
|
package/src/logger.ts
CHANGED
|
@@ -5,6 +5,10 @@ export const log = {
|
|
|
5
5
|
error: (...messages: any[]) => logAction(messages, "error"),
|
|
6
6
|
verbose: (...messages: any[]) => logAction(messages, "verbose"),
|
|
7
7
|
progress: (progress: number, total: number) => logProgress(progress, total),
|
|
8
|
+
group: {
|
|
9
|
+
open: (...messages: any[]) => logAction(messages, "group"),
|
|
10
|
+
close: (...messages: any[]) => logAction(messages, "groupEnd"),
|
|
11
|
+
},
|
|
8
12
|
};
|
|
9
13
|
|
|
10
14
|
async function logAction(messages: any[], type: LogType = "info") {
|
|
@@ -28,6 +32,12 @@ async function logAction(messages: any[], type: LogType = "info") {
|
|
|
28
32
|
console.log(...messages);
|
|
29
33
|
}
|
|
30
34
|
break;
|
|
35
|
+
case "group":
|
|
36
|
+
console.group(...messages);
|
|
37
|
+
break;
|
|
38
|
+
case "groupEnd":
|
|
39
|
+
console.groupEnd();
|
|
40
|
+
break;
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
if (windowLogging) window.imageExporterLogs.push({ message: combinedMessage, type });
|
|
@@ -39,7 +49,7 @@ async function logProgress(progress: number, total: number) {
|
|
|
39
49
|
}
|
|
40
50
|
}
|
|
41
51
|
|
|
42
|
-
type LogType = "info" | "error" | "verbose" | "progress";
|
|
52
|
+
type LogType = "info" | "error" | "verbose" | "progress" | "group" | "groupEnd";
|
|
43
53
|
|
|
44
54
|
type Log = {
|
|
45
55
|
message: string;
|