PluginProbe
Squeeze – Image Optimization & Compression, WEBP Conversion / 1.1
Squeeze – Image Optimization & Compression, WEBP Conversion v1.1
1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 trunk 1.0 1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5 1.5.1 1.5.2 1.6 All 42 releases
squeeze / assets / js / script.js

script.js in Squeeze – Image Optimization & Compression, WEBP Conversion 1.1, at assets/js/script.js

337 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 //import * as avif from '@jsquash/avif'; // TBD
2 //import * as webp from '@jsquash/webp'; // TBD
3 import * as jpeg from '@jsquash/jpeg';
4 import * as png from '@jsquash/png';
5 import optimise from '@jsquash/oxipng/optimise';
6 const { __ } = wp.i18n; // Import __() from wp.i18n
7
8 (function () {
9
10 const bulkBtn = document.querySelector("input[name='squeeze_bulk']")
11 const bulkLogInput = document.querySelector("[name='squeeze_bulk_log']")
12 const squeeze_bulk_ids = document.querySelector("input[name='squeeze_bulk_ids']")?.value ?? null;
13 const uncompressedIDs = squeeze_bulk_ids ? squeeze_bulk_ids.split(",") : [];
14
15 async function decode(sourceType, fileBuffer) {
16 switch (sourceType) {
17 //case 'avif':
18 // return await avif.decode(fileBuffer);
19 case 'jpeg':
20 return await jpeg.decode(fileBuffer);
21 case 'png':
22 return await png.decode(fileBuffer);
23 //case 'webp':
24 // return await webp.decode(fileBuffer);
25 default:
26 throw new Error(`Unknown source type: ${sourceType}`);
27 }
28 }
29
30 async function encode(outputType, imageData) {
31 const options = JSON.parse(squeeze.options);
32
33 switch (outputType) {
34 //case 'avif':
35 // return await avif.encode(imageData);
36 case 'jpeg':
37 const jpegOptions = {}
38 for (const [key, value] of Object.entries(options)) {
39 if (key.includes('jpeg')) {
40 const keyName = key.replace('jpeg_', '')
41 jpegOptions[keyName] = value
42 }
43 }
44 return await jpeg.encode(imageData, jpegOptions);
45 case 'png':
46 const pngOptions = {}
47 for (const [key, value] of Object.entries(options)) {
48 if (key.includes('png')) {
49 const keyName = key.replace('png_', '')
50 pngOptions[keyName] = value
51 }
52 }
53 return await png.encode(imageData, pngOptions);
54 //case 'webp':
55 // return await webp.encode(imageData);
56 default:
57 throw new Error(`Unknown output type: ${outputType}`);
58 }
59 }
60
61 async function convert(sourceType, outputType, fileBuffer) {
62 const imageData = await decode(sourceType, fileBuffer);
63 return encode(outputType, imageData);
64 }
65
66 function blobToBase64(blob) {
67 return new Promise((resolve, _) => {
68 const reader = new FileReader();
69 reader.onloadend = () => resolve(reader.result);
70 reader.readAsDataURL(blob);
71 });
72 }
73
74 async function showOutput(imageBuffer, outputType) {
75 const imageBlob = new Blob([imageBuffer], { type: `image/${outputType}` });
76 const base64String = await blobToBase64(imageBlob);
77
78 return base64String;
79 }
80
81 async function handleUpload(attachment, isBulk = false, isSingle = false, target = null) {
82 const attachmentData = attachment.attributes;
83 const url = attachmentData?.originalImageURL ?? attachmentData.url;
84 const mime = attachmentData.mime;
85 const name = attachmentData.name;
86 const filename = attachmentData?.originalImageName ?? attachmentData.filename;
87 const attachmentID = attachmentData.id;
88 const format = mime.split("/")[1];
89 const sourceType = format;
90 const outputType = format;
91 const options = JSON.parse(squeeze.options);
92
93 let imageBuffer;
94 let fileBuffer;
95 let base64;
96
97 if (format === "png") {
98 const pngOptions = {}
99 for (const [key, value] of Object.entries(options)) {
100 if (key.includes('png')) {
101 const keyName = key.replace('png_', '')
102 pngOptions[keyName] = value
103 }
104 }
105 imageBuffer = await fetch(url).then(res => res.arrayBuffer()).then(pngImageBuffer => optimise(pngImageBuffer, pngOptions));
106 base64 = await showOutput(imageBuffer, outputType);
107 } else {
108 let response = await fetch(url);
109 let blob = await response.blob();
110 let metadata = {
111 type: mime
112 };
113 let imageObj = new File([blob], name, metadata);
114 fileBuffer = await imageObj.arrayBuffer();
115
116 /*
117 if (window.Worker) {
118 //const myWorker = new Worker(new URL(`${squeeze.pluginUrl}/assets/js/worker.js`), { type: "module" });
119 const myWorker = new Worker(/* webpackChunkName: "foo-worker" */ /*new URL(`./worker.js`, import.meta.url));
120 myWorker.postMessage(
121 {
122 fileBuffer: fileBuffer,
123 sourceType: sourceType,
124 outputType: outputType,
125 }
126 );
127 console.log('Message posted to worker');
128
129 myWorker.onmessage = function(e) {
130 console.log('Message received from worker', e.data);
131 myWorker.terminate();
132 }
133 } else {
134 console.log('Your browser doesn\'t support web workers.');
135 }
136 */
137
138 imageBuffer = await convert(sourceType, outputType, fileBuffer);
139 base64 = await showOutput(imageBuffer, outputType);
140 }
141
142 let data = {
143 action: 'squeeze_update_attachment',
144 _ajax_nonce: squeeze.nonce,
145 filename: filename,
146 type: 'image',
147 format: format,
148 base64: base64,
149 attachmentID: attachmentID,
150 url: url,
151 }
152
153 jQuery.ajax({
154 url: squeeze.ajaxUrl,
155 type: 'POST',
156 data: data,
157 beforeSend: function () {
158 console.log('data', data)
159 if (isBulk)
160 bulkLogInput.value += `#${attachmentID}: ` + __('Compressed successfully, updating...', 'squeeze') + `\r\n`;
161 },
162 error: function (error) {
163 console.error(error)
164 if (target) {
165 target.closest("td").querySelector(".squeeze_status").innerText = __('An error has occured. Check the console for details.', 'squeeze')
166 target.remove();
167 }
168 },
169 success: function (response) {
170 console.log(response)
171 if (isBulk) {
172 if (response.success) {
173 bulkLogInput.value += `#${attachmentID}: ` + __('Updated successfully', 'squeeze') + `\r\n===============================\r\n`;
174 handleBulkUpload()
175 } else {
176 bulkLogInput.value += `#${attachmentID}: ${response.data}\r\n===============================\r\n`;
177 }
178 }
179 if (isSingle && target) {
180 target.closest("td").querySelector(".squeeze_status").innerText = response.data;
181 target.remove();
182 }
183 if (!isSingle && !isBulk) {
184 attachment.set('uploading', false) // resume uploading process
185 }
186 }
187 });
188
189 }
190
191 const handleBulkUpload = () => {
192 const data = {
193 action: 'squeeze_get_attachment',
194 _ajax_nonce: squeeze.nonce,
195 attachmentID: uncompressedIDs[0],
196 }
197
198 if (uncompressedIDs.length === 0) {
199 alert(__('All images have been compressed!', 'squeeze'))
200 bulkBtn.remove();
201 location.reload();
202 return;
203 }
204
205 bulkLogInput.value += `attachment #${uncompressedIDs[0]}: start compressing...\r\n`;
206
207 jQuery.ajax({
208 url: squeeze.ajaxUrl,
209 type: 'POST',
210 data: data,
211 error: function (error) {
212 console.error(error)
213 },
214 success: function (response) {
215 //console.log(response)
216 if (response.success) {
217 const responseData = response.data;
218 const attachment = {
219 attributes: {
220 url: responseData.url,
221 mime: responseData.mime,
222 name: responseData.name,
223 filename: responseData.filename,
224 id: responseData.id,
225 }
226 }
227 //console.log(attachment, 'attachment')
228 uncompressedIDs.shift();
229 handleUpload(attachment, true)
230 } else {
231 console.error(response.data)
232 }
233 }
234 });
235 }
236
237 function handleRestore(attachmentID, target) {
238 let data = {
239 action: 'squeeze_restore_attachment',
240 _ajax_nonce: squeeze.nonce,
241 attachmentID: attachmentID,
242 }
243
244 jQuery.ajax({
245 url: squeeze.ajaxUrl,
246 type: 'POST',
247 data: data,
248 beforeSend: function () {
249 target.disabled = true;
250 target.innerText = __('Restore in process...', 'squeeze')
251 },
252 error: function (error) {
253 console.error(error)
254 target.closest("td").querySelector(".squeeze_status").innerText = __('An error has occured. Check the console for details.', 'squeeze')
255 target.remove();
256 },
257 success: function (response) {
258 //console.log(response)
259 target.closest("td").querySelector(".squeeze_status").innerText = response.data; //__('Restored successfully', 'squeeze')
260 target.remove();
261 }
262 });
263 }
264
265 // Handle single compress button click
266 const handleSingleBtnClick = (event) => {
267 const attachmentID = event.target.dataset.attachment;
268
269 wp?.media?.attachment(attachmentID).fetch().then(function (data) {
270 const attachment = {
271 attributes: data
272 }
273 handleUpload(attachment, false, true, event.target)
274 });
275 }
276
277 // Handle restore button click
278 const handleRestoreBtnClick = (event) => {
279 const attachmentID = event.target.dataset.attachment;
280 handleRestore(attachmentID, event.target)
281 }
282
283 /**
284 * Handle single buttons click
285 */
286 function handleSingleButtonsClick() {
287 document.addEventListener("click", (e) => {
288 //console.log(e.target, 'e.target')
289 const singleBtnName = 'squeeze_compress_single';
290 const restoreBtnName = 'squeeze_restore';
291 if (e.target.getAttribute("name") === singleBtnName) {
292 e.target.disabled = true;
293 e.target.innerText = __('Compressing...', 'squeeze')
294 handleSingleBtnClick(e)
295 }
296 if (e.target.getAttribute("name") === restoreBtnName) {
297 e.target.disabled = true;
298 handleRestoreBtnClick(e)
299 }
300 })
301 }
302
303 handleSingleButtonsClick()
304
305
306 /**
307 * Handle bulk button click
308 */
309 bulkBtn?.addEventListener("click", (event) => {
310 if (uncompressedIDs.length === 0) {
311 return;
312 }
313
314 bulkBtn.disabled = true;
315 handleBulkUpload()
316
317 })
318
319 // https://wordpress.stackexchange.com/a/131295/186146 - override wp.Uploader.prototype.success
320 jQuery.extend(wp?.Uploader?.prototype, {
321 success: function (attachment) {
322 //console.log(attachment, 'success');
323 const options = JSON.parse(squeeze.options);
324 const isAutoCompress = options.auto_compress;
325 let isImage = attachment.attributes.type === 'image' &&
326 (attachment.attributes.subtype === 'jpeg' || attachment.attributes.subtype === 'png')
327
328 if (isImage && isAutoCompress) {
329 // set 'uploading' param to true, to pause the uploading process
330 attachment.set('uploading', true)
331 handleUpload(attachment)
332 }
333 },
334 });
335 })();
336
337 //console.log(JSON.parse(squeeze.options), 'squeeze.options')