image-exporter 0.0.1
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/.gitattributes +2 -0
- package/.prettierrc +5 -0
- package/LICENSE.md +201 -0
- package/README.md +3 -0
- package/dist/image-exporter.es.js +3807 -0
- package/dist/image-exporter.umd.js +3813 -0
- package/example/example.css +122 -0
- package/example/example.html +152 -0
- package/example/github.jpg +0 -0
- package/example/poll-h.svg +1 -0
- package/package.json +50 -0
- package/src/capture-images.ts +129 -0
- package/src/clean-up.ts +50 -0
- package/src/cors-proxy/index.ts +22 -0
- package/src/cors-proxy/proxy-css.ts +52 -0
- package/src/cors-proxy/proxy-images.ts +90 -0
- package/src/default-options.ts +58 -0
- package/src/download-images.ts +52 -0
- package/src/get-capture-element.test.html +21 -0
- package/src/get-capture-element.test.ts +36 -0
- package/src/get-capture-element.ts +175 -0
- package/src/get-options/get-input-options.test.html +217 -0
- package/src/get-options/get-input-options.test.ts +109 -0
- package/src/get-options/get-input-options.ts +40 -0
- package/src/get-options/get-item-options.ts +46 -0
- package/src/get-options/get-wrapper-options.test.html +33 -0
- package/src/get-options/get-wrapper-options.test.ts +109 -0
- package/src/get-options/get-wrapper-options.ts +84 -0
- package/src/get-options/index.ts +28 -0
- package/src/image-exporter.ts +108 -0
- package/src/index.ts +8 -0
- package/src/types/image.ts +2 -0
- package/src/types/index.ts +2 -0
- package/src/types/options.ts +69 -0
- package/src/utils/convert-to-slug.ts +15 -0
- package/src/utils/get-attribute-values.ts +68 -0
- package/src/utils/get-date-MMDDYY.ts +11 -0
- package/src/utils/ignore-items.ts +11 -0
- package/src/utils/index.ts +18 -0
- package/src/utils/is-valid-url.ts +20 -0
- package/src/utils/is-visible.ts +12 -0
- package/src/utils/parse-labels.ts +55 -0
- package/src/utils/push-to-window.ts +3 -0
- package/tests/index.html +88 -0
- package/tests/input-tests.html +169 -0
- package/vite.config.js +39 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as types from "./types";
|
|
2
|
+
|
|
3
|
+
export const defaultOptions: types.Options = {
|
|
4
|
+
corsProxyBaseUrl: "",
|
|
5
|
+
downloadImages: true,
|
|
6
|
+
selectors: {
|
|
7
|
+
wrapper: "[ie='wrapper']",
|
|
8
|
+
capture: "[ie='capture']",
|
|
9
|
+
trigger: "[ie='trigger']",
|
|
10
|
+
slug: "[ie='slug']",
|
|
11
|
+
ignore: "[ie='ignore']",
|
|
12
|
+
},
|
|
13
|
+
image: {
|
|
14
|
+
scale: {
|
|
15
|
+
value: 1,
|
|
16
|
+
attributeSelector: "ie-scale",
|
|
17
|
+
inputSelector: "ie-scale-input",
|
|
18
|
+
},
|
|
19
|
+
quality: {
|
|
20
|
+
value: 1,
|
|
21
|
+
attributeSelector: "ie-quality",
|
|
22
|
+
inputSelector: "ie-quality-input",
|
|
23
|
+
},
|
|
24
|
+
format: {
|
|
25
|
+
value: "jpg",
|
|
26
|
+
attributeSelector: "ie-format",
|
|
27
|
+
inputSelector: "ie-format-input",
|
|
28
|
+
},
|
|
29
|
+
dateInLabel: {
|
|
30
|
+
value: true,
|
|
31
|
+
attributeSelector: "ie-img-label-date",
|
|
32
|
+
inputSelector: "ie-img-label-date-input",
|
|
33
|
+
},
|
|
34
|
+
scaleInLabel: {
|
|
35
|
+
value: true,
|
|
36
|
+
attributeSelector: "ie-img-label-scale",
|
|
37
|
+
inputSelector: "ie-img-label-scale-input",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
zip: {
|
|
41
|
+
label: {
|
|
42
|
+
value: "images",
|
|
43
|
+
attributeSelector: "ie-zip-label",
|
|
44
|
+
inputSelector: "ie-zip-label-input",
|
|
45
|
+
},
|
|
46
|
+
dateInLabel: {
|
|
47
|
+
value: true,
|
|
48
|
+
attributeSelector: "ie-zip-label-date",
|
|
49
|
+
inputSelector: "ie-zip-label-date-input",
|
|
50
|
+
},
|
|
51
|
+
scaleInLabel: {
|
|
52
|
+
value: true,
|
|
53
|
+
attributeSelector: "ie-zip-label-scale",
|
|
54
|
+
inputSelector: "ie-zip-label-scale-input",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
debug: false,
|
|
58
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as types from "./types";
|
|
2
|
+
import download from "downloadjs";
|
|
3
|
+
import JSZip from "jszip";
|
|
4
|
+
import { parseZipLabel } from "./utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Downloads images based on the provided array of images and options.
|
|
8
|
+
* If there is only one image, it is downloaded individually.
|
|
9
|
+
* If there are multiple images, they are zipped and downloaded as a single file.
|
|
10
|
+
*
|
|
11
|
+
* @param images - An array of images to be downloaded. Each image should be represented as a tuple with the data URL and the file name.
|
|
12
|
+
* @param options - Additional options for downloading the images.
|
|
13
|
+
* @returns A promise that resolves when all the images are downloaded.
|
|
14
|
+
*/
|
|
15
|
+
export async function downloadImages(images: types.Image[], options: types.Options) {
|
|
16
|
+
if (images.length === 1) {
|
|
17
|
+
const [dataURL, fileName] = images[0];
|
|
18
|
+
|
|
19
|
+
await download(dataURL, fileName);
|
|
20
|
+
} else if (images.length > 1) {
|
|
21
|
+
const zipName = parseZipLabel(options);
|
|
22
|
+
const zipBlob = await zipUpImages(images);
|
|
23
|
+
|
|
24
|
+
await download(zipBlob, zipName);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Zips up the given images into a single ZIP file.
|
|
30
|
+
*
|
|
31
|
+
* @param images - An array of image tuples, where each tuple contains the data URL and the filename.
|
|
32
|
+
* @returns A Promise that resolves to the generated ZIP file as a Blob.
|
|
33
|
+
* @throws If there is an error creating the ZIP file.
|
|
34
|
+
*/
|
|
35
|
+
async function zipUpImages(images: types.Image[]) {
|
|
36
|
+
const zip = new JSZip();
|
|
37
|
+
// Loop through each image tuple and add to the zip
|
|
38
|
+
images.forEach(([dataURL, filename]) => {
|
|
39
|
+
// Extract the content from the data URL
|
|
40
|
+
const content = dataURL.split(",")[1]; // Assumes base64 encoding
|
|
41
|
+
zip.file(filename, content, { base64: true });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
// Generate the ZIP file
|
|
46
|
+
const zipBlob = await zip.generateAsync({ type: "blob" });
|
|
47
|
+
return zipBlob;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error("Error creating ZIP:", error);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Tests</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div ie="wrapper">
|
|
10
|
+
<div ie="capture" ie-scale="1,2,3"></div>
|
|
11
|
+
<div ie="capture"></div>
|
|
12
|
+
<div ie="capture"></div>
|
|
13
|
+
<div ie="capture"></div>
|
|
14
|
+
</div>
|
|
15
|
+
<script src="../../dist/image-exporter.umd.js"></script>
|
|
16
|
+
<script>
|
|
17
|
+
let imageExporter = new ImageExporter({ downloadImages: false, debug: true });
|
|
18
|
+
imageExporter.captureAll();
|
|
19
|
+
</script>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
+
import puppeteer from "puppeteer";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import * as types from "./types";
|
|
5
|
+
import { defaultOptions } from "./default-options";
|
|
6
|
+
|
|
7
|
+
describe("get-capture-element", () => {
|
|
8
|
+
let browser;
|
|
9
|
+
let page;
|
|
10
|
+
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
// Setup for puppeteer with Vitest
|
|
13
|
+
browser = await puppeteer.launch();
|
|
14
|
+
page = await browser.newPage();
|
|
15
|
+
await page.goto(`file://${path.join(__dirname, "get-capture-element.test.html")}`);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterAll(async () => {
|
|
19
|
+
// Teardown for puppeteer with Vitest
|
|
20
|
+
await browser.close();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("encapsulate multi-scale", async () => {
|
|
24
|
+
const result = await page.evaluate(() => {
|
|
25
|
+
const js = `const options = { downloadImages: false, debug: true };
|
|
26
|
+
const imageExporter = new ImageExporter(options);
|
|
27
|
+
const images = imageExporter.captureAll();`;
|
|
28
|
+
//insert at the end of the body
|
|
29
|
+
const script = document.createElement("script");
|
|
30
|
+
script.text = js;
|
|
31
|
+
document.body.appendChild(script);
|
|
32
|
+
|
|
33
|
+
return (window as any).getInputOptionsDebug;
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import * as types from "./types";
|
|
2
|
+
import { isVisible } from "./utils/is-visible";
|
|
3
|
+
import { pushToWindow } from "./utils/push-to-window";
|
|
4
|
+
|
|
5
|
+
// Finds all elements to be captured and returns them in an array
|
|
6
|
+
export function getCaptureElements(options: types.Options): HTMLElement[] {
|
|
7
|
+
try {
|
|
8
|
+
if (!document.querySelector(options.selectors.capture)) {
|
|
9
|
+
console.error("ImageExporter: No capture items found in the wrapper.");
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// If CSV values found in scale attribute, encapsulate elements until all scales are accounted for
|
|
14
|
+
findMultiScaleElements(options);
|
|
15
|
+
|
|
16
|
+
// Find all elements to be captured (which includes the multi-scale elements)
|
|
17
|
+
const elements = Array.from(
|
|
18
|
+
document.querySelectorAll(
|
|
19
|
+
`${options.selectors.wrapper} ${options.selectors.capture}`
|
|
20
|
+
) as NodeListOf<HTMLElement>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// Filter out elements that are not visible
|
|
24
|
+
const visibleElements = elements.filter((element) => isVisible(element));
|
|
25
|
+
|
|
26
|
+
return visibleElements;
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.error("ImageExporter: Error in getCaptureElements", e);
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// If CSV values found in ${prefix}-scale, encapsulate elements until all scales are accounted for
|
|
34
|
+
export function findMultiScaleElements(options: types.Options) {
|
|
35
|
+
try {
|
|
36
|
+
const elements = Array.from(
|
|
37
|
+
document.querySelectorAll(
|
|
38
|
+
`${options.selectors.wrapper} ${options.selectors.capture}`
|
|
39
|
+
) as NodeListOf<HTMLElement>
|
|
40
|
+
);
|
|
41
|
+
if (elements) {
|
|
42
|
+
const elementsWithScaleAttribute = elements.filter((element) =>
|
|
43
|
+
element.hasAttribute(options.image.scale.attributeSelector)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// Check attribute value. It will be a string.
|
|
47
|
+
// If string successfully converts to a number, do nothing.
|
|
48
|
+
// If string is comma-separated, convert to array of numbers.
|
|
49
|
+
elementsWithScaleAttribute.forEach((element) => {
|
|
50
|
+
const scaleValue: any = element.getAttribute(
|
|
51
|
+
options.image.scale.attributeSelector
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (scaleValue.includes(",")) {
|
|
55
|
+
console.log("Multi-scale element found:", scaleValue);
|
|
56
|
+
// If scaleValue is an array...
|
|
57
|
+
const scaleArray: Array<Number> = scaleValue.split(",").map(Number);
|
|
58
|
+
|
|
59
|
+
encapsulateMultiScaleElements(options, element, scaleArray, scaleValue);
|
|
60
|
+
if (options.debug)
|
|
61
|
+
pushToWindow("findMultiScaleElementsTest", element.outerHTML);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return true;
|
|
65
|
+
} else {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.error("ImageExporter: Error in findMultiScaleElements", e);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function encapsulateMultiScaleElements(
|
|
75
|
+
options: types.Options,
|
|
76
|
+
element: Element,
|
|
77
|
+
scaleArray: Array<Number>,
|
|
78
|
+
scaleValue: string
|
|
79
|
+
) {
|
|
80
|
+
try {
|
|
81
|
+
// Set scale attribute
|
|
82
|
+
element.setAttribute(options.image.scale.attributeSelector, scaleArray[0].toString());
|
|
83
|
+
// Force include scale img attribute
|
|
84
|
+
element.setAttribute(options.image.scaleInLabel.attributeSelector, "true");
|
|
85
|
+
element.setAttribute("ie-clone-source", scaleValue);
|
|
86
|
+
|
|
87
|
+
// iterate through array and wrap the element in a new element for each scale
|
|
88
|
+
for (let i = 1; i < scaleArray.length; i++) {
|
|
89
|
+
const newElement = cloneElementAttributes(options, element);
|
|
90
|
+
// Set scale attribute
|
|
91
|
+
newElement.setAttribute(
|
|
92
|
+
options.image.scale.attributeSelector,
|
|
93
|
+
scaleArray[i].toString()
|
|
94
|
+
);
|
|
95
|
+
// Force include scale img attribute
|
|
96
|
+
newElement.setAttribute(options.image.scaleInLabel.attributeSelector, "true");
|
|
97
|
+
// Insert element before the original element, then move the original element inside the new element, deleting the original element
|
|
98
|
+
if (element.parentNode) {
|
|
99
|
+
element.parentNode.insertBefore(newElement, element);
|
|
100
|
+
newElement.appendChild(element);
|
|
101
|
+
console.log("Encapsulated element", element, "with scale", scaleArray[i]);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.error("ImageExporter: Error in encapsulateMultiScaleElements", e);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// only clones attributes that are in the options.image[key].attributeSelector
|
|
111
|
+
function cloneElementAttributes(
|
|
112
|
+
options: types.Options,
|
|
113
|
+
originalElement: Element
|
|
114
|
+
): Element {
|
|
115
|
+
try {
|
|
116
|
+
// Create a new div element
|
|
117
|
+
const clonedElement = document.createElement("div");
|
|
118
|
+
|
|
119
|
+
const arrayOfPossibleAttributes = Object.keys(options.image).map(
|
|
120
|
+
(key) => options.image[key].attributeSelector
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Adds capture attribute to cloned element
|
|
124
|
+
const { prefix, value } = parseStringAttribute(options.selectors.capture);
|
|
125
|
+
clonedElement.setAttribute(prefix, value);
|
|
126
|
+
clonedElement.setAttribute("ie-clone", "true");
|
|
127
|
+
setExplicitDimensions(originalElement, clonedElement);
|
|
128
|
+
|
|
129
|
+
// Iterate over all attributes of the original element
|
|
130
|
+
Array.from(originalElement.attributes).forEach((attr: any) => {
|
|
131
|
+
// Check if the attribute name exists in types.Attributes
|
|
132
|
+
if (attr.name in arrayOfPossibleAttributes) {
|
|
133
|
+
// Copy the attribute to the cloned element
|
|
134
|
+
clonedElement.setAttribute(attr.name, attr.value);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return clonedElement;
|
|
139
|
+
} catch (e) {
|
|
140
|
+
console.error("ImageExporter: Error in cloneElementAttributes", e);
|
|
141
|
+
return originalElement;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function parseStringAttribute(attributeValue: string) {
|
|
146
|
+
if (!attributeValue.includes("=")) {
|
|
147
|
+
throw new Error("Invalid attribute format. Expected format: [prefix=value]");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const attributeArray = attributeValue.split("=");
|
|
151
|
+
if (attributeArray.length !== 2) {
|
|
152
|
+
throw new Error("Invalid attribute format. Expected format: [prefix=value]");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const prefix = attributeArray[0].trim().replace(/^\[|\]$/g, "");
|
|
156
|
+
const value = attributeArray[1]
|
|
157
|
+
.trim()
|
|
158
|
+
.replace(/^\[|\]$/g, "")
|
|
159
|
+
.replace(/^'|'$/g, "");
|
|
160
|
+
|
|
161
|
+
if (!prefix || !value) {
|
|
162
|
+
throw new Error("Invalid attribute format. Prefix or value is missing.");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return { prefix, value };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function setExplicitDimensions(originalElement: any, clonedElement: any) {
|
|
169
|
+
const originalElementStyle = window.getComputedStyle(originalElement);
|
|
170
|
+
const originalElementWidth = originalElementStyle.getPropertyValue("width");
|
|
171
|
+
const originalElementHeight = originalElementStyle.getPropertyValue("height");
|
|
172
|
+
|
|
173
|
+
clonedElement.style.width = originalElementWidth;
|
|
174
|
+
clonedElement.style.height = originalElementHeight;
|
|
175
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Tests</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<section>
|
|
10
|
+
<div>
|
|
11
|
+
<!-- Scale -->
|
|
12
|
+
<label for="scale"><strong>Scale</strong></label>
|
|
13
|
+
<select title="scale" ie-scale-input>
|
|
14
|
+
<option value="5">@1x</option>
|
|
15
|
+
</select>
|
|
16
|
+
</div>
|
|
17
|
+
<div>
|
|
18
|
+
<!-- Quality -->
|
|
19
|
+
<label for="quality"><strong>Quality</strong></label>
|
|
20
|
+
<input
|
|
21
|
+
type="range"
|
|
22
|
+
id="quality"
|
|
23
|
+
name="quality"
|
|
24
|
+
min="0.00"
|
|
25
|
+
max="1.00"
|
|
26
|
+
value="0.75"
|
|
27
|
+
step="0.01"
|
|
28
|
+
ie-quality-input
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
<div>
|
|
32
|
+
<!-- Format -->
|
|
33
|
+
<label for="format"><strong>Format</strong></label>
|
|
34
|
+
<select title="format" ie-format-input>
|
|
35
|
+
<option value="jpg">JPG</option>
|
|
36
|
+
</select>
|
|
37
|
+
</div>
|
|
38
|
+
<div>
|
|
39
|
+
<fieldset>
|
|
40
|
+
<legend><strong>Image label</strong></legend>
|
|
41
|
+
<!-- dateInLabel -->
|
|
42
|
+
<label for="dateInLabel">
|
|
43
|
+
<input
|
|
44
|
+
type="checkbox"
|
|
45
|
+
id="dateInLabel"
|
|
46
|
+
name="dateInLabel"
|
|
47
|
+
name="dateInLabel"
|
|
48
|
+
role="switch"
|
|
49
|
+
checked="checked"
|
|
50
|
+
ie-img-label-date-input
|
|
51
|
+
/>
|
|
52
|
+
Date in label
|
|
53
|
+
</label>
|
|
54
|
+
<!--scaleInLabel-->
|
|
55
|
+
<label for="scaleInLabel">
|
|
56
|
+
<input
|
|
57
|
+
type="checkbox"
|
|
58
|
+
id="scaleInLabel"
|
|
59
|
+
name="scaleInLabel"
|
|
60
|
+
name="scaleInLabel"
|
|
61
|
+
role="switch"
|
|
62
|
+
checked="checked"
|
|
63
|
+
ie-img-label-scale-input
|
|
64
|
+
/>
|
|
65
|
+
Scale in label
|
|
66
|
+
</label>
|
|
67
|
+
</fieldset>
|
|
68
|
+
</div>
|
|
69
|
+
<fieldset>
|
|
70
|
+
<legend><strong>Zip label</strong></legend>
|
|
71
|
+
<!-- zipLabel -->
|
|
72
|
+
<label for="zipLabel">Label</label>
|
|
73
|
+
<input type="text" id="zipLabel" name="zipLabel" ie-zip-label-input value="ie" />
|
|
74
|
+
<!-- zipDateInLabel -->
|
|
75
|
+
<label for="zipDateInLabel">
|
|
76
|
+
<input
|
|
77
|
+
type="checkbox"
|
|
78
|
+
id="zipDateInLabel"
|
|
79
|
+
name="zipDateInLabel"
|
|
80
|
+
name="zipDateInLabel"
|
|
81
|
+
role="switch"
|
|
82
|
+
checked="checked"
|
|
83
|
+
ie-zip-label-date-input
|
|
84
|
+
/>
|
|
85
|
+
Date in label
|
|
86
|
+
</label>
|
|
87
|
+
<!--zipScaleInLabel-->
|
|
88
|
+
<label for="zipScaleInLabel">
|
|
89
|
+
<input
|
|
90
|
+
type="checkbox"
|
|
91
|
+
id="zipScaleInLabel"
|
|
92
|
+
name="zipScaleInLabel"
|
|
93
|
+
name="zipScaleInLabel"
|
|
94
|
+
role="switch"
|
|
95
|
+
checked="checked"
|
|
96
|
+
ie-zip-label-scale-input
|
|
97
|
+
/>
|
|
98
|
+
Scale in label
|
|
99
|
+
</label>
|
|
100
|
+
</fieldset>
|
|
101
|
+
|
|
102
|
+
<button ie-trigger>Run</button>
|
|
103
|
+
</section>
|
|
104
|
+
<section>
|
|
105
|
+
<div>
|
|
106
|
+
<!-- Scale -->
|
|
107
|
+
<label for="test-scale"><strong>Scale</strong></label>
|
|
108
|
+
<select title="test-scale" test-scale-input>
|
|
109
|
+
<option value="5">@1x</option>
|
|
110
|
+
</select>
|
|
111
|
+
</div>
|
|
112
|
+
<div>
|
|
113
|
+
<!-- Quality -->
|
|
114
|
+
<label for="quality"><strong>Quality</strong></label>
|
|
115
|
+
<input
|
|
116
|
+
type="range"
|
|
117
|
+
id="quality"
|
|
118
|
+
name="quality"
|
|
119
|
+
min="0.00"
|
|
120
|
+
max="1.00"
|
|
121
|
+
value="0.75"
|
|
122
|
+
step="0.01"
|
|
123
|
+
test-quality-input
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
<div>
|
|
127
|
+
<!-- Format -->
|
|
128
|
+
<label for="format"><strong>Format</strong></label>
|
|
129
|
+
<select title="format" test-format-input>
|
|
130
|
+
<option value="jpg">JPG</option>
|
|
131
|
+
</select>
|
|
132
|
+
</div>
|
|
133
|
+
<div>
|
|
134
|
+
<fieldset>
|
|
135
|
+
<legend><strong>Image label</strong></legend>
|
|
136
|
+
<!-- dateInLabel -->
|
|
137
|
+
<label for="dateInLabel">
|
|
138
|
+
<input
|
|
139
|
+
type="checkbox"
|
|
140
|
+
id="dateInLabel"
|
|
141
|
+
name="dateInLabel"
|
|
142
|
+
name="dateInLabel"
|
|
143
|
+
role="switch"
|
|
144
|
+
checked="checked"
|
|
145
|
+
test-img-label-date-input
|
|
146
|
+
/>
|
|
147
|
+
Date in label
|
|
148
|
+
</label>
|
|
149
|
+
<!--scaleInLabel-->
|
|
150
|
+
<label for="scaleInLabel">
|
|
151
|
+
<input
|
|
152
|
+
type="checkbox"
|
|
153
|
+
id="scaleInLabel"
|
|
154
|
+
name="scaleInLabel"
|
|
155
|
+
name="scaleInLabel"
|
|
156
|
+
role="switch"
|
|
157
|
+
checked="checked"
|
|
158
|
+
test-img-label-scale-input
|
|
159
|
+
/>
|
|
160
|
+
Scale in label
|
|
161
|
+
</label>
|
|
162
|
+
</fieldset>
|
|
163
|
+
</div>
|
|
164
|
+
<fieldset>
|
|
165
|
+
<legend><strong>Zip label</strong></legend>
|
|
166
|
+
<!-- zipLabel -->
|
|
167
|
+
<label for="zipLabel">Label</label>
|
|
168
|
+
<input
|
|
169
|
+
type="text"
|
|
170
|
+
id="zipLabel"
|
|
171
|
+
name="zipLabel"
|
|
172
|
+
test-zip-label-input
|
|
173
|
+
value="ie"
|
|
174
|
+
/>
|
|
175
|
+
<!-- zipDateInLabel -->
|
|
176
|
+
<label for="zipDateInLabel">
|
|
177
|
+
<input
|
|
178
|
+
type="checkbox"
|
|
179
|
+
id="zipDateInLabel"
|
|
180
|
+
name="zipDateInLabel"
|
|
181
|
+
name="zipDateInLabel"
|
|
182
|
+
role="switch"
|
|
183
|
+
checked="checked"
|
|
184
|
+
test-zip-label-date-input
|
|
185
|
+
/>
|
|
186
|
+
Date in label
|
|
187
|
+
</label>
|
|
188
|
+
<!--zipScaleInLabel-->
|
|
189
|
+
<label for="zipScaleInLabel">
|
|
190
|
+
<input
|
|
191
|
+
type="checkbox"
|
|
192
|
+
id="zipScaleInLabel"
|
|
193
|
+
name="zipScaleInLabel"
|
|
194
|
+
name="zipScaleInLabel"
|
|
195
|
+
role="switch"
|
|
196
|
+
checked="checked"
|
|
197
|
+
test-zip-label-scale-input
|
|
198
|
+
/>
|
|
199
|
+
Scale in label
|
|
200
|
+
</label>
|
|
201
|
+
</fieldset>
|
|
202
|
+
</section>
|
|
203
|
+
<div
|
|
204
|
+
ie="wrapper"
|
|
205
|
+
ie-scale="2"
|
|
206
|
+
ie-quality="0.55"
|
|
207
|
+
ie-format="png"
|
|
208
|
+
ie-img-label-date="false"
|
|
209
|
+
ie-img-label-scale="false"
|
|
210
|
+
ie-zip-label="yay"
|
|
211
|
+
ie-zip-label-date="false"
|
|
212
|
+
ie-zip-label-scale="false"
|
|
213
|
+
></div>
|
|
214
|
+
<div test="wrapper"></div>
|
|
215
|
+
<script src="../../dist/image-exporter.umd.js"></script>
|
|
216
|
+
</body>
|
|
217
|
+
</html>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
+
import puppeteer from "puppeteer";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import * as types from "../types";
|
|
5
|
+
import { defaultOptions } from "../default-options";
|
|
6
|
+
|
|
7
|
+
describe("get-input-options", () => {
|
|
8
|
+
let browser;
|
|
9
|
+
let page;
|
|
10
|
+
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
// Setup for puppeteer with Vitest
|
|
13
|
+
browser = await puppeteer.launch();
|
|
14
|
+
page = await browser.newPage();
|
|
15
|
+
await page.goto(`file://${path.join(__dirname, "get-input-options.test.html")}`);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterAll(async () => {
|
|
19
|
+
// Teardown for puppeteer with Vitest
|
|
20
|
+
await browser.close();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("standard attributes", async () => {
|
|
24
|
+
const result = await page.evaluate(() => {
|
|
25
|
+
const js = `const options = { downloadImages: false, debug: true };
|
|
26
|
+
const imageExporter = new ImageExporter(options);
|
|
27
|
+
const images = imageExporter.captureAll();`;
|
|
28
|
+
//insert at the end of the body
|
|
29
|
+
const script = document.createElement("script");
|
|
30
|
+
script.text = js;
|
|
31
|
+
document.body.appendChild(script);
|
|
32
|
+
|
|
33
|
+
return (window as any).getInputOptionsDebug;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Assertions can then be made based on the result object
|
|
37
|
+
expect(result.image.scale.value).toBe(5);
|
|
38
|
+
expect(result.image.quality.value).toBe(0.75);
|
|
39
|
+
expect(result.image.format.value).toBe("jpg");
|
|
40
|
+
expect(result.image.dateInLabel.value).toBe(true);
|
|
41
|
+
expect(result.image.scaleInLabel.value).toBe(true);
|
|
42
|
+
expect(result.zip.label.value).toBe("ie");
|
|
43
|
+
expect(result.zip.dateInLabel.value).toBe(true);
|
|
44
|
+
expect(result.zip.scaleInLabel.value).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("custom attributes", async () => {
|
|
48
|
+
await page.reload();
|
|
49
|
+
const result = await page.evaluate(() => {
|
|
50
|
+
const js = `const options = {
|
|
51
|
+
downloadImages: false,
|
|
52
|
+
selectors: {
|
|
53
|
+
wrapper: "[test='wrapper']",
|
|
54
|
+
capture: "[test='capture']",
|
|
55
|
+
trigger: "[test='trigger']",
|
|
56
|
+
slug: "[test='slug']",
|
|
57
|
+
ignore: "[test='ignore']",
|
|
58
|
+
},
|
|
59
|
+
image: {
|
|
60
|
+
scale: {
|
|
61
|
+
inputSelector: "test-scale-input",
|
|
62
|
+
},
|
|
63
|
+
quality: {
|
|
64
|
+
inputSelector: "test-quality-input",
|
|
65
|
+
},
|
|
66
|
+
format: {
|
|
67
|
+
inputSelector: "test-format-input",
|
|
68
|
+
},
|
|
69
|
+
dateInLabel: {
|
|
70
|
+
inputSelector: "test-img-label-date-input",
|
|
71
|
+
},
|
|
72
|
+
scaleInLabel: {
|
|
73
|
+
inputSelector: "test-img-label-scale-input",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
zip: {
|
|
77
|
+
label: {
|
|
78
|
+
inputSelector: "test-zip-label-input",
|
|
79
|
+
},
|
|
80
|
+
dateInLabel: {
|
|
81
|
+
inputSelector: "test-zip-label-date-input",
|
|
82
|
+
},
|
|
83
|
+
scaleInLabel: {
|
|
84
|
+
inputSelector: "test-zip-label-scale-input",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
debug: true,
|
|
88
|
+
};
|
|
89
|
+
const imageExporter = new ImageExporter(options);
|
|
90
|
+
const images = imageExporter.captureAll();`;
|
|
91
|
+
//insert at the end of the body
|
|
92
|
+
const script = document.createElement("script");
|
|
93
|
+
script.text = js;
|
|
94
|
+
document.body.appendChild(script);
|
|
95
|
+
|
|
96
|
+
return (window as any).getInputOptionsDebug;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Assertions can then be made based on the result object
|
|
100
|
+
expect(result.image.scale.value).toBe(5);
|
|
101
|
+
expect(result.image.quality.value).toBe(0.75);
|
|
102
|
+
expect(result.image.format.value).toBe("jpg");
|
|
103
|
+
expect(result.image.dateInLabel.value).toBe(true);
|
|
104
|
+
expect(result.image.scaleInLabel.value).toBe(true);
|
|
105
|
+
expect(result.zip.label.value).toBe("ie");
|
|
106
|
+
expect(result.zip.dateInLabel.value).toBe(true);
|
|
107
|
+
expect(result.zip.scaleInLabel.value).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
});
|