Changeset 3345284
- Timestamp:
- 08/15/2025 07:18:40 PM (6 months ago)
- Location:
- squeeze
- Files:
-
- 107 added
- 27 edited
-
assets/screenshot-13.jpg (modified) (previous)
-
assets/screenshot-4.jpg (modified) (previous)
-
assets/screenshot-6.jpg (modified) (previous)
-
tags/1.7.0 (added)
-
tags/1.7.0/assets (added)
-
tags/1.7.0/assets/css (added)
-
tags/1.7.0/assets/css/admin.css (added)
-
tags/1.7.0/assets/css/admin.css.map (added)
-
tags/1.7.0/assets/css/admin.less (added)
-
tags/1.7.0/assets/images (added)
-
tags/1.7.0/assets/images/computer-folder-close-icon.svg (added)
-
tags/1.7.0/assets/images/computer-folder-open-icon.svg (added)
-
tags/1.7.0/assets/images/icon-bulk-page.svg (added)
-
tags/1.7.0/assets/images/icon-compare.svg (added)
-
tags/1.7.0/assets/images/icon-exclude.svg (added)
-
tags/1.7.0/assets/images/icon-resize.svg (added)
-
tags/1.7.0/assets/images/icon.svg (added)
-
tags/1.7.0/assets/images/replace_urls.jpg (added)
-
tags/1.7.0/assets/images/sprite.svg (added)
-
tags/1.7.0/assets/js (added)
-
tags/1.7.0/assets/js/0.bundle.js (added)
-
tags/1.7.0/assets/js/1.bundle.js (added)
-
tags/1.7.0/assets/js/1dbcc374dc53cb692541.wasm (added)
-
tags/1.7.0/assets/js/2.bundle.js (added)
-
tags/1.7.0/assets/js/3.bundle.js (added)
-
tags/1.7.0/assets/js/4240e511ac61ecfff2d8.js (added)
-
tags/1.7.0/assets/js/4afb21e314317a97602a.wasm (added)
-
tags/1.7.0/assets/js/6ac3239376efce53600f.wasm (added)
-
tags/1.7.0/assets/js/8206b9ffe333bdb791d8.wasm (added)
-
tags/1.7.0/assets/js/admin.bundle.js (added)
-
tags/1.7.0/assets/js/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/assets_js_worker_js.bundle.js (added)
-
tags/1.7.0/assets/js/assets_js_worker_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/c96242667dc8e630897a.wasm (added)
-
tags/1.7.0/assets/js/editor.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_avif_codec_enc_avif_enc_mt_worker_js.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_avif_codec_enc_avif_enc_mt_worker_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg-parallel_index_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg-parallel_snippets_wasm-bindgen-rayon-3d2df09ebec17a22_s-312b0a0.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg-parallel_snippets_wasm-bindgen-rayon-3d2df09ebec17a22_s-312b0a0.script.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg-parallel_snippets_wasm-bindgen-rayon-3d2df09ebec17a22_s-312b0a1.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg-parallel_snippets_wasm-bindgen-rayon-3d2df09ebec17a22_s-312b0a1.script.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg-parallel_snippets_wasm-bindgen-rayon-3d2df09ebec17a22_s-3a2b7f.script.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg-parallel_squoosh_oxipng_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/node_modules_jsquash_oxipng_codec_pkg_squoosh_oxipng_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_codec_enc_avif_enc_js.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_codec_enc_avif_enc_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_codec_enc_avif_enc_mt_js.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_codec_enc_avif_enc_mt_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-29c710.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-515c76.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-515c76.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-55a88c.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-88b2ac.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_jpeg_decode_js-node_modules_jsquash_jpeg_encode_js-node_modules_-72a791.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_jpeg_decode_js-node_modules_jsquash_jpeg_encode_js-node_modules_-9c2145.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_oxipng_codec_pkg-parallel_squoosh_oxipng_js.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_oxipng_codec_pkg-parallel_squoosh_oxipng_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_oxipng_codec_pkg_squoosh_oxipng_js.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_oxipng_codec_pkg_squoosh_oxipng_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_webp_codec_enc_webp_enc_js.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_webp_codec_enc_webp_enc_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_webp_codec_enc_webp_enc_simd_js.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_jsquash_webp_codec_enc_webp_enc_simd_js.script.bundle.js (added)
-
tags/1.7.0/assets/js/vendors-node_modules_piexifjs_piexif_js-node_modules_jsquash_avif_decode_js-node_modules_jsqu-2d8528.bundle.js (added)
-
tags/1.7.0/assets/templates (added)
-
tags/1.7.0/assets/templates/directory-item-empty.html (added)
-
tags/1.7.0/assets/templates/directory-item.html (added)
-
tags/1.7.0/assets/templates/log-details-button.html (added)
-
tags/1.7.0/assets/templates/log-step.html (added)
-
tags/1.7.0/assets/templates/log-wrapper.html (added)
-
tags/1.7.0/assets/templates/path-list-item.html (added)
-
tags/1.7.0/inc (added)
-
tags/1.7.0/inc/handlers.php (added)
-
tags/1.7.0/inc/helpers.php (added)
-
tags/1.7.0/inc/settings.php (added)
-
tags/1.7.0/languages (added)
-
tags/1.7.0/languages/squeeze-uk-0282bc9bb3139ae7f3090194c10090b4.json (added)
-
tags/1.7.0/languages/squeeze-uk-08ec2477f322448a2db534074ac234a4.json (added)
-
tags/1.7.0/languages/squeeze-uk-1c72eced88847462c7e0967d0b7e5a17.json (added)
-
tags/1.7.0/languages/squeeze-uk-24b88c172a2803f6ee0c4956b1a8afb1.json (added)
-
tags/1.7.0/languages/squeeze-uk-6ae642d7d2342ed41f24938c32a6f536.json (added)
-
tags/1.7.0/languages/squeeze-uk-81ea56f743cbb228777c5cd8e3e8aac3.json (added)
-
tags/1.7.0/languages/squeeze-uk-8a8cc8d6792f201000247ed42d4140e8.json (added)
-
tags/1.7.0/languages/squeeze-uk-ac76f1d75eb777f747e6708b19d31b78.json (added)
-
tags/1.7.0/languages/squeeze-uk-b1f8d5e52cbbc262494fff20eec962fd.json (added)
-
tags/1.7.0/languages/squeeze-uk-e28a2098475e8c88fb444548eea784e3.json (added)
-
tags/1.7.0/languages/squeeze-uk-e9cc8298549e98be96351e6176bc85d5.json (added)
-
tags/1.7.0/languages/squeeze-uk-ebfe0cea630778e3fc5018cec6e46aac.json (added)
-
tags/1.7.0/languages/squeeze-uk-f98be19bec7bc848ce3ed383c60037c1.json (added)
-
tags/1.7.0/languages/squeeze-uk-ff025606f2061c02a097c943a471265d.json (added)
-
tags/1.7.0/languages/squeeze-uk.mo (added)
-
tags/1.7.0/languages/squeeze-uk.po (added)
-
tags/1.7.0/languages/squeeze.pot (added)
-
tags/1.7.0/readme.txt (added)
-
tags/1.7.0/squeeze.php (added)
-
trunk/assets/css/admin.css (modified) (5 diffs)
-
trunk/assets/css/admin.css.map (modified) (1 diff)
-
trunk/assets/css/admin.less (modified) (5 diffs)
-
trunk/assets/images/replace_urls.jpg (added)
-
trunk/assets/js/0.bundle.js (added)
-
trunk/assets/js/1.bundle.js (added)
-
trunk/assets/js/2.bundle.js (added)
-
trunk/assets/js/3.bundle.js (added)
-
trunk/assets/js/admin.bundle.js (modified) (7 diffs)
-
trunk/assets/js/assets_js_worker_js.bundle.js (modified) (3 diffs)
-
trunk/assets/js/editor.bundle.js (modified) (8 diffs)
-
trunk/assets/js/script.bundle.js (modified) (8 diffs)
-
trunk/assets/js/vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-88b2ac.bundle.js (added)
-
trunk/assets/js/vendors-node_modules_piexifjs_piexif_js-node_modules_jsquash_avif_decode_js-node_modules_jsqu-2d8528.bundle.js (added)
-
trunk/assets/templates/path-list-item.html (modified) (1 diff)
-
trunk/inc/handlers.php (modified) (9 diffs)
-
trunk/inc/helpers.php (modified) (12 diffs)
-
trunk/inc/settings.php (modified) (15 diffs)
-
trunk/languages/squeeze-uk-0282bc9bb3139ae7f3090194c10090b4.json (modified) (3 diffs)
-
trunk/languages/squeeze-uk-08ec2477f322448a2db534074ac234a4.json (modified) (1 diff)
-
trunk/languages/squeeze-uk-1c72eced88847462c7e0967d0b7e5a17.json (added)
-
trunk/languages/squeeze-uk-24b88c172a2803f6ee0c4956b1a8afb1.json (modified) (3 diffs)
-
trunk/languages/squeeze-uk-6ae642d7d2342ed41f24938c32a6f536.json (added)
-
trunk/languages/squeeze-uk-81ea56f743cbb228777c5cd8e3e8aac3.json (added)
-
trunk/languages/squeeze-uk-8a8cc8d6792f201000247ed42d4140e8.json (modified) (3 diffs)
-
trunk/languages/squeeze-uk-ac76f1d75eb777f747e6708b19d31b78.json (added)
-
trunk/languages/squeeze-uk-b1f8d5e52cbbc262494fff20eec962fd.json (modified) (1 diff)
-
trunk/languages/squeeze-uk-e28a2098475e8c88fb444548eea784e3.json (added)
-
trunk/languages/squeeze-uk-e9cc8298549e98be96351e6176bc85d5.json (modified) (2 diffs)
-
trunk/languages/squeeze-uk-ebfe0cea630778e3fc5018cec6e46aac.json (modified) (1 diff)
-
trunk/languages/squeeze-uk-f98be19bec7bc848ce3ed383c60037c1.json (modified) (3 diffs)
-
trunk/languages/squeeze-uk-ff025606f2061c02a097c943a471265d.json (added)
-
trunk/languages/squeeze-uk.mo (modified) (previous)
-
trunk/languages/squeeze-uk.po (modified) (18 diffs)
-
trunk/languages/squeeze.pot (modified) (8 diffs)
-
trunk/readme.txt (modified) (13 diffs)
-
trunk/squeeze.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
squeeze/trunk/assets/css/admin.css
r3311866 r3345284 382 382 margin-inline-start: 0.5em; 383 383 } 384 .squeeze-settings-example { 385 max-width: fit-content; 386 display: inline-block; 387 margin-inline-start: var(--squeeze-spacing-m); 388 /*opacity: 0.5; 389 390 &.enabled { 391 opacity: 1; 392 }*/ 393 } 394 .squeeze-settings-example.squeeze-settings-example--webp_replace_urls { 395 display: block; 396 margin-inline-start: 0; 397 margin-top: var(--squeeze-spacing-m); 398 } 399 .squeeze-settings-example .squeeze-box--fieldset { 400 display: flex; 401 gap: var(--squeeze-spacing-m); 402 } 403 .squeeze-settings-example .squeeze-box--fieldset .squeeze-box-content { 404 gap: var(--squeeze-spacing-s); 405 } 406 .squeeze-settings-example .squeeze-box--fieldset .squeeze-box-content p { 407 display: flex; 408 justify-content: space-between; 409 gap: var(--squeeze-spacing-m); 410 } 411 .squeeze-settings-example .squeeze-box--fieldset .squeeze-box-content .striked { 412 text-decoration: line-through; 413 color: var(--squeeze-error-color); 414 } 415 .squeeze-settings-example .squeeze-box--fieldset .squeeze-box-content .greened { 416 color: var(--squeeze-success-color); 417 } 418 .squeeze-settings-example .squeeze-box--fieldset .squeeze-box-content img { 419 max-width: 100%; 420 height: auto; 421 } 384 422 .form-table tr.squeeze_setting_restore_defaults { 385 423 display: none; … … 387 425 .form-table tr:has(.squeeze-hidden) { 388 426 display: none; 427 } 428 .form-table tr.squeeze-legacy-option { 429 opacity: 0.5; 430 } 431 .form-table tr.squeeze-legacy-option:hover { 432 opacity: 1; 389 433 } 390 434 .js .squeeze-single-file-upload-notice:has(+ .html-uploader) { … … 466 510 gap: var(--squeeze-spacing-s); 467 511 } 468 .squeeze-path-list input[type="text"].squeeze-path-list__i tem{512 .squeeze-path-list input[type="text"].squeeze-path-list__input { 469 513 min-width: 15rem; 470 514 font-family: monospace; … … 473 517 background-color: var(--squeeze-border-color); 474 518 padding: var(--squeeze-spacing-xs) var(--squeeze-spacing-s); 519 } 520 .squeeze-path-list__item { 521 position: relative; 522 display: flex; 523 align-items: center; 524 gap: var(--squeeze-spacing-s); 525 } 526 .squeeze-path-list__remove { 527 background: none; 528 border: 0; 529 padding: 0; 530 cursor: pointer; 531 color: var(--squeeze-error-color); 532 width: 1.5rem; 533 height: 1.5rem; 534 } 535 .squeeze-path-list__remove:disabled { 536 opacity: 0.5; 537 cursor: not-allowed; 538 } 539 .squeeze-path-list__remove .squeeze-icon { 540 width: 1.5rem; 541 height: 1.5rem; 542 fill: currentColor; 475 543 } 476 544 .media-log-wrapper { … … 622 690 width: auto; 623 691 } 692 body.settings_page_squeeze-account .nav-tab[href*="#squeeze_account"] { 693 display: none !important; 694 } 695 body.media_page_squeeze-bulk .wrap .nav-tab-wrapper { 696 display: none !important; 697 } 624 698 /*# sourceMappingURL=admin.css.map */ -
squeeze/trunk/assets/css/admin.css.map
r3311866 r3345284 1 {"version":3,"sources":["admin.less"],"names":[],"mappings":"AAAA;EACI,yBAAyB,oCAAzB;EACA,kCAAA;EACA,gCAAA;EACA,gCAAA;EACA,8BAAA;EACA,8BAAA;EACA,4BAAA;EACA,+BAAA;EACA,8BAAA;EACA,6BAAA;EACA,uCAAA;EACA,2BAAA;EACA,0BAAA;EACA,6BAAA;EACA,uCAAA;EACA,wDAAA;EACA,8DAAA;EACA,0DAAA;EACA,mCAAA;EACA,4BAAA;EACA,2BAAA;EACA,yBAAA;EACA,2BAAA;EACA,6BAAA;EACA,kCAAA;EACA,qCAAA;EACA,uCAAA;EAEA,uBAAA;EACA,sBAAA;;AAGJ;EAEI;IAAK,2BAAA;;;AAGT;EACI;IAAK,WAAW,cAAX;;;AAGT,YAAa,KAAI;EACb,mBAAA;;AAGJ;EACI,kBAAkB,wBAAlB;EACA,eAAe,4BAAf;EACA,eAAe,wBAAf;EACA,SAAS,wBAAT;EACA,kBAAA;EACA,YAAY,yBAAZ;;;;AAEA,YAAC,YAAC;EACE,yBAAA;EACA,0BAAA;;AAGJ,YAAC;EACG,eAAe,kCAAf;EACA,YAAY,+BAAZ;EACA,kBAAkB,0BAAlB;EACA,qBAAA;;AAJJ,YAAC,UAMG;EACI,KAAK,wBAAL;;AAIR,YAAC;AAAS,YAAC;EACP,aAAA;EACA,8BAAA;EACA,mBAAA;EACA,gBAAgB,wBAAhB;EACA,yBAAyB,2BAAzB;;AALJ,YAAC,OAOG;AAPM,YAAC,OAOP;EACI,SAAA;EACA,WAAW,gCAAX;EACA,gBAAA;;AAGJ,YAbH,OAaI;AAAD,YAbO,OAaN;EACG,aAAA;EACA,KAAK,wBAAL;EACA,sBAAA;;AAIR,YAAC;EACG,aAAa,wBAAb;EACA,iBAAA;EACA,mBAAA;EACA,sBAAsB,2BAAtB;;AAGJ,YAAC;EACG,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAEA,YALH,QAKI;EACG,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,8BAAA;EACA,eAAA;;AAGJ,YAbH,QAaI;EACG,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAIR,YAAC;EACG,aAAA;EACA,uBAAuB,UAAU,mBAAjC;EACA,UAAU,yBAAV;;AAEA,QAA0B;EAA1B,YALH;IAMO,0BAAA;;;AAGJ,YATH,UASI;EACG,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,kBAAA;;AAEA,YAfP,UASI,KAMI,IAAI,eAAe;EAChB,SAAS,EAAT;EACA,kBAAA;EACA,MAAA;EACA,OAAO,KAAK,+BAAZ;EACA,SAAA;EACA,uBAAuB,2BAAvB;;AAIR,YAzBH,UAyBI;EACG,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,8BAAA;EACA,mBAAA;EACA,kBAAA;;AAEA,YAjCP,UAyBI,KAQI;EACG,SAAS,EAAT;EACA,kBAAA;EACA,KAAK,KAAK,+BAAV;EACA,QAAA;EACA,OAAA;EACA,sBAAsB,2BAAtB;;AAMZ,YAAC;EACG,mBAAA;;AADJ,YAAC,UAGG;EACI,2BAAA;;AAxHZ,YA6HI,MACI;EACI,YAAY,yBAAZ;;AA/HZ,YAmII;EACI,oBAAA;;AApIR,YAuII,MAAK;AAvIT,YAwII,MAAK;AAxIT,YAyII,MAAK;AAzIT,YA0II,MAAK;AA1IT,YA2II;AA3IJ,YA4II;EACI,kBAAkB,2BAAlB;EACA,oBAAA;;AA9IR,YAiJI;EACI,eAAA;EACA,WAAA;EACA,eAAe,kCAAf;;AApJR,YAuJI,MAAK;EACD,6BAAA;EACA,sBAAA;EACA,cAAc,4BAAd;;AAEA,YALJ,MAAK,cAKA;EAEG,kBAAkB,2BAAlB;EACA,QAAQ,sBAAR;;AAEJ,YAVJ,MAAK,cAUA;EAEG,kBAAkB,2BAAlB;EACA,QAAQ,sBAAR;;AAGJ,YAhBJ,MAAK,cAgBA;EACG,YAAY,4BAAZ;EACA,kBAAA;EACA,YAAY,KAAK,4BAAjB;EACA,YAAY,gCAAZ;;AAEJ,YAtBJ,MAAK,cAsBA;EACG,YAAY,4BAAZ;EACA,kBAAA;EACA,YAAY,KAAK,4BAAjB;EACA,YAAY,gCAAZ;;AAEJ,YA5BJ,MAAK,cA4BA;EACG,YAAY,4BAAZ;;AAGJ,YAhCJ,MAAK,cAgCC;EACE,sBAAA;EACA,0BAAA;;AAzLZ,YA6LI;EACI,aAAA;EACA,eAAe,wBAAf;;AAEA,YAJJ,EAIK;EACG,gBAAA;;AAlMZ,YAsMI,sBAEI;AAxMR,YAuMI,kCACI;EACI,MAAM,0BAAN;;AAMR,aAAC;EACG,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;;AAEA,aALH,YAKI;EACG,aAAA;EACA,KAAK,wBAAL;EACA,sBAAA;;AAEA,aAVP,YAKI,KAKI;EACG,WAAW,iCAAX;EACA,gBAAA;;AAGJ,aAfP,YAKI,KAUI,MACG;EACI,4CAAA;;AAMZ,aAvBH,YAuBI;EACG,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,kBAAA;EACA,yBAAA;;AAEA,aA9BP,YAuBI,MAOI;EACG,QAAQ,0BAAR;EACA,cAAc,0BAAd;;AAGJ,aAnCP,YAuBI,MAYI;EACG,QAAQ,4BAAR;EACA,cAAc,KAAK,+BAAnB;EACA,qBAAA;EAEA,kBAAkB,mCAAlB;EAEA,WAAW,cAAX;EACA,wBAAA;EACA,QAAQ,0CAA0C,0CAAlD;EACA,8CAAA;EACA,yCAAA;;AAGJ,aAjDP,YAuBI,MA0BI;EACG,WAAW,iCAAX;;AAMhB;EACI,WAAA;EACA,YAAA;EACA,MAAM,4BAAN;EACA,2BAAA;EACA,0BAAA;;AAGJ;EACI,WAAW,mCAAX;EACA,OAAO,mCAAP;EACA,cAAA;EACA,eAAA;;AAGJ;EACI,kBAAkB,8BAAlB;EACA,OAAO,yBAAP;EACA,SAAS,wBAAT;EACA,eAAe,kCAAf;EACA,aAAA;EACA,8BAAA;;AAEA,eAAC,eAAC;EACE,kBAAkB,4BAAlB;;AAGJ,eAAC,SACG;EACI,WAAW,iCAAX;;AAdZ,eAkBI;EACI,MAAM,yBAAN;EACA,cAAA;EACA,aAAA;EACA,SAAA;EACA,SAAA;;AAIR;EACI,aAAA;EACA,cAAA;EACA,kBAAkB,0BAAlB;EACA,qBAAA;;AAEA,iBAAC,IAAI;EACD,aAAA;;AAIR,iBAAkB;EACd,qBAAA;;AAEJ;EACI,qBAAA;EACA,WAAA;;AAGJ;EACI,sBAAA;EACA,OAAO,mCAAP;EACA,WAAW,gCAAX;EACA,kBAAA;;AAEA,wBAAE;EACE,YAAY,wBAAZ;;AAKR,KAAK,iBAAiB;EAClB,kBAAA;EACA,UAAA;EACA,QAAQ,4BAA4B,KAAK,4BAAzC;;AAEA,KALC,iBAAiB,oBAKhB;EACE,kBAAA;EACA,eAAe,KAAK,4BAApB;EACA,aAAa,KAAK,gCAAlB;;AAEA,KAVH,iBAAiB,oBAKhB,QAKG;EACG,SAAS,EAAT;EACA,kBAAA;EACA,cAAA;EACA,OAAA;EACA,MAAA;EACA,OAAO,KAAK,4BAAZ;;EACA,QAAQ,KAAK,4BAAb;;EACA,eAAe,KAAK,4BAApB;;EACA,YAAY,0BAAZ;EACA,kBAAkB,2BAAlB;EACA,oBAAA;;AAGJ,KAxBH,iBAAiB,oBAKhB,QAmBG;EACG,SAAS,EAAT;EACA,kBAAA;EACA,cAAA;EACA,SAAA;EACA,QAAA;EACA,OAAO,KAAK,4BAAZ;;EACA,QAAQ,KAAK,4BAAb;;EACA,eAAe,KAAK,4BAApB;;EACA,YAAY,0BAAZ;EACA,kBAAkB,2BAAlB;EACA,oBAAA;;AAEJ,KArCH,iBAAiB,oBAKhB,QAgCG,MAAM;EACH,YAAY,gCAAZ;;AAKA,KA3CP,iBAAiB,oBAyCjB,QACK,QACG;EACG,aAAa,KAAK,4BAAlB;;AAEJ,KA9CP,iBAAiB,oBAyCjB,QACK,QAIG;EACG,YAAY,4BAAZ;;AAMJ,KArDP,iBAAiB,oBAmDjB,cACK,QACG;EACG,YAAY,gCAAZ;;AAQJ,KA9DP,iBAAiB,oBA0DjB,SACK,QAGG;AAAS,KA9DjB,iBAAiB,oBA0DjB,SACK,QAGa;EACP,YAAA;;AAOhB;EACI,kBAAA;;AAEJ;EACI,0BAAA;;AAEJ ,WACI,GAAE;EACE,aAAA;;AAFR,WAII,GAAE,IAAI;EACF,aAAA;;AAIR,GAAI,mCAAkC,IAAI;EACtC,cAAA;;AAGJ;EACI,SAAS,wBAAT;EACA,YAAA;EACA,eAAe,4BAAf;EACA,YAAA;EACA,eAAA;EACA,YAAY,yBAAZ;EACA,gBAAA;;AAPJ,oBASI;EACI,gBAAgB,wBAAhB;;AAVR,oBAaI,0CACI;EACI,MAAM,yBAAN;EACA,SAAA;;AAhBZ,oBAoBI;EACI,WAAA;;AAGR;EACI,gBAAA;EACA,cAAA;EACA,SAAS,0BAAT;;AAHJ,4BAKI;EACI,4CAAA;;AAGR;EACI,aAAA;EACA,uBAAA;EACA,KAAK,wBAAL;EACA,sBAAA;;AAEA,eAAE,gBAAC;EACC,aAAA;EACA,mBAAA;EACA,KAAK,wBAAL;;AAEA,eALF,gBAAC,OAKG;EACE,cAAc,wBAAd;EACA,+DAAA;EACA,wCAAA;EACA,4BAAA;EACA,iBAAiB,wBAAjB;;AAIR,eAAC;EACG,YAAA;;AAGJ,eAAE;EACE,cAAc,wBAAd;;AAIA,eADH,IAAI,SACC;EACE,aAAA;;AAMA,eAFP,OACK,yBACI;EACE,8DAAA;;AArChB,eA0CI;EACI,eAAA;EACA,0BAAA;EACA,4BAAA;EACA,6BAAA;;AAEA,eANJ,MAMK;EACG,OAAO,4BAAP;;AAjDZ,eAqDI,MAAK;AArDT,eAqD4B,MAAK;EACzB,SAAA;;AAKR;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAEA,kBAAE,MAAK,aAAa,kBAAC;EACjB,gBAAA;EACA,sBAAA;EACA,SAAA;EACA,gBAAA;EACA,kBAAkB,2BAAlB;EACA,SAAS,0BAA0B,wBAAnC;;AAIR;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,SAAS,wBAAT;EACA,eAAe,kCAAf;EACA,kBAAkB,0BAAlB;EACA,kBAAA;;AAPJ,kBASI;EACI,SAAA;EACA,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,kBAAA;EACA,UAAA;;AAfR,kBASI,GAQI;EACI,SAAA;EACA,aAAA;EACA,cAAA;;AApBZ,kBAuBI;EACI,sBAAA;;AAxBR,kBA0BI;EACI,aAAA;;AAEA,kBAHJ,0BAGK;EACG,cAAA;;AA9BZ,kBAiCI,MAAK;EACD,SAAA;EACA,sBAAsB,2BAAtB;EACA,yBAAyB,2BAAzB;;AAIR;EACI,aAAA;EACA,KAAK,yBAAL;EACA,kBAAA;EACA,sBAAsB,yBAAtB;EACA,kBAAA;;AAEA,kBAAC;EACG,SAAS,EAAT;EACA,kBAAA;EACA,WAAA;EACA,aAAA;EACA,QAAA;EACA,kBAAA;EACA,QAAQ,wBAAwB,yBAAhC;EACA,uBAAuB,2BAAvB;EACA,yBAAyB,2BAAzB;EACA,2BAA2B,4BAA3B;EACA,YAAY,yBAAZ;;AAEJ,kBAAC;EACG,SAAS,EAAT;EACA,kBAAA;EACA,WAAA;EACA,QAAA;EACA,aAAA;EACA,cAAA;EACA,kBAAkB,2BAAlB;EACA,kBAAA;EACA,oBAAA;;AAIR;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,kBAAA;;AALJ,eAOI;EACI,MAAM,4BAAN;EACA,SAAA;;AAEA,eAJJ,cAIK;EACG,MAAM,4BAAN;;AAEJ,eAPJ,cAOK;EACG,MAAM,0BAAN;;AAfZ,eAmBI;EACI,WAAW,iCAAX;EACA,OAAO,mCAAP;;AAGR;EACI,kBAAA;EACA,OAAO,wBAAP;EACA,QAAQ,wBAAR;EACA,KAAK,wBAAL;EACA,gBAAA;;AALJ,oBAOI;EACI,YAAA;EACA,WAAA;;AAIR;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAGJ,yBAA0B,MAAM;EAAI,kBAAA;;AAEpC;EACI,OAAO,0BAAP;EACA,SAAS,0BAA0B,wBAAnC;EACA,sBAAA;EACA,kBAAA;EACA,mBAAA;;AAEA,sBAAC;EACG,kBAAkB,4BAAlB;;AAEA,sBAHH,yBAGI;EACG,SAAS,OAAT;EACA,kBAAA;EACA,0BAAA;;AAIR,sBAAC;EACG,kBAAkB,0BAAlB;;AAEA,sBAHH,yBAGI;EACG,SAAS,OAAT;EACA,kBAAA;EACA,0BAAA;;;AAKZ,sBAAuB;EACnB,kBAAA;;AAEA,sBAHmB,uBAGjB;EACE,kBAAA;EACA,UAAA;;AAEA,sBAPe,uBAGjB,WAIG;EACG,oBAAA;;AADJ,sBAPe,uBAGjB,WAIG,QAGG;EACI,YAAA;;AAKhB;EACI,kBAAA;;AAEA,oBAAE,EAAC;EACC,kBAAA;EACA,UAAA;;AAEA,oBAJF,EAAC,sBAIE;EACG,oBAAA;;AAIZ;EACI,kBAAA;EACA,MAAA;EACA,SAAA;EACA,WAAA;;AAEJ;EACI,kBAAA;EACA,aAAA;;;AAIJ;EACI,aAAA;EACA,KAAK,wBAAL;EACA,gBAAA;;AAEA,yBAAE;EACE,OAAA;EACA,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,SAAS,wBAAT;;AANJ,yBAAE,IAQE;EACI,WAAA;EACA,WAAA","file":"admin.css"}1 {"version":3,"sources":["admin.less"],"names":[],"mappings":"AAAA;EACI,yBAAyB,oCAAzB;EACA,kCAAA;EACA,gCAAA;EACA,gCAAA;EACA,8BAAA;EACA,8BAAA;EACA,4BAAA;EACA,+BAAA;EACA,8BAAA;EACA,6BAAA;EACA,uCAAA;EACA,2BAAA;EACA,0BAAA;EACA,6BAAA;EACA,uCAAA;EACA,wDAAA;EACA,8DAAA;EACA,0DAAA;EACA,mCAAA;EACA,4BAAA;EACA,2BAAA;EACA,yBAAA;EACA,2BAAA;EACA,6BAAA;EACA,kCAAA;EACA,qCAAA;EACA,uCAAA;EAEA,uBAAA;EACA,sBAAA;;AAGJ;EAEI;IAAK,2BAAA;;;AAGT;EACI;IAAK,WAAW,cAAX;;;AAGT,YAAa,KAAI;EACb,mBAAA;;AAGJ;EACI,kBAAkB,wBAAlB;EACA,eAAe,4BAAf;EACA,eAAe,wBAAf;EACA,SAAS,wBAAT;EACA,kBAAA;EACA,YAAY,yBAAZ;;;;AAEA,YAAC,YAAC;EACE,yBAAA;EACA,0BAAA;;AAGJ,YAAC;EACG,eAAe,kCAAf;EACA,YAAY,+BAAZ;EACA,kBAAkB,0BAAlB;EACA,qBAAA;;AAJJ,YAAC,UAMG;EACI,KAAK,wBAAL;;AAIR,YAAC;AAAS,YAAC;EACP,aAAA;EACA,8BAAA;EACA,mBAAA;EACA,gBAAgB,wBAAhB;EACA,yBAAyB,2BAAzB;;AALJ,YAAC,OAOG;AAPM,YAAC,OAOP;EACI,SAAA;EACA,WAAW,gCAAX;EACA,gBAAA;;AAGJ,YAbH,OAaI;AAAD,YAbO,OAaN;EACG,aAAA;EACA,KAAK,wBAAL;EACA,sBAAA;;AAIR,YAAC;EACG,aAAa,wBAAb;EACA,iBAAA;EACA,mBAAA;EACA,sBAAsB,2BAAtB;;AAGJ,YAAC;EACG,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAEA,YALH,QAKI;EACG,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,8BAAA;EACA,eAAA;;AAGJ,YAbH,QAaI;EACG,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAIR,YAAC;EACG,aAAA;EACA,uBAAuB,UAAU,mBAAjC;EACA,UAAU,yBAAV;;AAEA,QAA0B;EAA1B,YALH;IAMO,0BAAA;;;AAGJ,YATH,UASI;EACG,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,kBAAA;;AAEA,YAfP,UASI,KAMI,IAAI,eAAe;EAChB,SAAS,EAAT;EACA,kBAAA;EACA,MAAA;EACA,OAAO,KAAK,+BAAZ;EACA,SAAA;EACA,uBAAuB,2BAAvB;;AAIR,YAzBH,UAyBI;EACG,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,8BAAA;EACA,mBAAA;EACA,kBAAA;;AAEA,YAjCP,UAyBI,KAQI;EACG,SAAS,EAAT;EACA,kBAAA;EACA,KAAK,KAAK,+BAAV;EACA,QAAA;EACA,OAAA;EACA,sBAAsB,2BAAtB;;AAMZ,YAAC;EACG,mBAAA;;AADJ,YAAC,UAGG;EACI,2BAAA;;AAxHZ,YA6HI,MACI;EACI,YAAY,yBAAZ;;AA/HZ,YAmII;EACI,oBAAA;;AApIR,YAuII,MAAK;AAvIT,YAwII,MAAK;AAxIT,YAyII,MAAK;AAzIT,YA0II,MAAK;AA1IT,YA2II;AA3IJ,YA4II;EACI,kBAAkB,2BAAlB;EACA,oBAAA;;AA9IR,YAiJI;EACI,eAAA;EACA,WAAA;EACA,eAAe,kCAAf;;AApJR,YAuJI,MAAK;EACD,6BAAA;EACA,sBAAA;EACA,cAAc,4BAAd;;AAEA,YALJ,MAAK,cAKA;EAEG,kBAAkB,2BAAlB;EACA,QAAQ,sBAAR;;AAEJ,YAVJ,MAAK,cAUA;EAEG,kBAAkB,2BAAlB;EACA,QAAQ,sBAAR;;AAGJ,YAhBJ,MAAK,cAgBA;EACG,YAAY,4BAAZ;EACA,kBAAA;EACA,YAAY,KAAK,4BAAjB;EACA,YAAY,gCAAZ;;AAEJ,YAtBJ,MAAK,cAsBA;EACG,YAAY,4BAAZ;EACA,kBAAA;EACA,YAAY,KAAK,4BAAjB;EACA,YAAY,gCAAZ;;AAEJ,YA5BJ,MAAK,cA4BA;EACG,YAAY,4BAAZ;;AAGJ,YAhCJ,MAAK,cAgCC;EACE,sBAAA;EACA,0BAAA;;AAzLZ,YA6LI;EACI,aAAA;EACA,eAAe,wBAAf;;AAEA,YAJJ,EAIK;EACG,gBAAA;;AAlMZ,YAsMI,sBAEI;AAxMR,YAuMI,kCACI;EACI,MAAM,0BAAN;;AAMR,aAAC;EACG,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;;AAEA,aALH,YAKI;EACG,aAAA;EACA,KAAK,wBAAL;EACA,sBAAA;;AAEA,aAVP,YAKI,KAKI;EACG,WAAW,iCAAX;EACA,gBAAA;;AAGJ,aAfP,YAKI,KAUI,MACG;EACI,4CAAA;;AAMZ,aAvBH,YAuBI;EACG,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,kBAAA;EACA,yBAAA;;AAEA,aA9BP,YAuBI,MAOI;EACG,QAAQ,0BAAR;EACA,cAAc,0BAAd;;AAGJ,aAnCP,YAuBI,MAYI;EACG,QAAQ,4BAAR;EACA,cAAc,KAAK,+BAAnB;EACA,qBAAA;EAEA,kBAAkB,mCAAlB;EAEA,WAAW,cAAX;EACA,wBAAA;EACA,QAAQ,0CAA0C,0CAAlD;EACA,8CAAA;EACA,yCAAA;;AAGJ,aAjDP,YAuBI,MA0BI;EACG,WAAW,iCAAX;;AAMhB;EACI,WAAA;EACA,YAAA;EACA,MAAM,4BAAN;EACA,2BAAA;EACA,0BAAA;;AAGJ;EACI,WAAW,mCAAX;EACA,OAAO,mCAAP;EACA,cAAA;EACA,eAAA;;AAGJ;EACI,kBAAkB,8BAAlB;EACA,OAAO,yBAAP;EACA,SAAS,wBAAT;EACA,eAAe,kCAAf;EACA,aAAA;EACA,8BAAA;;AAEA,eAAC,eAAC;EACE,kBAAkB,4BAAlB;;AAGJ,eAAC,SACG;EACI,WAAW,iCAAX;;AAdZ,eAkBI;EACI,MAAM,yBAAN;EACA,cAAA;EACA,aAAA;EACA,SAAA;EACA,SAAA;;AAIR;EACI,aAAA;EACA,cAAA;EACA,kBAAkB,0BAAlB;EACA,qBAAA;;AAEA,iBAAC,IAAI;EACD,aAAA;;AAIR,iBAAkB;EACd,qBAAA;;AAEJ;EACI,qBAAA;EACA,WAAA;;AAGJ;EACI,sBAAA;EACA,OAAO,mCAAP;EACA,WAAW,gCAAX;EACA,kBAAA;;AAEA,wBAAE;EACE,YAAY,wBAAZ;;AAKR,KAAK,iBAAiB;EAClB,kBAAA;EACA,UAAA;EACA,QAAQ,4BAA4B,KAAK,4BAAzC;;AAEA,KALC,iBAAiB,oBAKhB;EACE,kBAAA;EACA,eAAe,KAAK,4BAApB;EACA,aAAa,KAAK,gCAAlB;;AAEA,KAVH,iBAAiB,oBAKhB,QAKG;EACG,SAAS,EAAT;EACA,kBAAA;EACA,cAAA;EACA,OAAA;EACA,MAAA;EACA,OAAO,KAAK,4BAAZ;;EACA,QAAQ,KAAK,4BAAb;;EACA,eAAe,KAAK,4BAApB;;EACA,YAAY,0BAAZ;EACA,kBAAkB,2BAAlB;EACA,oBAAA;;AAGJ,KAxBH,iBAAiB,oBAKhB,QAmBG;EACG,SAAS,EAAT;EACA,kBAAA;EACA,cAAA;EACA,SAAA;EACA,QAAA;EACA,OAAO,KAAK,4BAAZ;;EACA,QAAQ,KAAK,4BAAb;;EACA,eAAe,KAAK,4BAApB;;EACA,YAAY,0BAAZ;EACA,kBAAkB,2BAAlB;EACA,oBAAA;;AAEJ,KArCH,iBAAiB,oBAKhB,QAgCG,MAAM;EACH,YAAY,gCAAZ;;AAKA,KA3CP,iBAAiB,oBAyCjB,QACK,QACG;EACG,aAAa,KAAK,4BAAlB;;AAEJ,KA9CP,iBAAiB,oBAyCjB,QACK,QAIG;EACG,YAAY,4BAAZ;;AAMJ,KArDP,iBAAiB,oBAmDjB,cACK,QACG;EACG,YAAY,gCAAZ;;AAQJ,KA9DP,iBAAiB,oBA0DjB,SACK,QAGG;AAAS,KA9DjB,iBAAiB,oBA0DjB,SACK,QAGa;EACP,YAAA;;AAOhB;EACI,kBAAA;;AAEJ;EACI,0BAAA;;AAEJ;EACI,sBAAA;EACA,qBAAA;EACA,qBAAqB,wBAArB;;;;;;;AAOA,yBAAC,yBAAC;EACE,cAAA;EACA,sBAAA;EACA,YAAY,wBAAZ;;AAbR,yBAgBI;EACI,aAAA;EACA,KAAK,wBAAL;;AAlBR,yBAgBI,uBAII;EACI,KAAK,wBAAL;;AArBZ,yBAgBI,uBAII,qBAGI;EACI,aAAA;EACA,8BAAA;EACA,KAAK,wBAAL;;AA1BhB,yBAgBI,uBAII,qBAQI;EACI,6BAAA;EACA,OAAO,0BAAP;;AA9BhB,yBAgBI,uBAII,qBAYI;EACI,OAAO,4BAAP;;AAjChB,yBAgBI,uBAII,qBAeI;EACI,eAAA;EACA,YAAA;;AAKhB,WACI,GAAE;EACE,aAAA;;AAFR,WAII,GAAE,IAAI;EACF,aAAA;;AALR,WAOI,GAAE;EACE,YAAA;;AAEA,WAHJ,GAAE,sBAGG;EACG,UAAA;;AAKZ,GAAI,mCAAkC,IAAI;EACtC,cAAA;;AAGJ;EACI,SAAS,wBAAT;EACA,YAAA;EACA,eAAe,4BAAf;EACA,YAAA;EACA,eAAA;EACA,YAAY,yBAAZ;EACA,gBAAA;;AAPJ,oBASI;EACI,gBAAgB,wBAAhB;;AAVR,oBAaI,0CACI;EACI,MAAM,yBAAN;EACA,SAAA;;AAhBZ,oBAoBI;EACI,WAAA;;AAGR;EACI,gBAAA;EACA,cAAA;EACA,SAAS,0BAAT;;AAHJ,4BAKI;EACI,4CAAA;;AAGR;EACI,aAAA;EACA,uBAAA;EACA,KAAK,wBAAL;EACA,sBAAA;;AAEA,eAAE,gBAAC;EACC,aAAA;EACA,mBAAA;EACA,KAAK,wBAAL;;AAEA,eALF,gBAAC,OAKG;EACE,cAAc,wBAAd;EACA,+DAAA;EACA,wCAAA;EACA,4BAAA;EACA,iBAAiB,wBAAjB;;AAIR,eAAC;EACG,YAAA;;AAGJ,eAAE;EACE,cAAc,wBAAd;;AAIA,eADH,IAAI,SACC;EACE,aAAA;;AAMA,eAFP,OACK,yBACI;EACE,8DAAA;;AArChB,eA0CI;EACI,eAAA;EACA,0BAAA;EACA,4BAAA;EACA,6BAAA;;AAEA,eANJ,MAMK;EACG,OAAO,4BAAP;;AAjDZ,eAqDI,MAAK;AArDT,eAqD4B,MAAK;EACzB,SAAA;;AAKR;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAEA,kBAAE,MAAK,aAAa,kBAAC;EACjB,gBAAA;EACA,sBAAA;EACA,SAAA;EACA,gBAAA;EACA,kBAAkB,2BAAlB;EACA,SAAS,0BAA0B,wBAAnC;;AAGJ,kBAAC;EACG,kBAAA;EACA,aAAA;EACA,mBAAA;EACA,KAAK,wBAAL;;AAGJ,kBAAC;EACG,gBAAA;EACA,SAAA;EACA,UAAA;EACA,eAAA;EACA,OAAO,0BAAP;EACA,aAAA;EACA,cAAA;;AAEA,kBATH,QASI;EACG,YAAA;EACA,mBAAA;;AAXR,kBAAC,QAcG;EACI,aAAA;EACA,cAAA;EACA,kBAAA;;AAKZ;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,SAAS,wBAAT;EACA,eAAe,kCAAf;EACA,kBAAkB,0BAAlB;EACA,kBAAA;;AAPJ,kBASI;EACI,SAAA;EACA,aAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,kBAAA;EACA,UAAA;;AAfR,kBASI,GAQI;EACI,SAAA;EACA,aAAA;EACA,cAAA;;AApBZ,kBAuBI;EACI,sBAAA;;AAxBR,kBA0BI;EACI,aAAA;;AAEA,kBAHJ,0BAGK;EACG,cAAA;;AA9BZ,kBAiCI,MAAK;EACD,SAAA;EACA,sBAAsB,2BAAtB;EACA,yBAAyB,2BAAzB;;AAIR;EACI,aAAA;EACA,KAAK,yBAAL;EACA,kBAAA;EACA,sBAAsB,yBAAtB;EACA,kBAAA;;AAEA,kBAAC;EACG,SAAS,EAAT;EACA,kBAAA;EACA,WAAA;EACA,aAAA;EACA,QAAA;EACA,kBAAA;EACA,QAAQ,wBAAwB,yBAAhC;EACA,uBAAuB,2BAAvB;EACA,yBAAyB,2BAAzB;EACA,2BAA2B,4BAA3B;EACA,YAAY,yBAAZ;;AAEJ,kBAAC;EACG,SAAS,EAAT;EACA,kBAAA;EACA,WAAA;EACA,QAAA;EACA,aAAA;EACA,cAAA;EACA,kBAAkB,2BAAlB;EACA,kBAAA;EACA,oBAAA;;AAIR;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,kBAAA;;AALJ,eAOI;EACI,MAAM,4BAAN;EACA,SAAA;;AAEA,eAJJ,cAIK;EACG,MAAM,4BAAN;;AAEJ,eAPJ,cAOK;EACG,MAAM,0BAAN;;AAfZ,eAmBI;EACI,WAAW,iCAAX;EACA,OAAO,mCAAP;;AAGR;EACI,kBAAA;EACA,OAAO,wBAAP;EACA,QAAQ,wBAAR;EACA,KAAK,wBAAL;EACA,gBAAA;;AALJ,oBAOI;EACI,YAAA;EACA,WAAA;;AAIR;EACI,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;;AAGJ,yBAA0B,MAAM;EAAI,kBAAA;;AAEpC;EACI,OAAO,0BAAP;EACA,SAAS,0BAA0B,wBAAnC;EACA,sBAAA;EACA,kBAAA;EACA,mBAAA;;AAEA,sBAAC;EACG,kBAAkB,4BAAlB;;AAEA,sBAHH,yBAGI;EACG,SAAS,OAAT;EACA,kBAAA;EACA,0BAAA;;AAIR,sBAAC;EACG,kBAAkB,0BAAlB;;AAEA,sBAHH,yBAGI;EACG,SAAS,OAAT;EACA,kBAAA;EACA,0BAAA;;;AAKZ,sBAAuB;EACnB,kBAAA;;AAEA,sBAHmB,uBAGjB;EACE,kBAAA;EACA,UAAA;;AAEA,sBAPe,uBAGjB,WAIG;EACG,oBAAA;;AADJ,sBAPe,uBAGjB,WAIG,QAGG;EACI,YAAA;;AAKhB;EACI,kBAAA;;AAEA,oBAAE,EAAC;EACC,kBAAA;EACA,UAAA;;AAEA,oBAJF,EAAC,sBAIE;EACG,oBAAA;;AAIZ;EACI,kBAAA;EACA,MAAA;EACA,SAAA;EACA,WAAA;;AAEJ;EACI,kBAAA;EACA,aAAA;;;AAIJ;EACI,aAAA;EACA,KAAK,wBAAL;EACA,gBAAA;;AAEA,yBAAE;EACE,OAAA;EACA,aAAA;EACA,sBAAA;EACA,KAAK,wBAAL;EACA,mBAAA;EACA,SAAS,wBAAT;;AANJ,yBAAE,IAQE;EACI,WAAA;EACA,WAAA;;AAKZ,IAAI,8BAEA,SAAQ;EACJ,wBAAA;;AAGR,IAAI,wBAEA,MAAM;EACF,wBAAA","file":"admin.css"} -
squeeze/trunk/assets/css/admin.less
r3311866 r3345284 457 457 margin-inline-start: .5em; 458 458 } 459 .squeeze-settings-example { 460 max-width: fit-content; 461 display: inline-block; 462 margin-inline-start: var(--squeeze-spacing-m); 463 /*opacity: 0.5; 464 465 &.enabled { 466 opacity: 1; 467 }*/ 468 469 &&--webp_replace_urls { 470 display: block; 471 margin-inline-start: 0; 472 margin-top: var(--squeeze-spacing-m); 473 } 474 475 .squeeze-box--fieldset { 476 display: flex; 477 gap: var(--squeeze-spacing-m); 478 479 .squeeze-box-content { 480 gap: var(--squeeze-spacing-s); 481 482 p { 483 display: flex; 484 justify-content: space-between; 485 gap: var(--squeeze-spacing-m); 486 } 487 .striked { 488 text-decoration: line-through; 489 color: var(--squeeze-error-color); 490 } 491 .greened { 492 color: var(--squeeze-success-color); 493 } 494 img { 495 max-width: 100%; 496 height: auto; 497 } 498 } 499 } 500 } 459 501 .form-table { 460 502 tr.squeeze_setting_restore_defaults { … … 463 505 tr:has(.squeeze-hidden) { 464 506 display: none; 507 } 508 tr.squeeze-legacy-option { 509 opacity: 0.5; 510 511 &:hover { 512 opacity: 1; 513 } 465 514 } 466 515 } … … 567 616 gap: var(--squeeze-spacing-s); 568 617 569 & input[type="text"]&__i tem{618 & input[type="text"]&__input { 570 619 min-width: 15rem; 571 620 font-family: monospace; … … 574 623 background-color: var(--squeeze-border-color); 575 624 padding: var(--squeeze-spacing-xs) var(--squeeze-spacing-s); 625 } 626 627 &__item { 628 position: relative; 629 display: flex; 630 align-items: center; 631 gap: var(--squeeze-spacing-s); 632 } 633 634 &__remove { 635 background: none; 636 border: 0; 637 padding: 0; 638 cursor: pointer; 639 color: var(--squeeze-error-color); 640 width: 1.5rem; 641 height: 1.5rem; 642 643 &:disabled { 644 opacity: 0.5; 645 cursor: not-allowed; 646 } 647 648 .squeeze-icon { 649 width: 1.5rem; 650 height: 1.5rem; 651 fill: currentColor; 652 } 576 653 } 577 654 } … … 782 859 } 783 860 } 861 862 body.settings_page_squeeze-account { 863 // Hide the your-license tab when on the account settings page 864 .nav-tab[href*="#squeeze_account"] { 865 display: none !important; 866 } 867 } 868 body.media_page_squeeze-bulk { 869 // Hide the account tab when on the bulk squeeze page 870 .wrap .nav-tab-wrapper { 871 display: none !important; 872 } 873 } -
squeeze/trunk/assets/js/admin.bundle.js
r3311866 r3345284 27 27 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 28 28 29 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"handleBulkButtonClick\": () => (/* binding */ handleBulkButtonClick),\n/* harmony export */ \"handleBulkFromPage\": () => (/* binding */ handleBulkFromPage),\n/* harmony export */ \"handleBulkToggle\": () => (/* binding */ handleBulkToggle),\n/* harmony export */ \"handleButtonsClick\": () => (/* binding */ handleButtonsClick),\n/* harmony export */ \"handleClosePathDialog\": () => (/* binding */ handleClosePathDialog),\n/* harmony export */ \"handle DirectoryCheck\": () => (/* binding */ handleDirectoryCheck),\n/* harmony export */ \"handleDirectoryClick\": () => (/* binding */ handleDirectoryClick),\n/* harmony export */ \"handleFetchImagesFromPage\": () => (/* binding */ handleFetchImagesFromPage),\n/* harmony export */ \"handleMultiFileFormUpload\": () => (/* binding */ handleMultiFileFormUpload),\n/* harmony export */ \"handleOnLeave\": () => (/* binding */ handleOnLeave),\n/* harmony export */ \"handleRecursiveUpload\": () => (/* binding */ handleRecursiveUpload),\n/* harmony export */ \"handleRestoreBtnClick\": () => (/* binding */ handleRestoreBtnClick),\n/* harmony export */ \"handleSingleBtnClick\": () => (/* binding */ handleSingleBtnClick)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](squeezeOptions);\r\n\r\nconst updateUI = (initId, response) => {\r\n const statusEl = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.postsFilterForm?.querySelector(`#post-${initId} .column-squeeze .squeeze_status`);\r\n if (statusEl) statusEl.innerHTML = response.data;\r\n\r\n const gridItem = document.querySelector(`.media-frame.mode-grid .attachment[data-id=\"${initId}\"]`);\r\n if (gridItem) {\r\n const centered = gridItem.querySelector('.centered');\r\n const progress = gridItem.querySelector('.media-progress-bar');\r\n if (centered) centered.style.display = 'block';\r\n if (progress) progress.remove();\r\n gridItem.classList.remove('uploading');\r\n }\r\n};\r\n\r\nconst getTotalPages = (path) => {\r\n const selectors = {\r\n uncompressed: \"input[name='squeeze_bulk_uncompressed_pages']\",\r\n all: \"input[name='squeeze_bulk_total_pages']\"\r\n };\r\n const sel = selectors[path];\r\n const val = sel && document.querySelector(sel)?.value;\r\n return Number(val) || 1;\r\n};\r\n\r\nconst checkPaused = (data, page) => {\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused) return false;\r\n handleBulkPause(data, page);\r\n return true;\r\n};\r\n\r\nconst logAndThumbnail = async (filename, response, wrapper) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(response.data, {\r\n mediaLogWrapper: wrapper,\r\n iconId: response.success ? 'check-mark-circle-icon' : 'ban-sign-icon'\r\n });\r\n\r\n const titleEl = wrapper.querySelector('h3');\r\n if (titleEl && response.filename) {\r\n titleEl.textContent = `${__('Media', 'squeeze')} ${filename} (${response.filename}):`;\r\n }\r\n\r\n const thumbUrl = response.sizes?.thumbnail?.url || response.url;\r\n if (thumbUrl) {\r\n const thumb = document.createElement('div');\r\n thumb.classList.add('media-log-thumbnail');\r\n thumb.innerHTML = `<img src=\"${thumbUrl}\" alt=\"${filename}\"/>`;\r\n wrapper.appendChild(thumb);\r\n }\r\n};\r\n\r\nconst handleDirectoryCheck = (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.savePathBtn.disabled = !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.dirContainer.querySelector(\"input[type='checkbox']:checked\");\r\n};\r\n\r\nconst handleClosePathDialog = (event) => {\r\n if (!event.target.contains(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog)) return;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog.close();\r\n};\r\n\r\nconst handleBulkToggle = (event, process, mediaIDs, page = 1) => {\r\n const isPaused = event.target.dataset.running === 'true';\r\n\r\n event.target.dataset.running = isPaused ? 'false' : 'true';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, isPaused ? __('Resume bulk squeezing', 'squeeze') : __('Pause bulk squeezing', 'squeeze'), isPaused ? '#play-button-round-icon' : '#pause-button-icon');\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused = isPaused;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process = process;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = mediaIDs;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = page;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target = event.target;\r\n\r\n console.log('handleBulkToggle', _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData);\r\n\r\n return isPaused;\r\n};\r\n\r\n// Handle single compress button click\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleSingleBtnClick = async (event, Squeeze) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n const squeezeStatus = event.target.closest(\"td\").querySelector(\".squeeze_status\");\r\n\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async (data) => {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const response = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n //squeezeStatus.innerHTML = response?.data?.message ?? response;\r\n squeezeStatus.innerHTML = response?.data ?? response;\r\n\r\n if (event.target.closest(\"td.field\")) {\r\n const table = event.target.closest(\"td\")?.querySelector(\".squeeze_status .squeeze-comparison-table\");\r\n if (table) {\r\n const td = document.createElement(\"td\");\r\n td.classList.add(\"field\");\r\n td.style.width = \"100%\";\r\n td.appendChild(table);\r\n event.target.closest(\"tr\").appendChild(td);\r\n }\r\n }\r\n // TBD: add file size label to the attachment info\r\n /*\r\n if (event.target.closest('.attachment-info')) {\r\n const fileSizeLabel = event.target.closest('.attachment-info').querySelector('.file-size');\r\n if (fileSizeLabel) {\r\n const fileSize = response?.data?.sizes?.scaled?.compressed_size ?? response?.data?.sizes?.original?.compressed_size ?? null;\r\n if (fileSize) {\r\n const humanFileSize = SqueezeHelpers.humanFileSize(fileSize, true);\r\n fileSizeLabel.innerHTML = fileSizeLabel.innerHTML.replace(/(<\\/strong>\\s*)(.*)/, `$1${humanFileSize}`);\r\n }\r\n }\r\n }\r\n */\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error;\r\n } finally {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.removeAllButtons(event.target.closest(\"td\")?.querySelectorAll(`button`));\r\n window.onbeforeunload = null;\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error;\r\n event.target.remove();\r\n }\r\n};\r\n\r\nconst handleRestoreBtnClick = async (event) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n\r\n event.target.disabled = true;\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Restore in process...', 'squeeze');\r\n\r\n try {\r\n const response = await Squeeze.handleRestore(attachmentID);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = response.data;\r\n } catch (error) {\r\n console.error(error);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = error;\r\n } finally {\r\n event.target.closest('td').querySelector(`[name='squeeze_compress_again']`).disabled = false;\r\n event.target.remove();\r\n window.onbeforeunload = null;\r\n }\r\n};\r\n\r\nconst handleBulkButtonClick = async (event, process, mediaIDs, currentPage) => {\r\n if (mediaIDs.length === 0) return;\r\n\r\n const totalPages = getTotalPages(process);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableBulkButtons();\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process === process) {\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs/*.length > 0*/) {\r\n mediaIDs = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs;\r\n }\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page) {\r\n currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page;\r\n }\r\n }\r\n\r\n const isPaused = handleBulkToggle(event, process, mediaIDs, currentPage);\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await handleRecursiveUpload(process, mediaIDs, currentPage, true);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0 && finalResponse.page >= totalPages) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n};\r\n\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleButtonsClick = async (event, Squeeze) => {\r\n const singleBtnName = 'squeeze_compress_single';\r\n const compressAgainBtnName = 'squeeze_compress_again';\r\n const restoreBtnName = 'squeeze_restore';\r\n\r\n if (event.target.getAttribute(\"name\") === singleBtnName || event.target.getAttribute(\"name\") === compressAgainBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Squeezing...', 'squeeze');\r\n window.onbeforeunload = handleOnLeave;\r\n handleSingleBtnClick(event, Squeeze);\r\n }\r\n\r\n if (event.target.getAttribute(\"name\") === restoreBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n window.onbeforeunload = handleOnLeave;\r\n handleRestoreBtnClick(event);\r\n }\r\n};\r\n\r\nconst handleDirectoryClick = async (event) => {\r\n if (event.target !== event.currentTarget) return;\r\n\r\n const currentDir = event.target.closest(\".directory-item\");\r\n const currentPath = currentDir.dataset.path;\r\n const parentPath = currentDir.dataset.parent;\r\n\r\n if (parentPath === '/' || currentDir.classList.contains(\"loading\")) return;\r\n\r\n if (currentDir.classList.contains(\"loaded\")) {\r\n currentDir.classList.toggle(\"opened\");\r\n return;\r\n }\r\n\r\n currentDir.classList.add(\"loading\");\r\n\r\n const subDirs = await Squeeze.getDirectories(currentPath);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.renderDirectories(subDirs, currentDir, {\r\n handleDirectoryClick,\r\n handleDirectoryCheck\r\n });\r\n\r\n currentDir.classList.remove(\"loading\");\r\n currentDir.classList.add(\"loaded\", \"opened\");\r\n}\r\n\r\n/**\r\n * Hadnle warning on page leave\r\n*/\r\nconst handleOnLeave = () => {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const page = urlParams.get('page');\r\n const isUploadPage = window.location.href.includes('upload.php');\r\n const isMediaNewPage = window.location.href.includes('media-new.php');\r\n const isAttachmentPage = window.location.href.includes('post.php') && urlParams.get('action') === 'edit';\r\n\r\n if (page === 'squeeze-bulk' || isMediaNewPage || isAttachmentPage) {\r\n return __('Are you sure you want to leave this page? The squeezing process will be terminated!', 'squeeze');\r\n }\r\n if (isUploadPage) {\r\n return __('Are you sure you want to leave this page? The settings will not be saved!', 'squeeze');\r\n }\r\n};\r\n\r\nconst handleBulkPause = (data, currentPage) => {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(__('Bulk squeezing has been paused!', 'squeeze'), { isPause: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = data;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = currentPage;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target.disabled = false;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target, __('Resume bulk squeezing', 'squeeze'), '#play-button-round-icon');\r\n};\r\n\r\nconst handleUpdateChart = (uncompressedImagesCount) => {\r\n const chartValue = document.querySelector(\".squeeze-bulk-media-stats-chart-value > text\");\r\n const chartBar = document.querySelector(\".squeeze-bulk-media-stats-chart\");\r\n const squeezedImages = document.querySelector(\".squeeze-bulk-media-stats-item-value\");\r\n\r\n if (!chartValue || !chartBar) return;\r\n\r\n const imagesLeft = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages - uncompressedImagesCount;\r\n const percentage = parseFloat((imagesLeft / _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages) * 100).toFixed(2);\r\n const dasharray = percentage * 560 / 100;\r\n chartValue.textContent = `${percentage}%`;\r\n chartBar.style.setProperty('--squeeze-dasharray', dasharray);\r\n\r\n if (squeezedImages) {\r\n squeezedImages.textContent = `${imagesLeft} / ${_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages}`;\r\n }\r\n};\r\n\r\nconst handleRecursiveUpload = async (path, data, currentPage, isUpdateChart = false) => {\r\n\r\n if (!Array.isArray(data)) return { success: false, data: 'No data provided!', mediaIDs: [] }; // when bulk directory path has no images\r\n \r\n const totalPages = getTotalPages(path);\r\n\r\n if (data.length === 0) {\r\n currentPage += 1;\r\n if (currentPage > totalPages || !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId) return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n }\r\n }\r\n\r\n const initData = [...data]; // initial data\r\n\r\n const filename = data[0]?.filename ? data[0].filename : `ID #${data[0]}`;\r\n const mediaLogWrapper = await _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${__('Start squeezing...', 'squeeze')}`, { title: filename, isStart: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId = data[0] || 0; // update lastId to the last processed ID\r\n\r\n try {\r\n const response = await Squeeze.handleBulkUpload(path, data);\r\n\r\n await logAndThumbnail(filename, response, mediaLogWrapper);\r\n\r\n if (isUpdateChart && path !== 'all') {\r\n let uncompressedImagesCount = 0;\r\n if (path === 'uncompressed') {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages - 1 || 0;\r\n uncompressedImagesCount = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages;\r\n } else if (path === 'path') {\r\n uncompressedImagesCount = response.mediaIDs.length;\r\n }\r\n handleUpdateChart(uncompressedImagesCount);\r\n }\r\n\r\n if (checkPaused(data, currentPage)) {\r\n return { success: false, data: 'Process has been paused!', mediaIDs: data, page: currentPage };\r\n }\r\n\r\n updateUI(initData[0], response);\r\n\r\n if (response.mediaIDs.length > 0) {\r\n return handleRecursiveUpload(path, response.mediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { ...response, page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${error}`, { mediaLogWrapper, iconId: 'ban-sign-icon' });\r\n\r\n if (data.length > 0) {\r\n return handleRecursiveUpload(path, data, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { success: false, data: error, mediaIDs: [], page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n\r\nconst handleMultiFileFormUpload = (compressOptions) => {\r\n if (typeof wpUploaderInit === 'undefined' || typeof plupload === 'undefined' || typeof uploader === 'undefined') return;\r\n\r\n const SqueezeUploader = uploader;\r\n\r\n SqueezeUploader.bind('FilesAdded', function (up, files) { });\r\n\r\n SqueezeUploader.bind('FileUploaded', function (up, file, response) {\r\n const fileMime = file.type;\r\n const fileType = fileMime.split('/')[0];\r\n const fileSubType = fileMime.split('/')[1];\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) return;\r\n\r\n const fileID = file.id;\r\n const attachmentID = response.response;\r\n const mediaItem = document.getElementById(`media-item-${fileID}`);\r\n\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n /**\r\n * Wait for media item to load( 'async-upload.php' )\r\n * Ping every 1 second until the media item is loaded\r\n * @returns Promise\r\n */\r\n const waitForItemLoad = () => {\r\n return new Promise((resolve) => {\r\n let interval = setInterval(() => {\r\n if (mediaItem.querySelector('.media-item-wrapper')) {\r\n mediaItem.querySelector('.media-item-wrapper').innerHTML += `\r\n <div class=\"progress\">\r\n <div class=\"percent\">${__('Squeezing...', 'squeeze')}</div>\r\n <div class=\"bar\" style=\"width: 200px;\"></div>\r\n </div>\r\n `;\r\n clearInterval(interval);\r\n resolve();\r\n }\r\n }, 1000);\r\n });\r\n };\r\n\r\n waitForItemLoad().then(() => {\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async function (data) {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n window.onbeforeunload = null;\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${uploadData.data}</div>`;\r\n mediaItem.querySelector('.progress')?.remove();\r\n } else {\r\n alert(uploadData?.data ?? uploadData);\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n });\r\n\r\n SqueezeUploader.bind('UploadComplete', function (up, files) { });\r\n};\n\n//# sourceURL=webpack:///./assets/js/handlers.js?");29 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"handleBulkButtonClick\": () => (/* binding */ handleBulkButtonClick),\n/* harmony export */ \"handleBulkFromPage\": () => (/* binding */ handleBulkFromPage),\n/* harmony export */ \"handleBulkToggle\": () => (/* binding */ handleBulkToggle),\n/* harmony export */ \"handleButtonsClick\": () => (/* binding */ handleButtonsClick),\n/* harmony export */ \"handleClosePathDialog\": () => (/* binding */ handleClosePathDialog),\n/* harmony export */ \"handleCompressBeforeUpload\": () => (/* binding */ handleCompressBeforeUpload),\n/* harmony export */ \"handleDirectoryCheck\": () => (/* binding */ handleDirectoryCheck),\n/* harmony export */ \"handleDirectoryClick\": () => (/* binding */ handleDirectoryClick),\n/* harmony export */ \"handleFetchImagesFromPage\": () => (/* binding */ handleFetchImagesFromPage),\n/* harmony export */ \"handleMultiFileFormUpload\": () => (/* binding */ handleMultiFileFormUpload),\n/* harmony export */ \"handleOnLeave\": () => (/* binding */ handleOnLeave),\n/* harmony export */ \"handleRecursiveUpload\": () => (/* binding */ handleRecursiveUpload),\n/* harmony export */ \"handleRestoreBtnClick\": () => (/* binding */ handleRestoreBtnClick),\n/* harmony export */ \"handleSingleBtnClick\": () => (/* binding */ handleSingleBtnClick)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](squeezeOptions);\r\n\r\nconst updateUI = (initId, response) => {\r\n const statusEl = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.postsFilterForm?.querySelector(`#post-${initId} .column-squeeze .squeeze_status`);\r\n if (statusEl) statusEl.innerHTML = response?.data?.message ?? response?.data ?? response;\r\n\r\n const gridItem = document.querySelector(`.media-frame.mode-grid .attachment[data-id=\"${initId}\"]`);\r\n if (gridItem) {\r\n const centered = gridItem.querySelector('.centered');\r\n const progress = gridItem.querySelector('.media-progress-bar');\r\n if (centered) centered.style.display = 'block';\r\n if (progress) progress.remove();\r\n gridItem.classList.remove('uploading');\r\n }\r\n};\r\n\r\nconst getTotalPages = (path) => {\r\n const selectors = {\r\n uncompressed: \"input[name='squeeze_bulk_uncompressed_pages']\",\r\n all: \"input[name='squeeze_bulk_total_pages']\"\r\n };\r\n const sel = selectors[path];\r\n const val = sel && document.querySelector(sel)?.value;\r\n return Number(val) || 1;\r\n};\r\n\r\nconst checkPaused = (data, page) => {\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused) return false;\r\n handleBulkPause(data, page);\r\n return true;\r\n};\r\n\r\nconst logAndThumbnail = async (filename, response, wrapper) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(response?.data?.message ?? response?.data, {\r\n mediaLogWrapper: wrapper,\r\n iconId: response.success ? 'check-mark-circle-icon' : 'ban-sign-icon'\r\n });\r\n\r\n const titleEl = wrapper?.querySelector('h3');\r\n if (titleEl && response?.data?.filename) {\r\n titleEl.textContent = `${__('Media', 'squeeze')} ${filename} (${response.data.filename}):`;\r\n }\r\n\r\n const thumbUrl = response?.data?.sizes?.thumbnail?.url || response?.data?.url || response?.url;\r\n if (thumbUrl) {\r\n const thumb = document.createElement('div');\r\n thumb.classList.add('media-log-thumbnail');\r\n thumb.innerHTML = `<img src=\"${thumbUrl}\" alt=\"${filename}\"/>`;\r\n wrapper?.appendChild(thumb);\r\n }\r\n};\r\n\r\nconst handleDirectoryCheck = (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.savePathBtn.disabled = !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.dirContainer.querySelector(\"input[type='checkbox']:checked\");\r\n};\r\n\r\nconst handleClosePathDialog = (event) => {\r\n if (!event.target.contains(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog)) return;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog.close();\r\n};\r\n\r\nconst handleBulkToggle = (event, process, mediaIDs, page = 1) => {\r\n const isPaused = event.target.dataset.running === 'true';\r\n\r\n event.target.dataset.running = isPaused ? 'false' : 'true';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, isPaused ? __('Resume bulk squeezing', 'squeeze') : __('Pause bulk squeezing', 'squeeze'), isPaused ? '#play-button-round-icon' : '#pause-button-icon');\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused = isPaused;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process = process;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = mediaIDs;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = page;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target = event.target;\r\n\r\n //console.log('handleBulkToggle', cachedMediaData);\r\n\r\n return isPaused;\r\n};\r\n\r\n// Handle single compress button click\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleSingleBtnClick = async (event, Squeeze) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n const squeezeStatus = event.target.closest(\"td\").querySelector(\".squeeze_status\");\r\n\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async (data) => {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const response = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n squeezeStatus.innerHTML = response?.data?.message ?? response?.data ?? response;\r\n\r\n if (event.target.closest(\"td.field\")) {\r\n const table = event.target.closest(\"td\")?.querySelector(\".squeeze_status .squeeze-comparison-table\");\r\n if (table) {\r\n const td = document.createElement(\"td\");\r\n td.classList.add(\"field\");\r\n td.style.width = \"100%\";\r\n td.appendChild(table);\r\n event.target.closest(\"tr\").appendChild(td);\r\n }\r\n }\r\n // TBD: add file size label to the attachment info\r\n /*\r\n if (event.target.closest('.attachment-info')) {\r\n const fileSizeLabel = event.target.closest('.attachment-info').querySelector('.file-size');\r\n if (fileSizeLabel) {\r\n const fileSize = response?.data?.sizes?.scaled?.compressed_size ?? response?.data?.sizes?.original?.compressed_size ?? null;\r\n if (fileSize) {\r\n const humanFileSize = SqueezeHelpers.humanFileSize(fileSize, true);\r\n fileSizeLabel.innerHTML = fileSizeLabel.innerHTML.replace(/(<\\/strong>\\s*)(.*)/, `$1${humanFileSize}`);\r\n }\r\n }\r\n }\r\n */\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error?.message ?? error;\r\n } finally {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.removeAllButtons(event.target.closest(\"td\")?.querySelectorAll(`button`));\r\n window.onbeforeunload = null;\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error?.message ?? error;\r\n event.target.remove();\r\n }\r\n};\r\n\r\nconst handleRestoreBtnClick = async (event) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n\r\n event.target.disabled = true;\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Restore in process...', 'squeeze');\r\n\r\n try {\r\n const response = await Squeeze.handleRestore(attachmentID);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = response?.data ?? response;\r\n } catch (error) {\r\n console.error(error);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = error?.message ?? JSON.stringify(error, null, 2);\r\n } finally {\r\n event.target.closest('td').querySelector(`[name='squeeze_compress_again']`).disabled = false;\r\n event.target.remove();\r\n window.onbeforeunload = null;\r\n }\r\n};\r\n\r\nconst handleBulkButtonClick = async (event, process, mediaIDs, currentPage) => {\r\n if (mediaIDs.length === 0) return;\r\n\r\n const totalPages = getTotalPages(process);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableBulkButtons();\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process === process) {\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs/*.length > 0*/) {\r\n mediaIDs = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs;\r\n }\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page) {\r\n currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page;\r\n }\r\n }\r\n\r\n const isPaused = handleBulkToggle(event, process, mediaIDs, currentPage);\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await handleRecursiveUpload(process, mediaIDs, currentPage, true);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0 && finalResponse.page >= totalPages) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n};\r\n\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleButtonsClick = async (event, Squeeze) => {\r\n const singleBtnName = 'squeeze_compress_single';\r\n const compressAgainBtnName = 'squeeze_compress_again';\r\n const restoreBtnName = 'squeeze_restore';\r\n\r\n if (event.target.getAttribute(\"name\") === singleBtnName || event.target.getAttribute(\"name\") === compressAgainBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Squeezing...', 'squeeze');\r\n window.onbeforeunload = handleOnLeave;\r\n handleSingleBtnClick(event, Squeeze);\r\n }\r\n\r\n if (event.target.getAttribute(\"name\") === restoreBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n window.onbeforeunload = handleOnLeave;\r\n handleRestoreBtnClick(event);\r\n }\r\n};\r\n\r\nconst handleDirectoryClick = async (event) => {\r\n if (event.target !== event.currentTarget) return;\r\n\r\n const currentDir = event.target.closest(\".directory-item\");\r\n const currentPath = currentDir.dataset.path;\r\n const parentPath = currentDir.dataset.parent;\r\n\r\n if (parentPath === '/' || currentDir.classList.contains(\"loading\")) return;\r\n\r\n if (currentDir.classList.contains(\"loaded\")) {\r\n currentDir.classList.toggle(\"opened\");\r\n return;\r\n }\r\n\r\n currentDir.classList.add(\"loading\");\r\n\r\n const subDirs = await Squeeze.getDirectories(currentPath);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.renderDirectories(subDirs, currentDir, {\r\n handleDirectoryClick,\r\n handleDirectoryCheck\r\n });\r\n\r\n currentDir.classList.remove(\"loading\");\r\n currentDir.classList.add(\"loaded\", \"opened\");\r\n}\r\n\r\n/**\r\n * Hadnle warning on page leave\r\n*/\r\nconst handleOnLeave = () => {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const page = urlParams.get('page');\r\n const isUploadPage = window.location.href.includes('upload.php');\r\n const isMediaNewPage = window.location.href.includes('media-new.php');\r\n const isAttachmentPage = window.location.href.includes('post.php') && urlParams.get('action') === 'edit';\r\n\r\n if (page === 'squeeze-bulk' || isMediaNewPage || isAttachmentPage) {\r\n return __('Are you sure you want to leave this page? The squeezing process will be terminated!', 'squeeze');\r\n }\r\n if (isUploadPage) {\r\n return __('Are you sure you want to leave this page? The settings will not be saved!', 'squeeze');\r\n }\r\n};\r\n\r\nconst handleBulkPause = (data, currentPage) => {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(__('Bulk squeezing has been paused!', 'squeeze'), { isPause: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = data;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = currentPage;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target.disabled = false;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target, __('Resume bulk squeezing', 'squeeze'), '#play-button-round-icon');\r\n};\r\n\r\nconst handleUpdateChart = (uncompressedImagesCount) => {\r\n const chartValue = document.querySelector(\".squeeze-bulk-media-stats-chart-value > text\");\r\n const chartBar = document.querySelector(\".squeeze-bulk-media-stats-chart\");\r\n const squeezedImages = document.querySelector(\".squeeze-bulk-media-stats-item-value\");\r\n\r\n if (!chartValue || !chartBar) return;\r\n\r\n const imagesLeft = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages - uncompressedImagesCount;\r\n const percentage = parseFloat((imagesLeft / _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages) * 100).toFixed(2);\r\n const dasharray = percentage * 560 / 100;\r\n chartValue.textContent = `${percentage}%`;\r\n chartBar.style.setProperty('--squeeze-dasharray', dasharray);\r\n\r\n if (squeezedImages) {\r\n squeezedImages.textContent = `${imagesLeft} / ${_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages}`;\r\n }\r\n};\r\n\r\nconst handleRecursiveUpload = async (path, data, currentPage, isUpdateChart = false) => {\r\n\r\n if (!Array.isArray(data)) return { success: false, data: 'No data provided!', mediaIDs: [] }; // when bulk directory path has no images\r\n\r\n const totalPages = getTotalPages(path);\r\n\r\n if (data.length === 0) {\r\n currentPage += 1;\r\n if (currentPage > totalPages || !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId) return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n }\r\n }\r\n\r\n const initData = [...data]; // initial data\r\n\r\n const filename = data[0]?.filename ? data[0].filename : `ID #${data[0]}`;\r\n const mediaLogWrapper = await _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${__('Start squeezing...', 'squeeze')}`, { title: filename, isStart: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId = data[0] || 0; // update lastId to the last processed ID\r\n\r\n try {\r\n const response = await Squeeze.handleBulkUpload(path, data);\r\n\r\n //console.log('handleRecursiveUpload response', response);\r\n\r\n await logAndThumbnail(filename, response, mediaLogWrapper);\r\n\r\n if (isUpdateChart && path !== 'all') {\r\n let uncompressedImagesCount = 0;\r\n if (path === 'uncompressed') {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages - 1 || 0;\r\n uncompressedImagesCount = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages;\r\n } else if (path === 'path') {\r\n uncompressedImagesCount = response.mediaIDs.length;\r\n }\r\n handleUpdateChart(uncompressedImagesCount);\r\n }\r\n\r\n if (checkPaused(data, currentPage)) {\r\n return { success: false, data: 'Process has been paused!', mediaIDs: data, page: currentPage };\r\n }\r\n\r\n updateUI(initData[0], response);\r\n\r\n if (response.mediaIDs.length > 0) {\r\n return handleRecursiveUpload(path, response.mediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { ...response, page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${error}`, { mediaLogWrapper, iconId: 'ban-sign-icon' });\r\n\r\n if (data.length > 0) {\r\n return handleRecursiveUpload(path, data, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { success: false, data: error, mediaIDs: [], page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n\r\n/**\r\n * Handles the compression of image before upload using Squeeze.\r\n * It compresses only the original image, not the thumbnails.\r\n * \r\n * @param {object} up - The plupload instance\r\n * @param {object} pluploadFile - The file to be compressed\r\n * @param {object} compressOptions - The compression options object\r\n * @returns {boolean} - Returns false to prevent further processing of the file\r\n */\r\nconst handleCompressBeforeUpload = async (up, pluploadFile, compressOptions) => {\r\n if (typeof Squeeze === 'undefined') return;\r\n if (typeof Squeeze.compressBeforeUpload !== 'function') {\r\n console.warn('Squeeze.compressBeforeUpload is not a function');\r\n return;\r\n }\r\n \r\n if (pluploadFile?._isSqueezed || pluploadFile?._isExcluded || pluploadFile?._isFailed) {\r\n //console.warn('File is already compressed:', pluploadFile);\r\n return; // Skip files that are already compressed\r\n }\r\n // Check if the file is an image based on its MIME type\r\n if (!pluploadFile.type.startsWith('image/')) {\r\n //console.warn('File is not an image:', pluploadFile.name);\r\n return; // Skip non-image files\r\n }\r\n\r\n const file = pluploadFile.getNative() || pluploadFile.getSource();\r\n\r\n const type = file?.type?.split('/')[0] ?? '';\r\n const subtype = file?.type?.split('/')[1] ?? '';\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(type, subtype, compressOptions)) {\r\n //console.warn('Skipping compression for:', pluploadFile.name);\r\n return; // Skip compression for this file\r\n }\r\n\r\n //console.time('BeforeUpload')\r\n\r\n up.stop();\r\n window.onbeforeunload = handleOnLeave;\r\n \r\n \r\n\r\n try {\r\n let originalFile = file;\r\n const base64Obj = await Squeeze.compressBeforeUpload(file);\r\n if (!base64Obj || !base64Obj.base64) {\r\n console.warn('Compression skipped or failed for:', file.name);\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isFailed = true; // Mark the file as failed\r\n //window.onbeforeunload = null;\r\n setTimeout(() => up.start(), 0);\r\n return; // Skip further processing if compression failed or was skipped\r\n }\r\n \r\n const isDirectWebp = compressOptions?.direct_webp && file.type !== 'image/webp';\r\n const isBackupOriginal = compressOptions?.backup_original;\r\n\r\n if (isBackupOriginal) {\r\n // If backup original is enabled, convert the original file to WebP if it's not already\r\n if (isDirectWebp) {\r\n originalFile = await Squeeze.convertFileToWebp(file);\r\n } else {\r\n originalFile = file; // Keep the original file as is\r\n }\r\n pluploadFile.originalFile = originalFile; // Store the original file in the pluploadFile object\r\n }\r\n\r\n const compressedFile = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.base64ToFile(base64Obj.base64, file.name, file.type);\r\n const newSource = new mOxie.File(null, compressedFile);\r\n\r\n if (!newSource) {\r\n console.error('Failed to create new mOxie.File from base64 data');\r\n return; // Exit if newSource is not created\r\n }\r\n\r\n //console.log('Compressed file created:', newSource);\r\n\r\n // Override the file's getSource method to return the new compressed source\r\n pluploadFile.getSource = function () {\r\n return newSource;\r\n };\r\n\r\n // Reset status back to QUEUED\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isSqueezed = true; // Mark the file as compressed\r\n pluploadFile.base64 = base64Obj.base64; // Store the base64 data of the compressed image in the attachment\r\n pluploadFile.base64Webp = base64Obj?.base64Webp; // Store the WebP base64 data of the compressed image in the attachment\r\n \r\n // In the next tick, restart the queue\r\n setTimeout(() => up.start(), 0);\r\n\r\n //window.onbeforeunload = null;\r\n\r\n } catch (error) {\r\n console.error('Error during compression before upload:', error);\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isFailed = true; // Mark the file as failed\r\n setTimeout(() => up.start(), 0);\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nconst handleMultiFileFormUpload = (compressOptions) => {\r\n if (typeof wpUploaderInit === 'undefined' || typeof plupload === 'undefined' || typeof uploader === 'undefined') return;\r\n\r\n const SqueezeUploader = uploader;\r\n\r\n SqueezeUploader.bind('BeforeUpload', async function (up, pluploadFile) {\r\n handleCompressBeforeUpload(up, pluploadFile, compressOptions)\r\n });\r\n\r\n SqueezeUploader.bind('FileUploaded', function (up, file, response) {\r\n //console.log('FileUploaded', file, response);\r\n const fileMime = file.type;\r\n const fileType = fileMime.split('/')[0];\r\n const fileSubType = fileMime.split('/')[1];\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) return;\r\n\r\n /**\r\n * Wait for media item to load( 'async-upload.php' )\r\n * Ping every 1 second until the media item is loaded\r\n * @returns Promise\r\n */\r\n const waitForItemLoad = (addProgressBar = true) => {\r\n return new Promise((resolve) => {\r\n let interval = setInterval(() => {\r\n if (mediaItem.querySelector('.media-item-wrapper')) {\r\n if (addProgressBar) {\r\n mediaItem.querySelector('.media-item-wrapper').innerHTML += `\r\n <div class=\"progress\">\r\n <div class=\"percent\">${__('Squeezing...', 'squeeze')}</div>\r\n <div class=\"bar\" style=\"width: 200px;\"></div>\r\n </div>\r\n `;\r\n }\r\n clearInterval(interval);\r\n resolve();\r\n }\r\n }, 1000);\r\n });\r\n };\r\n\r\n const fileID = file.id;\r\n const attachmentID = response.response;\r\n const mediaItem = document.getElementById(`media-item-${fileID}`);\r\n\r\n if (file?._isExcluded) {\r\n console.warn('File is excluded from compression:', file.name);\r\n waitForItemLoad(false).then(() => {\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${__('File is excluded from compression:', 'squeeze')} ${file.name}</div>`;\r\n });\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n if (file?._isFailed) {\r\n console.warn('File compression failed:', file.name);\r\n waitForItemLoad(false).then(() => {\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${__('File compression failed:', 'squeeze')} ${file.name}</div>`;\r\n });\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n waitForItemLoad().then(() => {\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async function (data) {\r\n //console.log('Fetched attachment data:', data);\r\n const attachment = { attributes: data };\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.extendAttachment(attachment, file);\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n window.onbeforeunload = null;\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${uploadData?.data?.message}</div>`;\r\n mediaItem.querySelector('.progress')?.remove();\r\n } else {\r\n mediaItem.innerHTML += uploadData?.data?.message ?? uploadData?.data ?? uploadData;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n });\r\n}\r\n\r\n\n\n//# sourceURL=webpack:///./assets/js/handlers.js?"); 30 30 31 31 /***/ }), … … 37 37 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 38 38 39 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64SizeInBytes\": () => (/* binding */ base64SizeInBytes),\n/* harmony export */ \"base64ToBlob\": () => (/* binding */ base64ToBlob),\n/* harmony export */ \" cachedMediaData\": () => (/* binding */ cachedMediaData),\n/* harmony export */ \"disableAllButtons\": () => (/* binding */ disableAllButtons),\n/* harmony export */ \"disableBulkButtons\": () => (/* binding */ disableBulkButtons),\n/* harmony export */ \"elements\": () => (/* binding */ elements),\n/* harmony export */ \"humanFileSize\": () => (/* binding */ humanFileSize),\n/* harmony export */ \"isDocHidden\": () => (/* binding */ isDocHidden),\n/* harmony export */ \"logMessage\": () => (/* binding */ logMessage),\n/* harmony export */ \"maybeCompressAttachment\": () => (/* binding */ maybeCompressAttachment),\n/* harmony export */ \"populatePathInput\": () => (/* binding */ populatePathInput),\n/* harmony export */ \"removeAllButtons\": () => (/* binding */ removeAllButtons),\n/* harmony export */ \"renderDirectories\": () => (/* binding */ renderDirectories),\n/* harmony export */ \"renderTemplate\": () => (/* binding */ renderTemplate),\n/* harmony export */ \"restoreBulkButtons\": () => (/* binding */ restoreBulkButtons),\n/* harmony export */ \"updateButtonText\": () => (/* binding */ updateButtonText)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\n// move static helper functions here\r\nconst elements = {\r\n bulkBtn: document.querySelector(\"[name='squeeze_bulk']\"),\r\n bulkAgainBtn: document.querySelector(\"[name='squeeze_bulk_again']\"),\r\n bulkPathBtn: document.querySelector(\"[name='squeeze_bulk_path_button']\"),\r\n selectPathBtn: document.querySelector(\"[name='squeeze_select_path_button']\"),\r\n savePathBtn: document.querySelector(\"[name='squeeze_save_path_button']\"),\r\n pathDialog: document.getElementById(\"squeeze-path-dialog\"),\r\n closePathDialogBtn: document.querySelector(\"[name='squeeze_close_path_dialog_button']\"),\r\n pathInput: document.querySelector(\"[name='squeeze_bulk_path']\"),\r\n pathList: document.querySelector(\".squeeze-path-list\"),\r\n postsFilterForm: document.querySelector(\"#posts-filter\"),\r\n dirContainer: document.getElementById(\"squeeze-bulk-directory-list\"),\r\n bulkLogInput: document.querySelector(\"#squeeze-log-data\"),\r\n pauseBulkBtn: document.querySelector(\"[name='squeeze_pause_page_bulk']\")\r\n}\r\n\r\nconst cachedMediaData = {\r\n isPaused: false,\r\n page: 1,\r\n process: '',\r\n mediaIDs: [],\r\n lastId: 0,\r\n totalImages: document.querySelector(\"[name='squeeze_bulk_total_images']\")?.value || 0,\r\n uncompressedImages: document.querySelector(\"[name='squeeze_bulk_uncompressed_images']\")?.value || 0,\r\n target: null\r\n}\r\n\r\nconst loadTemplate = async (templatePath, data) => {\r\n const response = await fetch(templatePath);\r\n let template = await response.text();\r\n\r\n // Process sub-templates\r\n const subTemplateRegex = /\\{\\{\\>\\s*(.*?)\\s*\\}\\}/g;\r\n let match;\r\n while ((match = subTemplateRegex.exec(template)) !== null) {\r\n const subTemplatePath = `${squeezeOptions.templateBase}/${match[1].trim()}.html`;\r\n const subTemplate = await loadTemplate(subTemplatePath, data);\r\n template = template.replace(match[0], subTemplate);\r\n }\r\n\r\n // Function to safely evaluate conditions (supports boolean variables, expressions, AND/OR)\r\n const evaluateCondition = (condition, data) => {\r\n try {\r\n // Convert standalone boolean variables (e.g., webp_lossless) to data['webp_lossless']\r\n condition = condition.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match) =>\r\n match in data ? `data['${match}']` : match\r\n );\r\n\r\n return new Function(\"data\", `with(data) { return ${condition}; }`)(data);\r\n } catch (e) {\r\n console.error(\"Error evaluating condition:\", condition, e);\r\n return false;\r\n }\r\n };\r\n\r\n // Recursive function to process nested if-else conditions\r\n const processIfStatements = (template) => {\r\n return template.replace(/\\{\\{#if ([\\s\\S]*?)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g, (match, condition, content) => {\r\n condition = condition.trim();\r\n const conditionResult = evaluateCondition(condition, data);\r\n\r\n // Extract and split the if-else blocks\r\n const elseMatch = content.match(/\\{\\{#else\\}\\}([\\s\\S]*)/);\r\n const trueBlock = elseMatch ? content.replace(/\\{\\{#else\\}\\}([\\s\\S]*)/, \"\") : content;\r\n const falseBlock = elseMatch ? elseMatch[1] : \"\";\r\n\r\n // Process nested if statements recursively\r\n return processIfStatements(conditionResult ? trueBlock : falseBlock);\r\n });\r\n };\r\n\r\n // Apply recursive processing of if conditions\r\n template = processIfStatements(template);\r\n\r\n // Replace variables\r\n return template.replace(/\\{\\{(.*?)\\}\\}/g, (match, key) => data[key.trim()] || '');\r\n}\r\n\r\nconst renderTemplate = async (templatePath, data, target = null) => {\r\n const renderedHTML = await loadTemplate(templatePath, data);\r\n\r\n // Create a temporary container to parse HTML\r\n const tempContainer = document.createElement(\"template\");\r\n tempContainer.innerHTML = renderedHTML.trim();\r\n\r\n if (!target) {\r\n return tempContainer.content.firstChild;\r\n }\r\n\r\n target.appendChild(tempContainer.content.firstChild);\r\n\r\n // Return the last element of the rendered template\r\n return target.lastElementChild;\r\n}\r\n\r\nconst logMessage = async (msg, options = {}) => {\r\n const { mediaLogWrapper = null, isStart = false, isPause = false } = options;\r\n let { title = '', iconId = 'check-mark-circle-icon' } = options;\r\n\r\n if (!elements.bulkLogInput) return;\r\n\r\n if (isStart || isPause) {\r\n iconId = isPause ? 'pause-button-icon' : 'image-file-icon';\r\n title = isPause ? __('Bulk squeezing has been paused!', 'squeeze') : `${__('Media', 'squeeze')} ${title}:`;\r\n return await renderTemplate(squeezeOptions.templates.logWrapper, { title: title, msg: msg, iconId: iconId, isStart: isStart, isPause: isPause }, elements.bulkLogInput);\r\n } else {\r\n if (mediaLogWrapper) {\r\n const process = mediaLogWrapper.querySelector(\".media-log-process\");\r\n const step = await renderTemplate(squeezeOptions.templates.logStep, { msg: msg, iconId: iconId }, process);\r\n\r\n if (msg.includes('squeeze-comparison-table')) {\r\n const comparisonTable = step.querySelector('.squeeze-comparison-table');\r\n const toggleBtn = await renderTemplate(squeezeOptions.templates.logDetailsButton, { buttonText: __('Show details', 'squeeze') }, mediaLogWrapper);\r\n\r\n toggleBtn.addEventListener(\"click\", () => {\r\n comparisonTable.classList.toggle(\"show\");\r\n toggleBtn.textContent = comparisonTable.classList.contains(\"show\") ? __('Hide details', 'squeeze') : __('Show details', 'squeeze');\r\n });\r\n step.closest(\".media-log-wrapper\").appendChild(comparisonTable);\r\n step.closest(\".media-log-wrapper\").appendChild(toggleBtn);\r\n }\r\n } else {\r\n elements.bulkLogInput.innerHTML += msg + `<br>`;\r\n }\r\n }\r\n}\r\n\r\nconst restoreBulkButtons = () => {\r\n elements.bulkBtn.disabled = false;\r\n elements.bulkAgainBtn.disabled = false;\r\n elements.bulkPathBtn.disabled = false;\r\n elements.selectPathBtn.disabled = false;\r\n updateButtonText(elements.bulkBtn, __('Run Bulk Squeeze', 'squeeze'), '#play-button-round-icon');\r\n updateButtonText(elements.bulkAgainBtn, __('Repeat Bulk Squeeze', 'squeeze'), '#combine-left-right-outline-icon');\r\n updateButtonText(elements.bulkPathBtn, __('Run Directory Squeeze', 'squeeze'), '#play-button-round-icon');\r\n elements.bulkBtn.dataset.running = 'false';\r\n elements.bulkAgainBtn.dataset.running = 'false';\r\n elements.bulkPathBtn.dataset.running = 'false';\r\n\r\n cachedMediaData.process = '';\r\n cachedMediaData.mediaIDs = [];\r\n cachedMediaData.page = 1;\r\n}\r\n\r\nconst disableBulkButtons = () => {\r\n elements.bulkBtn.disabled = true;\r\n elements.bulkAgainBtn.disabled = true;\r\n elements.bulkPathBtn.disabled = true;\r\n elements.selectPathBtn.disabled = true;\r\n}\r\n\r\nconst disableAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst removeAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.remove());\r\n}\r\n\r\nconst updateButtonText = (button, text, svgAnchor = false) => {\r\n button.childNodes.forEach((node) => {\r\n if (node.nodeName === '#text' && node.textContent.trim() !== '') {\r\n node.textContent = text;\r\n }\r\n if (svgAnchor && node.nodeName === 'svg') {\r\n node.querySelector('use').setAttribute('xlink:href', svgAnchor);\r\n }\r\n });\r\n}\r\n\r\n// Function to render directories in the dialog\r\nconst renderDirectories = async (dirs, parentDir = null, listeners = {}) => {\r\n if (!dirs) return;\r\n if (typeof dirs === 'object') dirs = Object.values(dirs);\r\n if (!elements.dirContainer.classList.contains(\"loaded\")) elements.dirContainer.innerHTML = \"\";\r\n\r\n if (dirs.length === 0 && !parentDir) {\r\n const listItem = await renderTemplate(squeezeOptions.templates.directoryItemEmpty, { emptyText: __('No directories found!', 'squeeze') }, elements.dirContainer);\r\n return;\r\n }\r\n\r\n const selectedFolders = JSON.parse(elements.pathInput.value);\r\n let target;\r\n\r\n for (const dir of dirs) {\r\n const listItemClasses = [];\r\n\r\n if (dir.parent === '/') {\r\n listItemClasses.push(\"loaded\", \"opened\");\r\n }\r\n\r\n if (parentDir) {\r\n target = parentDir;\r\n } else if (dir.parent) {\r\n const parentElement = elements.dirContainer.querySelector(`[data-path=\"${dir.parent}\"]`);\r\n if (parentElement) {\r\n target = parentElement;\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n\r\n const listItem = await renderTemplate(\r\n squeezeOptions.templates.directoryItem,\r\n {\r\n parent: dir.parent,\r\n path: dir.path,\r\n label: dir.name,\r\n classes: listItemClasses.join(\" \"),\r\n isWritable: dir.is_writeable && !(Array.isArray(selectedFolders) && selectedFolders.includes(dir.path)),\r\n isChecked: dir.is_writeable && Array.isArray(selectedFolders) && selectedFolders.includes(dir.path),\r\n },\r\n target\r\n )\r\n\r\n listItem.querySelector(\"label\").addEventListener(\"click\", listeners.handleDirectoryClick);\r\n listItem.querySelector(\"input[type='checkbox']\")?.addEventListener(\"change\", listeners.handleDirectoryCheck);\r\n }\r\n\r\n elements.dirContainer.classList.add(\"loaded\");\r\n}\r\n\r\nconst populatePathInput = async () => {\r\n const path = elements.pathInput.value;\r\n if (!path) return;\r\n\r\n try {\r\n const selectedFolders = JSON.parse(path);\r\n const inputs = elements.pathList.querySelectorAll(\".squeeze-path-list__item\");\r\n\r\n inputs.forEach(input => input.remove());\r\n\r\n for (const folder of selectedFolders) {\r\n const input = await renderTemplate(squeezeOptions.templates.pathListItem, { folder: folder }, elements.pathList);\r\n }\r\n } catch (error) {\r\n alert(__('Error parsing path input!', 'squeeze'));\r\n console.error('Error parsing path input:', error);\r\n }\r\n}\r\n\r\nconst getHiddenProp = () => {\r\n var prefixes = ['webkit', 'moz', 'ms', 'o'];\r\n\r\n // if 'hidden' is natively supported just return it\r\n if ('hidden' in document) return 'hidden';\r\n\r\n // otherwise loop over all the known prefixes until we find one\r\n for (let i = 0; i < prefixes.length; i++) {\r\n if ((prefixes[i] + 'Hidden') in document)\r\n return prefixes[i] + 'Hidden';\r\n }\r\n\r\n // otherwise it's not supported\r\n return null;\r\n}\r\n\r\nconst isDocHidden = () => {\r\n const prop = getHiddenProp();\r\n if (!prop) return false;\r\n\r\n return document[prop];\r\n}\r\n\r\n/**\r\n * @see https://stackoverflow.com/a/20732091\r\n */\r\nconst humanFileSize = (size) => {\r\n let i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));\r\n return +((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];\r\n}\r\n\r\nconst base64SizeInBytes = (base64) => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64; \r\n\r\n // Calculate padding characters ('=' at the end of Base64)\r\n const padding = (base64String.match(/=+$/) || [\"\"])[0].length;\r\n\r\n // Compute byte size\r\n return (base64String.length * 3) / 4 - padding;\r\n}\r\n\r\nconst maybeCompressAttachment = (attachmentType, attachmentSubType, compressOptions) => {\r\n const isAutoCompress = compressOptions.auto_compress;\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType);\r\n\r\n return isImage && isAutoCompress;\r\n};\r\n\r\nconst base64ToBlob = (base64, type = 'image/jpeg') => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64;\r\n\r\n // Decode Base64 string\r\n const byteCharacters = atob(base64String);\r\n const byteNumbers = new Array(byteCharacters.length);\r\n \r\n for (let i = 0; i < byteCharacters.length; i++) {\r\n byteNumbers[i] = byteCharacters.charCodeAt(i);\r\n }\r\n\r\n const byteArray = new Uint8Array(byteNumbers);\r\n return new Blob([byteArray], { type: type });\r\n}\n\n//# sourceURL=webpack:///./assets/js/helpers.js?");39 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64SizeInBytes\": () => (/* binding */ base64SizeInBytes),\n/* harmony export */ \"base64ToBlob\": () => (/* binding */ base64ToBlob),\n/* harmony export */ \"base64ToFile\": () => (/* binding */ base64ToFile),\n/* harmony export */ \"cachedMediaData\": () => (/* binding */ cachedMediaData),\n/* harmony export */ \"disableAllButtons\": () => (/* binding */ disableAllButtons),\n/* harmony export */ \"disableBulkButtons\": () => (/* binding */ disableBulkButtons),\n/* harmony export */ \"elements\": () => (/* binding */ elements),\n/* harmony export */ \"extendAttachment\": () => (/* binding */ extendAttachment),\n/* harmony export */ \"fileToBase64\": () => (/* binding */ fileToBase64),\n/* harmony export */ \"getFileFromUrl\": () => (/* binding */ getFileFromUrl),\n/* harmony export */ \"handleRemovePathButton\": () => (/* binding */ handleRemovePathButton),\n/* harmony export */ \"humanFileSize\": () => (/* binding */ humanFileSize),\n/* harmony export */ \"isDocHidden\": () => (/* binding */ isDocHidden),\n/* harmony export */ \"logMessage\": () => (/* binding */ logMessage),\n/* harmony export */ \"maybeCompressAttachment\": () => (/* binding */ maybeCompressAttachment),\n/* harmony export */ \"objectToFormData\": () => (/* binding */ objectToFormData),\n/* harmony export */ \"populatePathInput\": () => (/* binding */ populatePathInput),\n/* harmony export */ \"removeAllButtons\": () => (/* binding */ removeAllButtons),\n/* harmony export */ \"renderDirectories\": () => (/* binding */ renderDirectories),\n/* harmony export */ \"renderTemplate\": () => (/* binding */ renderTemplate),\n/* harmony export */ \"restoreBulkButtons\": () => (/* binding */ restoreBulkButtons),\n/* harmony export */ \"updateButtonText\": () => (/* binding */ updateButtonText)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\n// move static helper functions here\r\nconst elements = {\r\n bulkBtn: document.querySelector(\"[name='squeeze_bulk']\"),\r\n bulkAgainBtn: document.querySelector(\"[name='squeeze_bulk_again']\"),\r\n bulkPathBtn: document.querySelector(\"[name='squeeze_bulk_path_button']\"),\r\n bulkPathRemoveBtns: document.querySelectorAll(\".squeeze-path-list__remove\"),\r\n selectPathBtn: document.querySelector(\"[name='squeeze_select_path_button']\"),\r\n savePathBtn: document.querySelector(\"[name='squeeze_save_path_button']\"),\r\n pathDialog: document.getElementById(\"squeeze-path-dialog\"),\r\n closePathDialogBtn: document.querySelector(\"[name='squeeze_close_path_dialog_button']\"),\r\n pathInput: document.querySelector(\"[name='squeeze_bulk_path']\"),\r\n pathList: document.querySelector(\".squeeze-path-list\"),\r\n postsFilterForm: document.querySelector(\"#posts-filter\"),\r\n dirContainer: document.getElementById(\"squeeze-bulk-directory-list\"),\r\n bulkLogInput: document.querySelector(\"#squeeze-log-data\"),\r\n pauseBulkBtn: document.querySelector(\"[name='squeeze_pause_page_bulk']\")\r\n}\r\n\r\nconst cachedMediaData = {\r\n isPaused: false,\r\n page: 1,\r\n process: '',\r\n mediaIDs: [],\r\n lastId: 0,\r\n totalImages: document.querySelector(\"[name='squeeze_bulk_total_images']\")?.value || 0,\r\n uncompressedImages: document.querySelector(\"[name='squeeze_bulk_uncompressed_images']\")?.value || 0,\r\n target: null\r\n}\r\n\r\nconst loadTemplate = async (templatePath, data) => {\r\n const response = await fetch(templatePath);\r\n let template = await response.text();\r\n\r\n // Process sub-templates\r\n const subTemplateRegex = /\\{\\{\\>\\s*(.*?)\\s*\\}\\}/g;\r\n let match;\r\n while ((match = subTemplateRegex.exec(template)) !== null) {\r\n const subTemplatePath = `${squeezeOptions.templateBase}/${match[1].trim()}.html`;\r\n const subTemplate = await loadTemplate(subTemplatePath, data);\r\n template = template.replace(match[0], subTemplate);\r\n }\r\n\r\n // Function to safely evaluate conditions (supports boolean variables, expressions, AND/OR)\r\n const evaluateCondition = (condition, data) => {\r\n try {\r\n // Convert standalone boolean variables (e.g., webp_lossless) to data['webp_lossless']\r\n condition = condition.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match) =>\r\n match in data ? `data['${match}']` : match\r\n );\r\n\r\n return new Function(\"data\", `with(data) { return ${condition}; }`)(data);\r\n } catch (e) {\r\n console.error(\"Error evaluating condition:\", condition, e);\r\n return false;\r\n }\r\n };\r\n\r\n // Recursive function to process nested if-else conditions\r\n const processIfStatements = (template) => {\r\n return template.replace(/\\{\\{#if ([\\s\\S]*?)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g, (match, condition, content) => {\r\n condition = condition.trim();\r\n const conditionResult = evaluateCondition(condition, data);\r\n\r\n // Extract and split the if-else blocks\r\n const elseMatch = content.match(/\\{\\{#else\\}\\}([\\s\\S]*)/);\r\n const trueBlock = elseMatch ? content.replace(/\\{\\{#else\\}\\}([\\s\\S]*)/, \"\") : content;\r\n const falseBlock = elseMatch ? elseMatch[1] : \"\";\r\n\r\n // Process nested if statements recursively\r\n return processIfStatements(conditionResult ? trueBlock : falseBlock);\r\n });\r\n };\r\n\r\n // Apply recursive processing of if conditions\r\n template = processIfStatements(template);\r\n\r\n // Replace variables\r\n return template.replace(/\\{\\{(.*?)\\}\\}/g, (match, key) => data[key.trim()] || '');\r\n}\r\n\r\nconst renderTemplate = async (templatePath, data, target = null) => {\r\n const renderedHTML = await loadTemplate(templatePath, data);\r\n\r\n // Create a temporary container to parse HTML\r\n const tempContainer = document.createElement(\"template\");\r\n tempContainer.innerHTML = renderedHTML.trim();\r\n\r\n if (!target) {\r\n return tempContainer.content.firstChild;\r\n }\r\n\r\n target.appendChild(tempContainer.content.firstChild);\r\n\r\n // Return the last element of the rendered template\r\n return target.lastElementChild;\r\n}\r\n\r\nconst logMessage = async (msg, options = {}) => {\r\n const { mediaLogWrapper = null, isStart = false, isPause = false } = options;\r\n let { title = '', iconId = 'check-mark-circle-icon' } = options;\r\n\r\n if (!elements.bulkLogInput) return;\r\n\r\n if (isStart || isPause) {\r\n iconId = isPause ? 'pause-button-icon' : 'image-file-icon';\r\n title = isPause ? __('Bulk squeezing has been paused!', 'squeeze') : `${__('Media', 'squeeze')} ${title}:`;\r\n return await renderTemplate(squeezeOptions.templates.logWrapper, { title: title, msg: msg, iconId: iconId, isStart: isStart, isPause: isPause }, elements.bulkLogInput);\r\n } else {\r\n if (mediaLogWrapper) {\r\n const process = mediaLogWrapper.querySelector(\".media-log-process\");\r\n const step = await renderTemplate(squeezeOptions.templates.logStep, { msg: msg, iconId: iconId }, process);\r\n\r\n if (msg && msg.includes('squeeze-comparison-table')) {\r\n const comparisonTable = step.querySelector('.squeeze-comparison-table');\r\n const toggleBtn = await renderTemplate(squeezeOptions.templates.logDetailsButton, { buttonText: __('Show details', 'squeeze') }, mediaLogWrapper);\r\n\r\n toggleBtn.addEventListener(\"click\", () => {\r\n comparisonTable.classList.toggle(\"show\");\r\n toggleBtn.textContent = comparisonTable.classList.contains(\"show\") ? __('Hide details', 'squeeze') : __('Show details', 'squeeze');\r\n });\r\n step.closest(\".media-log-wrapper\").appendChild(comparisonTable);\r\n step.closest(\".media-log-wrapper\").appendChild(toggleBtn);\r\n }\r\n } else {\r\n elements.bulkLogInput.innerHTML += msg + `<br>`;\r\n }\r\n }\r\n}\r\n\r\nconst restoreBulkButtons = () => {\r\n elements.bulkBtn.disabled = false;\r\n elements.bulkAgainBtn.disabled = false;\r\n elements.bulkPathBtn.disabled = false;\r\n elements.selectPathBtn.disabled = false;\r\n updateButtonText(elements.bulkBtn, __('Run Bulk Squeeze', 'squeeze'), '#play-button-round-icon');\r\n updateButtonText(elements.bulkAgainBtn, __('Repeat Bulk Squeeze', 'squeeze'), '#combine-left-right-outline-icon');\r\n updateButtonText(elements.bulkPathBtn, __('Run Directory Squeeze', 'squeeze'), '#play-button-round-icon');\r\n elements.bulkBtn.dataset.running = 'false';\r\n elements.bulkAgainBtn.dataset.running = 'false';\r\n elements.bulkPathBtn.dataset.running = 'false';\r\n elements.bulkPathRemoveBtns?.forEach((btn) => {\r\n btn.disabled = false;\r\n });\r\n\r\n cachedMediaData.process = '';\r\n cachedMediaData.mediaIDs = [];\r\n cachedMediaData.page = 1;\r\n}\r\n\r\nconst disableBulkButtons = () => {\r\n elements.bulkBtn.disabled = true;\r\n elements.bulkAgainBtn.disabled = true;\r\n elements.bulkPathBtn.disabled = true;\r\n elements.selectPathBtn.disabled = true;\r\n elements.bulkPathRemoveBtns?.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst disableAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst removeAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.remove());\r\n}\r\n\r\nconst updateButtonText = (button, text, svgAnchor = false) => {\r\n button.childNodes.forEach((node) => {\r\n if (node.nodeName === '#text' && node.textContent.trim() !== '') {\r\n node.textContent = text;\r\n }\r\n if (svgAnchor && node.nodeName === 'svg') {\r\n node.querySelector('use').setAttribute('xlink:href', svgAnchor);\r\n }\r\n });\r\n}\r\n\r\n// Function to render directories in the dialog\r\nconst renderDirectories = async (dirs, parentDir = null, listeners = {}) => {\r\n if (!dirs) return;\r\n if (typeof dirs === 'object') dirs = Object.values(dirs);\r\n if (!elements.dirContainer.classList.contains(\"loaded\")) elements.dirContainer.innerHTML = \"\";\r\n\r\n if (dirs.length === 0 && !parentDir) {\r\n const listItem = await renderTemplate(squeezeOptions.templates.directoryItemEmpty, { emptyText: __('No directories found!', 'squeeze') }, elements.dirContainer);\r\n return;\r\n }\r\n\r\n const selectedFolders = JSON.parse(elements.pathInput.value);\r\n let target;\r\n\r\n for (const dir of dirs) {\r\n const listItemClasses = [];\r\n\r\n if (dir.parent === '/') {\r\n listItemClasses.push(\"loaded\", \"opened\");\r\n }\r\n\r\n if (parentDir) {\r\n target = parentDir;\r\n } else if (dir.parent) {\r\n const parentElement = elements.dirContainer.querySelector(`[data-path=\"${dir.parent}\"]`);\r\n if (parentElement) {\r\n target = parentElement;\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n\r\n const listItem = await renderTemplate(\r\n squeezeOptions.templates.directoryItem,\r\n {\r\n parent: dir.parent,\r\n path: dir.path,\r\n label: dir.name,\r\n classes: listItemClasses.join(\" \"),\r\n isWritable: dir.is_writeable && !(Array.isArray(selectedFolders) && selectedFolders.includes(dir.path)),\r\n isChecked: dir.is_writeable && Array.isArray(selectedFolders) && selectedFolders.includes(dir.path),\r\n },\r\n target\r\n )\r\n\r\n listItem.querySelector(\"label\").addEventListener(\"click\", listeners.handleDirectoryClick);\r\n listItem.querySelector(\"input[type='checkbox']\")?.addEventListener(\"change\", listeners.handleDirectoryCheck);\r\n }\r\n\r\n elements.dirContainer.classList.add(\"loaded\");\r\n}\r\n\r\nconst handleRemovePathButton = (e) => {\r\n e.preventDefault();\r\n const item = e.target.closest(\".squeeze-path-list__item\");\r\n if (item) {\r\n item.remove();\r\n const currentPaths = Array.from(elements.pathList.querySelectorAll(\".squeeze-path-list__input\"))\r\n .map(input => input.value.trim())\r\n .filter(value => value !== '');\r\n elements.pathInput.value = JSON.stringify(currentPaths);\r\n }\r\n}\r\n\r\nconst populatePathInput = async () => {\r\n const path = elements.pathInput.value;\r\n if (!path) return;\r\n\r\n try {\r\n const selectedFolders = JSON.parse(path);\r\n const items = elements.pathList.querySelectorAll(\".squeeze-path-list__item\");\r\n\r\n items.forEach(item => item.remove());\r\n\r\n for (const folder of selectedFolders) {\r\n const item = await renderTemplate(squeezeOptions.templates.pathListItem, { folder: folder }, elements.pathList);\r\n const removeButton = item.querySelector(\".squeeze-path-list__remove\");\r\n removeButton.addEventListener(\"click\", handleRemovePathButton);\r\n\r\n }\r\n } catch (error) {\r\n alert(__('Error parsing path input!', 'squeeze'));\r\n console.error('Error parsing path input:', error);\r\n }\r\n}\r\n\r\nconst getHiddenProp = () => {\r\n var prefixes = ['webkit', 'moz', 'ms', 'o'];\r\n\r\n // if 'hidden' is natively supported just return it\r\n if ('hidden' in document) return 'hidden';\r\n\r\n // otherwise loop over all the known prefixes until we find one\r\n for (let i = 0; i < prefixes.length; i++) {\r\n if ((prefixes[i] + 'Hidden') in document)\r\n return prefixes[i] + 'Hidden';\r\n }\r\n\r\n // otherwise it's not supported\r\n return null;\r\n}\r\n\r\nconst isDocHidden = () => {\r\n const prop = getHiddenProp();\r\n if (!prop) return false;\r\n\r\n return document[prop];\r\n}\r\n\r\n/**\r\n * @see https://stackoverflow.com/a/20732091\r\n */\r\nconst humanFileSize = (size) => {\r\n let i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));\r\n return +((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];\r\n}\r\n\r\nconst base64SizeInBytes = (base64) => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64; \r\n\r\n // Calculate padding characters ('=' at the end of Base64)\r\n const padding = (base64String.match(/=+$/) || [\"\"])[0].length;\r\n\r\n // Compute byte size\r\n return (base64String.length * 3) / 4 - padding;\r\n}\r\n\r\nconst maybeCompressAttachment = (attachmentType, attachmentSubType, compressOptions = null) => {\r\n const isAutoCompress = compressOptions?.auto_compress ?? true;\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType);\r\n\r\n return isImage && isAutoCompress;\r\n};\r\n\r\nconst base64ToBlob = (base64, type = 'image/jpeg') => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64;\r\n\r\n // Decode Base64 string\r\n const byteCharacters = atob(base64String);\r\n const byteNumbers = new Array(byteCharacters.length);\r\n \r\n for (let i = 0; i < byteCharacters.length; i++) {\r\n byteNumbers[i] = byteCharacters.charCodeAt(i);\r\n }\r\n\r\n const byteArray = new Uint8Array(byteNumbers);\r\n return new Blob([byteArray], { type: type });\r\n}\r\n\r\nconst base64ToFile = (base64, fileName = 'image.jpg', type = 'image/jpeg') => {\r\n const blob = base64ToBlob(base64, type);\r\n return new File([blob], fileName, { type: type });\r\n}\r\n\r\nconst fileToBase64 = (file) => {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = () => resolve(reader.result);\r\n reader.onerror = (error) => reject(error);\r\n reader.readAsDataURL(file);\r\n });\r\n}\r\n\r\nfunction objectToFormData(obj, fd = null, parentKey = null) {\r\n const formData = fd || new FormData();\r\n\r\n for (const key in obj) {\r\n if (!obj.hasOwnProperty(key)) continue;\r\n const value = obj[key];\r\n\r\n // build the form key: either \"foo\", \"parent[foo]\" or \"parent[]\" for arrays\r\n const formKey = parentKey\r\n ? Array.isArray(obj)\r\n ? `${parentKey}[]`\r\n : `${parentKey}[${key}]`\r\n : key;\r\n\r\n // Files or Blobs go straight in\r\n if (value instanceof File || value instanceof Blob) {\r\n formData.append(formKey, value, value.name);\r\n }\r\n // Arrays: recurse so they become key[]=val0, key[]=val1…\r\n else if (Array.isArray(value)) {\r\n objectToFormData(value, formData, formKey);\r\n }\r\n // Plain objects: recurse so they become key[subkey]=subval\r\n else if (\r\n value !== null &&\r\n typeof value === 'object' &&\r\n !(value instanceof Date)\r\n ) {\r\n objectToFormData(value, formData, formKey);\r\n }\r\n // Dates: convert to ISO string (or format as you like)\r\n else if (value instanceof Date) {\r\n formData.append(formKey, value.toISOString());\r\n }\r\n // Everything else (number, string, boolean, null, undefined)\r\n else {\r\n // Explicitly convert undefined to empty string so PHP sees it\r\n const stringVal =\r\n value === undefined || value === null ? '' : String(value);\r\n formData.append(formKey, stringVal);\r\n }\r\n }\r\n\r\n return formData;\r\n}\r\n\r\n/**\r\n * Extend the attachment object with additional data from the file.\r\n * @param {object} attachment \r\n * @param {object} file \r\n * @returns {object} — the extended attachment object.\r\n */\r\nconst extendAttachment = async (attachment, file) => {\r\n if (typeof attachment !== 'object' || !attachment.attributes) {\r\n console.warn('Invalid attachment object:', attachment);\r\n return;\r\n }\r\n\r\n const attributes = attachment.attributes;\r\n\r\n if (file?.base64) {\r\n attributes.base64Compressed = file.base64; // Use the base64 data from the attachment\r\n }\r\n\r\n if (file?.base64Webp) {\r\n attributes.base64WebpCompressed = file.base64Webp; // Use the WebP base64 data from the attachment\r\n }\r\n\r\n if (file?.originalFile) {\r\n attributes.originalFile = file.originalFile; // Use the original file from the attachment to be able to create a backup\r\n }\r\n\r\n return attachment;\r\n}\r\n\r\nconst getFileFromUrl = async (url, filename, format) => {\r\n const response = await fetch(url);\r\n const blob = await response.blob();\r\n const mimeType = format ? `image/${format}` : blob.type;\r\n return new File([blob], filename, { type: mimeType });\r\n}\n\n//# sourceURL=webpack:///./assets/js/helpers.js?"); 40 40 41 41 /***/ }), … … 47 47 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 48 48 49 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SQUEEZE)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nclass SQUEEZE {\r\n\r\n constructor(squeeze) {\r\n this.options = JSON.parse(squeeze.options); // plugin options\r\n this.nonce = squeeze.nonce; // nonce\r\n this.ajaxUrl = squeeze.ajaxUrl; // ajax url\r\n this.timeout = parseInt(this.options.timeout) * 1000; // convert to milliseconds\r\n this.poolSize = navigator.hardwareConcurrency || 1; // number of threads\r\n }\r\n\r\n handleCompress = async ( attachment ) => {\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const name = attachmentData.name;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const sizes = attachmentData.sizes;\r\n const format = mime.split(\"/\")[1];\r\n const sourceType = format;\r\n const outputType = format;\r\n const skipFull = attachmentData.originalImageName === undefined ? true : false;\r\n const timeout = this.timeout;\r\n const isPreview = attachmentData?.isPreview ?? false;\r\n const file = attachmentData?.file ?? null;\r\n\r\n //console.log(attachmentData, 'attachmentData')\r\n\r\n const worker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(\"assets_js_worker_js\"), __webpack_require__.b), {type: undefined}); // worker url\r\n worker.postMessage({\r\n action: 'compress',\r\n format,\r\n url,\r\n name,\r\n sourceType,\r\n outputType,\r\n mime,\r\n sizes,\r\n skipFull,\r\n timeout,\r\n isPreview,\r\n file,\r\n options: this.options,\r\n //urlOriginal: urlOriginal,\r\n });\r\n\r\n return new Promise((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n worker.terminate();\r\n console.warn('Worker terminated');\r\n reject(__('Request timed out.', 'squeeze'));\r\n }, timeout);\r\n\r\n worker.onmessage = (event) => {\r\n clearTimeout(timeoutId);\r\n if (event.data.error) {\r\n reject(event.data.error);\r\n } else {\r\n resolve(event.data);\r\n }\r\n worker.terminate();\r\n };\r\n\r\n worker.onerror = (error) => {\r\n clearTimeout(timeoutId);\r\n reject(`Worker error: ${error.message}`);\r\n };\r\n });\r\n\r\n }\r\n\r\n handleUpload = async ({ attachment, base64, type = 'uncompressed', mediaIDs = [] }) => {\r\n\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const format = mime.split(\"/\")[1];\r\n const sizes = attachmentData.sizes;\r\n\r\n //console.log(attachmentData, 'attachmentData')\r\n\r\n const data = {\r\n action: 'squeeze_update_attachment',\r\n _ajax_nonce: this.nonce,\r\n filename: filename,\r\n type: 'image',\r\n format: format,\r\n base64: base64.base64,\r\n base64Sizes: base64.base64Sizes,\r\n base64Webp: base64.base64Webp,\r\n base64SizesWebp: base64.base64SizesWebp,\r\n attachmentID: attachmentID,\r\n url: url,\r\n process: type,\r\n }\r\n\r\n console.log(data, 'squeeze_update_attachment') \r\n\r\n try {\r\n const uploadResponse = await jQuery.ajax({\r\n url: this.ajaxUrl, // + '111',\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n //if (type === 'uncompressed' || type === 'all' || type === 'path') {\r\n //if (uploadResponse.success) {\r\n uploadResponse['mediaIDs'] = mediaIDs;\r\n //}\r\n\r\n uploadResponse['filename'] = filename;\r\n uploadResponse['url'] = url;\r\n uploadResponse['sizes'] = sizes;\r\n\r\n return uploadResponse;\r\n \r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n };\r\n }\r\n\r\n }\r\n\r\n handleBulkUpload = async (type = 'uncompressed', mediaIDs = []) => {\r\n let currentID;\r\n let attachment;\r\n\r\n switch (type) {\r\n case 'all':\r\n case 'uncompressed':\r\n currentID = mediaIDs[0];\r\n break;\r\n case 'path':\r\n currentID = mediaIDs[0]?.filename;\r\n break;\r\n default:\r\n currentID = 0;\r\n break;\r\n }\r\n\r\n if (type === 'path') {\r\n\r\n \r\n\r\n attachment = {\r\n attributes: {\r\n url: mediaIDs[0].url,\r\n mime: mediaIDs[0].mime,\r\n name: mediaIDs[0].name,\r\n filename: mediaIDs[0].filename,\r\n id: mediaIDs[0].id,\r\n sizes: mediaIDs[0]?.sizes,\r\n }\r\n }\r\n\r\n } else {\r\n\r\n const attachmentResponse = await this.getAttachment(currentID); \r\n if (attachmentResponse.success === false) {\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': attachmentResponse.data\r\n }\r\n }\r\n const attachmentData = attachmentResponse.data;\r\n attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n\r\n }\r\n\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n\r\n const mediaType = attachment.attributes.mime.split(\"/\")[0];\r\n const mediaSubType = attachment.attributes.mime.split(\"/\")[1];\r\n\r\n if (!this.maybeCompressAttachment(mediaType, mediaSubType)) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': __('Skipped', 'squeeze')\r\n }\r\n }\r\n\r\n try {\r\n const compressData = await this.handleCompress( attachment );\r\n const uploadData = await this.handleUpload({ attachment: attachment, base64: compressData, type: type, mediaIDs: mediaIDs })\r\n\r\n return uploadData;\r\n\r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n }\r\n }\r\n\r\n }\r\n\r\n maybeCompressAttachment = (attachmentType, attachmentSubType) => {\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType)\r\n\r\n if (isImage) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n \r\n\r\n handleRestore = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_restore_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n };\r\n\r\n const response = await jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n };\r\n\r\n // Get list of attachments by path\r\n getAttachmentsByPath = async (path) => {\r\n\r\n const data = {\r\n action: 'squeeze_get_attachment_by_path',\r\n path: path,\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getAttachment = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_get_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getNextAttachments = async (page = 1, type = 'uncompressed', lastId = 0) => {\r\n const data = {\r\n action: 'squeeze_get_next_attachments',\r\n _ajax_nonce: this.nonce,\r\n page: page,\r\n type: type,\r\n lastId: lastId,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getDirectories = async (parentDir = false) => {\r\n const data = {\r\n action: 'squeeze_get_directories',\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n if (parentDir) {\r\n data['parentDir'] = parentDir;\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n \r\n\r\n setOptions = async (options) => {\r\n const data = {\r\n action: 'squeeze_set_options',\r\n _ajax_nonce: this.nonce,\r\n options: options,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /*\r\n getSizesFromFile = (file) => {\r\n if (!file) return;\r\n\r\n // get list of thumbnails from file\r\n const sizes = {};\r\n \r\n const fd = new FormData();\r\n fd.append('action', 'squeeze_get_sizes_from_file');\r\n fd.append('_ajax_nonce', this.nonce);\r\n fd.append('file', file);\r\n\r\n jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: fd,\r\n processData: false,\r\n contentType: false,\r\n async: false, // synchronous request\r\n }).done((response) => {\r\n console.log(response, 'getSizesFromFile response');\r\n if (response.success) {\r\n Object.keys(response.data).forEach((size) => {\r\n sizes[size] = response.data[size];\r\n });\r\n } else {\r\n console.error('Error getting sizes from file:', response.data);\r\n }\r\n }).fail((error) => {\r\n console.error('AJAX error:', error);\r\n });\r\n\r\n return sizes;\r\n\r\n }\r\n */\r\n\r\n}\n\n//# sourceURL=webpack:///./assets/js/squeeze.js?"); 49 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SQUEEZE)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var browser_image_compression__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! browser-image-compression */ \"./node_modules/browser-image-compression/dist/browser-image-compression.mjs\");\n/* harmony import */ var _jsquash_webp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @jsquash/webp */ \"./node_modules/@jsquash/webp/encode.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nclass SQUEEZE {\r\n\r\n constructor(squeeze) {\r\n this.options = JSON.parse(squeeze.options); // plugin options\r\n this.nonce = squeeze.nonce; // nonce\r\n this.ajaxUrl = squeeze.ajaxUrl; // ajax url\r\n this.timeout = parseInt(this.options.timeout) * 1000; // convert to milliseconds\r\n this.poolSize = navigator.hardwareConcurrency || 1; // number of threads\r\n }\r\n\r\n handleCompress = async ( attachment, type = 'uncompressed' ) => {\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const name = attachmentData.name;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const sizes = attachmentData.sizes;\r\n const format = mime.split(\"/\")[1];\r\n const sourceType = format;\r\n const outputType = format;\r\n const skipFull = attachmentData?.skipFull ?? attachmentData.originalImageName === undefined ? true : false;\r\n const timeout = this.timeout;\r\n const isPreview = attachmentData?.isPreview ?? false;\r\n const file = attachmentData?.file ?? null; // the original file, it passed for the newly uploaded attachment to compress it\r\n\r\n // the original compressed image base64, it passed when the attachment was already compressed and we need to compress thumbs only\r\n // we pass it in order to prevent re-compressing the original image when we need to compress thumbs only\r\n const base64Compressed = attachmentData?.base64Compressed ?? null; \r\n const base64WebpCompressed = attachmentData?.base64WebpCompressed ?? null; // the original compressed webp image base64\r\n\r\n const worker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(\"assets_js_worker_js\"), __webpack_require__.b), {type: undefined}); // worker url\r\n const channel = new MessageChannel();\r\n worker.postMessage({\r\n action: 'compress',\r\n format,\r\n url,\r\n name,\r\n sourceType,\r\n outputType,\r\n mime,\r\n sizes,\r\n skipFull,\r\n timeout,\r\n isPreview,\r\n file,\r\n base64Compressed,\r\n base64WebpCompressed,\r\n type,\r\n options: this.options,\r\n //urlOriginal: urlOriginal,\r\n }, [channel.port2]);\r\n\r\n // Listen for compression requests from the worker via port1\r\n channel.port1.onmessage = async (ev) => {\r\n //console.log(\"Worker received compression request:\", ev.data);\r\n const { id, action, fileOrArrayBuffer, mime, options } = ev.data;\r\n if (action !== 'imageCompression') return;\r\n\r\n try {\r\n // Accept ArrayBuffer or Blob\r\n const blob = (fileOrArrayBuffer instanceof ArrayBuffer)\r\n ? new Blob([this.toUint8Array(fileOrArrayBuffer)], { type: mime })\r\n : fileOrArrayBuffer;\r\n\r\n const compressedBlob = await (0,browser_image_compression__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(blob, { useWebWorker: true, ...(options || {}) });\r\n\r\n // quick checks\r\n //console.log('compressedBlob.type, size:', compressedBlob.type, compressedBlob.size);\r\n // normalize final binary\r\n const compressedArrayBuffer = await compressedBlob.arrayBuffer();\r\n\r\n // Reply with the compressed ArrayBuffer (transfer to avoid copy)\r\n channel.port1.postMessage({ id, ok: true, arrayBuffer: compressedArrayBuffer }, [compressedArrayBuffer]);\r\n } catch (err) {\r\n channel.port1.postMessage({ id, ok: false, error: err.message || String(err) });\r\n }\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n worker.terminate();\r\n console.warn('Worker compress terminated', name, sourceType, outputType);\r\n reject(__('Request timed out.', 'squeeze'));\r\n }, timeout);\r\n\r\n worker.onmessage = (event) => {\r\n clearTimeout(timeoutId);\r\n if (event.data.error) {\r\n reject(event.data.error);\r\n } else {\r\n resolve(event.data);\r\n }\r\n worker.terminate();\r\n };\r\n\r\n worker.onerror = (error) => {\r\n clearTimeout(timeoutId);\r\n reject(`Worker error: ${error.message}`);\r\n };\r\n });\r\n\r\n }\r\n\r\n handleUpload = async ({ attachment, base64, type = 'uncompressed', mediaIDs = [] }) => {\r\n\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const format = base64?.isDirectWebp && type !== 'path' ? 'webp' : mime.split(\"/\")[1];\r\n const sizes = attachmentData.sizes;\r\n\r\n const isDirectWebp = base64?.isDirectWebp && mime !== 'image/webp';\r\n const isBackupOriginal = this.options?.backup_original ?? false; // check if backup original is enabled\r\n let originalFile = attachmentData?.originalFile ?? null; // the original file, used for creating backup\r\n \r\n // if originalFile is not provided, try to get it from the URL\r\n // used when the attachment needs to be converted to webp from jpg or png\r\n if (!originalFile && type !== 'path' && isBackupOriginal && isDirectWebp) {\r\n const file = await (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getFileFromUrl)(url, filename, mime.split(\"/\")[1])\r\n //console.log('conveting original file to webp', file);\r\n originalFile = await this.convertFileToWebp(file);\r\n }\r\n //console.log('handleUpload attachmentData', attachmentData)\r\n\r\n const data = {\r\n action: 'squeeze_update_attachment',\r\n _ajax_nonce: this.nonce,\r\n filename: filename,\r\n type: 'image',\r\n format: format,\r\n base64: base64.base64,\r\n base64Sizes: base64.base64Sizes,\r\n base64Webp: base64.base64Webp,\r\n base64SizesWebp: base64.base64SizesWebp,\r\n attachmentID: attachmentID,\r\n url: url,\r\n process: type,\r\n originalFile: originalFile,\r\n }\r\n\r\n const formData = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.objectToFormData)(data);\r\n\r\n //console.log('squeeze_update_attachment', JSON.stringify(data, null, 2));\r\n\r\n try {\r\n const uploadResponse = await jQuery.ajax({\r\n url: this.ajaxUrl, // + '111',\r\n type: 'POST',\r\n data: formData,\r\n processData: false, // very important!\r\n contentType: false, // very important!\r\n });\r\n\r\n //if (uploadResponse.success) {\r\n uploadResponse['mediaIDs'] = mediaIDs;\r\n //}\r\n\r\n if (!uploadResponse?.data?.url) {\r\n uploadResponse.url = url; // fallback to original URL if not provided\r\n }\r\n\r\n //console.log('uploadResponse', JSON.stringify(uploadResponse, null, 2));\r\n\r\n return uploadResponse;\r\n \r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n };\r\n }\r\n\r\n }\r\n\r\n handleBulkUpload = async (type = 'uncompressed', mediaIDs = []) => {\r\n let currentID;\r\n let attachment;\r\n\r\n switch (type) {\r\n case 'all':\r\n case 'uncompressed':\r\n currentID = mediaIDs[0];\r\n break;\r\n case 'path':\r\n currentID = mediaIDs[0]?.filename;\r\n break;\r\n default:\r\n currentID = 0;\r\n break;\r\n }\r\n\r\n if (type === 'path') {\r\n\r\n \r\n\r\n attachment = {\r\n attributes: {\r\n url: mediaIDs[0].url,\r\n mime: mediaIDs[0].mime,\r\n name: mediaIDs[0].name,\r\n filename: mediaIDs[0].filename,\r\n id: mediaIDs[0].id,\r\n sizes: mediaIDs[0]?.sizes,\r\n }\r\n }\r\n\r\n } else {\r\n\r\n const attachmentResponse = await this.getAttachment(currentID); \r\n if (attachmentResponse.success === false) {\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': attachmentResponse.data\r\n }\r\n }\r\n const attachmentData = attachmentResponse.data;\r\n attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n\r\n }\r\n\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n\r\n const mediaType = attachment.attributes.mime.split(\"/\")[0];\r\n const mediaSubType = attachment.attributes.mime.split(\"/\")[1];\r\n\r\n if (!(0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment)(mediaType, mediaSubType)) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': __('Skipped', 'squeeze')\r\n }\r\n }\r\n\r\n try {\r\n const compressData = await this.handleCompress( attachment, type );\r\n const uploadData = await this.handleUpload({ attachment: attachment, base64: compressData, type: type, mediaIDs: mediaIDs })\r\n\r\n return uploadData;\r\n\r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error?.message ?? error,\r\n 'success': false\r\n }\r\n }\r\n\r\n }\r\n\r\n \r\n\r\n handleRestore = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_restore_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n };\r\n\r\n const response = await jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n };\r\n\r\n // Get list of attachments by path\r\n getAttachmentsByPath = async (path) => {\r\n\r\n const data = {\r\n action: 'squeeze_get_attachment_by_path',\r\n path: path,\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getAttachment = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_get_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getNextAttachments = async (page = 1, type = 'uncompressed', lastId = 0) => {\r\n const data = {\r\n action: 'squeeze_get_next_attachments',\r\n _ajax_nonce: this.nonce,\r\n page: page,\r\n type: type,\r\n lastId: lastId,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getDirectories = async (parentDir = false) => {\r\n const data = {\r\n action: 'squeeze_get_directories',\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n if (parentDir) {\r\n data['parentDir'] = parentDir;\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n \r\n\r\n setOptions = async (options) => {\r\n const data = {\r\n action: 'squeeze_set_options',\r\n _ajax_nonce: this.nonce,\r\n options: options,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Compresses an image before upload.\r\n * If the compressSizes parameter is provided, it will compress the sizes specified along with the original image.\r\n * \r\n * @param {File} file - The file to be compressed\r\n * @param {object} compressSizes - Optional sizes for compression\r\n * @returns {Promise<object|boolean>} - Returns a Promise that resolves to the compressed file as a base64 object or false if the file is invalid\r\n */\r\n compressBeforeUpload = async (file, compressSizes = null) => {\r\n if (!(file instanceof Blob) && !(file instanceof File)) {\r\n console.error('Invalid file type:', file);\r\n return false; // Return false if the file is not a Blob or File\r\n }\r\n\r\n const attachment = {\r\n attributes: {\r\n url: null,\r\n mime: file.type,\r\n name: file.name,\r\n filename: file.name,\r\n id: 0,\r\n sizes: compressSizes,\r\n file: file,\r\n skipFull: false,\r\n }\r\n }\r\n\r\n try {\r\n const base64Obj = await this.handleCompress(attachment);\r\n\r\n return base64Obj; // Return the compressed file as base64Obj\r\n } catch (error) {\r\n console.error(error);\r\n return error; // Return the error for further handling\r\n }\r\n }\r\n\r\n isWebpEncodingSupported = async () => {\r\n try {\r\n const canvas = document.createElement('canvas');\r\n if (!canvas.toDataURL) return false;\r\n const data = canvas.toDataURL('image/webp');\r\n // WebP signature starts with \"data:image/webp\"\r\n return data.indexOf('data:image/webp') === 0;\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n\r\n handleConvertFileToWebp = async (args) => {\r\n const timeout = this.timeout;\r\n \r\n const { file, sourceType, name } = args;\r\n const fileBuffer = await file.arrayBuffer();\r\n const mime = sourceType === 'png' ? 'image/png' : 'image/jpeg';\r\n const inputBlob = new Blob([fileBuffer], { type: mime });\r\n // compression options you can tune\r\n const imageCompressionOptions = {\r\n useWebWorker: true,\r\n fileType: 'image/webp',\r\n };\r\n\r\n return new Promise(async (resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n console.warn('Worker convertToWebp terminated', name);\r\n reject(new Error(__('Request timed out.', 'squeeze')));\r\n }, timeout);\r\n\r\n try {\r\n\r\n const compressedBlob = await (0,browser_image_compression__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(inputBlob, imageCompressionOptions);\r\n\r\n // quick checks\r\n //console.log('compressedBlob.type, size:', compressedBlob.type, compressedBlob.size);\r\n // normalize final binary\r\n const webpArrayBuffer = await compressedBlob.arrayBuffer();\r\n\r\n const webpName = name.replace(/\\.\\w+$/, '.webp');\r\n const webpFile = new File([webpArrayBuffer], webpName, { type: 'image/webp', lastModified: Date.now() });\r\n\r\n clearTimeout(timeoutId);\r\n resolve({ webpFile }); // must return object with webpFile prop\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n console.error('Error during image processing:', error);\r\n reject(error);\r\n }\r\n });\r\n \r\n }\r\n\r\n // helper: normalize buffer-like inputs to Uint8Array\r\n toUint8Array = (bufferLike) => {\r\n if (bufferLike instanceof Uint8Array) return bufferLike;\r\n if (bufferLike instanceof ArrayBuffer) return new Uint8Array(bufferLike);\r\n if (ArrayBuffer.isView(bufferLike)) return new Uint8Array(bufferLike.buffer, bufferLike.byteOffset, bufferLike.byteLength);\r\n // Node Buffer (in some environments) has .buffer and .byteOffset\r\n if (bufferLike && typeof bufferLike === 'object' && bufferLike.buffer) {\r\n return new Uint8Array(bufferLike.buffer, bufferLike.byteOffset || 0, bufferLike.byteLength || bufferLike.length);\r\n }\r\n throw new Error('Unsupported buffer type: ' + Object.prototype.toString.call(bufferLike));\r\n }\r\n\r\n /**\r\n * Convert an image File to WebP.\r\n *\r\n * @param {File} inputFile — the original image File (e.g. JPEG, PNG).\r\n * @returns {Promise<File>} — a Promise that resolves to a WebP File.\r\n */\r\n convertFileToWebp = async (inputFile) => {\r\n // Ensure it’s an image\r\n if (!inputFile.type.startsWith('image/')) {\r\n throw new Error('Input must be an image File');\r\n }\r\n const args = {\r\n file: inputFile,\r\n sourceType: inputFile.type.split('/')[1], // e.g. 'jpeg', 'png'\r\n name: inputFile.name,\r\n }\r\n const webpSupported = await this.isWebpEncodingSupported();\r\n try {\r\n // Convert the image to WebP\r\n let webpData;\r\n if (webpSupported) {\r\n webpData = await this.handleConvertFileToWebp(args);\r\n } else {\r\n console.warn('WebP encoding not supported on this device. Using original format instead.');\r\n const webpName = args.name.replace(/\\.\\w+$/, '.webp');\r\n webpData = await this.convertToWebpWithJsquash(inputFile, webpName);\r\n }\r\n if (!webpData || !webpData.webpFile) {\r\n throw new Error('Failed to convert image to WebP');\r\n }\r\n\r\n return webpData.webpFile; // Return the WebP File\r\n\r\n } catch (error) {\r\n console.error('Error converting image to WebP:', error);\r\n throw error; // Re-throw the error for further handling\r\n }\r\n\r\n }\r\n\r\n /**\r\n * Convert an input (File | Blob | ArrayBuffer | Uint8Array) to a WebP File using @jsquash/webp.\r\n * @param {File|Blob|ArrayBuffer|Uint8Array} input\r\n * @param {string} outputName - desired filename for the .webp output\r\n * @param {{quality?: number, lossless?: boolean, method?: number}} [opts] - encoder options (quality 0-100)\r\n * @returns {Promise<File>} - WebP File\r\n */\r\n convertToWebpWithJsquash = async (input, outputName = 'out.webp', opts = { quality: 100 }) => {\r\n // Normalize input to Blob\r\n let blob;\r\n if (input instanceof Blob) {\r\n blob = input;\r\n } else if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) {\r\n blob = new Blob([input]);\r\n } else {\r\n throw new Error('Unsupported input type. Provide File, Blob, ArrayBuffer or TypedArray.');\r\n }\r\n\r\n // Load image into <img>\r\n const dataURL = await new Promise((resolve, reject) => {\r\n const fr = new FileReader();\r\n fr.onload = () => resolve(fr.result);\r\n fr.onerror = reject;\r\n fr.readAsDataURL(blob);\r\n });\r\n\r\n const img = await new Promise((resolve, reject) => {\r\n const i = new Image();\r\n i.onload = () => resolve(i);\r\n i.onerror = () => reject(new Error('Failed to load image for conversion'));\r\n i.src = dataURL;\r\n // avoid cross-origin taint if data-url is used\r\n });\r\n\r\n // Draw to canvas and extract ImageData\r\n const canvas = document.createElement('canvas');\r\n canvas.width = img.naturalWidth || img.width;\r\n canvas.height = img.naturalHeight || img.height;\r\n const ctx = canvas.getContext('2d');\r\n ctx.drawImage(img, 0, 0);\r\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n\r\n // encode -> returns ArrayBuffer (WASM libwebp)\r\n // opts example: { quality: 75, lossless: false, method: 4 }\r\n const webpArrayBuffer = await (0,_jsquash_webp__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(imageData, opts);\r\n\r\n // Validate a little (size)\r\n if (!webpArrayBuffer || webpArrayBuffer.byteLength < 20) {\r\n throw new Error('jsquash produced an invalid WebP buffer');\r\n }\r\n\r\n // Wrap into File\r\n const webpFile = new File([webpArrayBuffer], outputName.replace(/\\.\\w+$/, '.webp'), {\r\n type: 'image/webp',\r\n lastModified: Date.now(),\r\n });\r\n\r\n return {webpFile};\r\n }\r\n\r\n}\n\n//# sourceURL=webpack:///./assets/js/squeeze.js?"); 50 51 /***/ }), 52 53 /***/ "./node_modules/@jsquash/webp/encode.js": 54 /*!**********************************************!*\ 55 !*** ./node_modules/@jsquash/webp/encode.js ***! 56 \**********************************************/ 57 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 58 59 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ encode),\n/* harmony export */ \"init\": () => (/* binding */ init)\n/* harmony export */ });\n/* harmony import */ var _meta_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./meta.js */ \"./node_modules/@jsquash/webp/meta.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@jsquash/webp/utils.js\");\n/* harmony import */ var wasm_feature_detect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! wasm-feature-detect */ \"./node_modules/wasm-feature-detect/dist/esm/index.js\");\n/**\n * Copyright 2020 Google Inc. All Rights Reserved.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n\nlet emscriptenModule;\nasync function init(module, moduleOptionOverrides) {\n if (await (0,wasm_feature_detect__WEBPACK_IMPORTED_MODULE_0__.simd)()) {\n const webpEncoder = await __webpack_require__.e(/*! import() */ \"vendors-node_modules_jsquash_webp_codec_enc_webp_enc_simd_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./codec/enc/webp_enc_simd.js */ \"./node_modules/@jsquash/webp/codec/enc/webp_enc_simd.js\"));\n emscriptenModule = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.initEmscriptenModule)(webpEncoder.default, module, moduleOptionOverrides);\n return emscriptenModule;\n }\n const webpEncoder = await __webpack_require__.e(/*! import() */ \"vendors-node_modules_jsquash_webp_codec_enc_webp_enc_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./codec/enc/webp_enc.js */ \"./node_modules/@jsquash/webp/codec/enc/webp_enc.js\"));\n emscriptenModule = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.initEmscriptenModule)(webpEncoder.default, module, moduleOptionOverrides);\n return emscriptenModule;\n}\nasync function encode(data, options = {}) {\n if (!emscriptenModule)\n emscriptenModule = init();\n const _options = { ..._meta_js__WEBPACK_IMPORTED_MODULE_2__.defaultOptions, ...options };\n const module = await emscriptenModule;\n const result = module.encode(data.data, data.width, data.height, _options);\n if (!result)\n throw new Error('Encoding error.');\n return result.buffer;\n}\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/encode.js?"); 60 61 /***/ }), 62 63 /***/ "./node_modules/@jsquash/webp/meta.js": 64 /*!********************************************!*\ 65 !*** ./node_modules/@jsquash/webp/meta.js ***! 66 \********************************************/ 67 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 68 69 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"defaultOptions\": () => (/* binding */ defaultOptions),\n/* harmony export */ \"extension\": () => (/* binding */ extension),\n/* harmony export */ \"label\": () => (/* binding */ label),\n/* harmony export */ \"mimeType\": () => (/* binding */ mimeType)\n/* harmony export */ });\nconst label = 'WebP';\nconst mimeType = 'image/webp';\nconst extension = 'webp';\n// These come from struct WebPConfig in encode.h.\nconst defaultOptions = {\n quality: 75,\n target_size: 0,\n target_PSNR: 0,\n method: 4,\n sns_strength: 50,\n filter_strength: 60,\n filter_sharpness: 0,\n filter_type: 1,\n partitions: 0,\n segments: 4,\n pass: 1,\n show_compressed: 0,\n preprocessing: 0,\n autofilter: 0,\n partition_limit: 0,\n alpha_compression: 1,\n alpha_filtering: 1,\n alpha_quality: 100,\n lossless: 0,\n exact: 0,\n image_hint: 0,\n emulate_jpeg_size: 0,\n thread_level: 0,\n low_memory: 0,\n near_lossless: 100,\n use_delta_palette: 0,\n use_sharp_yuv: 0,\n};\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/meta.js?"); 70 71 /***/ }), 72 73 /***/ "./node_modules/@jsquash/webp/utils.js": 74 /*!*********************************************!*\ 75 !*** ./node_modules/@jsquash/webp/utils.js ***! 76 \*********************************************/ 77 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 78 79 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"initEmscriptenModule\": () => (/* binding */ initEmscriptenModule)\n/* harmony export */ });\n/**\n * Copyright 2020 Google Inc. All Rights Reserved.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module.\n */\nfunction initEmscriptenModule(moduleFactory, wasmModule, moduleOptionOverrides = {}) {\n let instantiateWasm;\n if (wasmModule) {\n instantiateWasm = (imports, callback) => {\n const instance = new WebAssembly.Instance(wasmModule, imports);\n callback(instance);\n return instance.exports;\n };\n }\n return moduleFactory({\n // Just to be safe, don't automatically invoke any wasm functions\n noInitialRun: true,\n instantiateWasm,\n ...moduleOptionOverrides,\n });\n}\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/utils.js?"); 80 81 /***/ }), 82 83 /***/ "./node_modules/browser-image-compression/dist/browser-image-compression.mjs": 84 /*!***********************************************************************************!*\ 85 !*** ./node_modules/browser-image-compression/dist/browser-image-compression.mjs ***! 86 \***********************************************************************************/ 87 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 88 89 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ imageCompression)\n/* harmony export */ });\n/**\n * Browser Image Compression\n * v2.0.2\n * by Donald <[email protected]>\n * https://github.com/Donaldcwl/browser-image-compression\n */\n\nfunction _mergeNamespaces(e,t){return t.forEach((function(t){t&&\"string\"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(r){if(\"default\"!==r&&!(r in e)){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}}))})),Object.freeze(e)}function copyExifWithoutOrientation(e,t){return new Promise((function(r,i){let o;return getApp1Segment(e).then((function(e){try{return o=e,r(new Blob([t.slice(0,2),o,t.slice(2)],{type:\"image/jpeg\"}))}catch(e){return i(e)}}),i)}))}const getApp1Segment=e=>new Promise(((t,r)=>{const i=new FileReader;i.addEventListener(\"load\",(({target:{result:e}})=>{const i=new DataView(e);let o=0;if(65496!==i.getUint16(o))return r(\"not a valid JPEG\");for(o+=2;;){const a=i.getUint16(o);if(65498===a)break;const s=i.getUint16(o+2);if(65505===a&&1165519206===i.getUint32(o+4)){const a=o+10;let f;switch(i.getUint16(a)){case 18761:f=!0;break;case 19789:f=!1;break;default:return r(\"TIFF header contains invalid endian\")}if(42!==i.getUint16(a+2,f))return r(\"TIFF header contains invalid version\");const l=i.getUint32(a+4,f),c=a+l+2+12*i.getUint16(a+l,f);for(let e=a+l+2;e<c;e+=12){if(274==i.getUint16(e,f)){if(3!==i.getUint16(e+2,f))return r(\"Orientation data type is invalid\");if(1!==i.getUint32(e+4,f))return r(\"Orientation data count is invalid\");i.setUint16(e+8,1,f);break}}return t(e.slice(o,o+2+s))}o+=2+s}return t(new Blob)})),i.readAsArrayBuffer(e)}));var e={},t={get exports(){return e},set exports(t){e=t}};!function(e){var r,i,UZIP={};t.exports=UZIP,UZIP.parse=function(e,t){for(var r=UZIP.bin.readUshort,i=UZIP.bin.readUint,o=0,a={},s=new Uint8Array(e),f=s.length-4;101010256!=i(s,f);)f--;o=f;o+=4;var l=r(s,o+=4);r(s,o+=2);var c=i(s,o+=2),u=i(s,o+=4);o+=4,o=u;for(var h=0;h<l;h++){i(s,o),o+=4,o+=4,o+=4,i(s,o+=4);c=i(s,o+=4);var d=i(s,o+=4),A=r(s,o+=4),g=r(s,o+2),p=r(s,o+4);o+=6;var m=i(s,o+=8);o+=4,o+=A+g+p,UZIP._readLocal(s,m,a,c,d,t)}return a},UZIP._readLocal=function(e,t,r,i,o,a){var s=UZIP.bin.readUshort,f=UZIP.bin.readUint;f(e,t),s(e,t+=4),s(e,t+=2);var l=s(e,t+=2);f(e,t+=2),f(e,t+=4),t+=4;var c=s(e,t+=8),u=s(e,t+=2);t+=2;var h=UZIP.bin.readUTF8(e,t,c);if(t+=c,t+=u,a)r[h]={size:o,csize:i};else{var d=new Uint8Array(e.buffer,t);if(0==l)r[h]=new Uint8Array(d.buffer.slice(t,t+i));else{if(8!=l)throw\"unknown compression method: \"+l;var A=new Uint8Array(o);UZIP.inflateRaw(d,A),r[h]=A}}},UZIP.inflateRaw=function(e,t){return UZIP.F.inflate(e,t)},UZIP.inflate=function(e,t){return e[0],e[1],UZIP.inflateRaw(new Uint8Array(e.buffer,e.byteOffset+2,e.length-6),t)},UZIP.deflate=function(e,t){null==t&&(t={level:6});var r=0,i=new Uint8Array(50+Math.floor(1.1*e.length));i[r]=120,i[r+1]=156,r+=2,r=UZIP.F.deflateRaw(e,i,r,t.level);var o=UZIP.adler(e,0,e.length);return i[r+0]=o>>>24&255,i[r+1]=o>>>16&255,i[r+2]=o>>>8&255,i[r+3]=o>>>0&255,new Uint8Array(i.buffer,0,r+4)},UZIP.deflateRaw=function(e,t){null==t&&(t={level:6});var r=new Uint8Array(50+Math.floor(1.1*e.length)),i=UZIP.F.deflateRaw(e,r,i,t.level);return new Uint8Array(r.buffer,0,i)},UZIP.encode=function(e,t){null==t&&(t=!1);var r=0,i=UZIP.bin.writeUint,o=UZIP.bin.writeUshort,a={};for(var s in e){var f=!UZIP._noNeed(s)&&!t,l=e[s],c=UZIP.crc.crc(l,0,l.length);a[s]={cpr:f,usize:l.length,crc:c,file:f?UZIP.deflateRaw(l):l}}for(var s in a)r+=a[s].file.length+30+46+2*UZIP.bin.sizeUTF8(s);r+=22;var u=new Uint8Array(r),h=0,d=[];for(var s in a){var A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,0)}var g=0,p=h;for(var s in a){A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,1,d[g++])}var m=h-p;return i(u,h,101010256),h+=4,o(u,h+=4,g),o(u,h+=2,g),i(u,h+=2,m),i(u,h+=4,p),h+=4,h+=2,u.buffer},UZIP._noNeed=function(e){var t=e.split(\".\").pop().toLowerCase();return-1!=\"png,jpg,jpeg,zip\".indexOf(t)},UZIP._writeHeader=function(e,t,r,i,o,a){var s=UZIP.bin.writeUint,f=UZIP.bin.writeUshort,l=i.file;return s(e,t,0==o?67324752:33639248),t+=4,1==o&&(t+=2),f(e,t,20),f(e,t+=2,0),f(e,t+=2,i.cpr?8:0),s(e,t+=2,0),s(e,t+=4,i.crc),s(e,t+=4,l.length),s(e,t+=4,i.usize),f(e,t+=4,UZIP.bin.sizeUTF8(r)),f(e,t+=2,0),t+=2,1==o&&(t+=2,t+=2,s(e,t+=6,a),t+=4),t+=UZIP.bin.writeUTF8(e,t,r),0==o&&(e.set(l,t),t+=l.length),t},UZIP.crc={table:function(){for(var e=new Uint32Array(256),t=0;t<256;t++){for(var r=t,i=0;i<8;i++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update:function(e,t,r,i){for(var o=0;o<i;o++)e=UZIP.crc.table[255&(e^t[r+o])]^e>>>8;return e},crc:function(e,t,r){return 4294967295^UZIP.crc.update(4294967295,e,t,r)}},UZIP.adler=function(e,t,r){for(var i=1,o=0,a=t,s=t+r;a<s;){for(var f=Math.min(a+5552,s);a<f;)o+=i+=e[a++];i%=65521,o%=65521}return o<<16|i},UZIP.bin={readUshort:function(e,t){return e[t]|e[t+1]<<8},writeUshort:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255},readUint:function(e,t){return 16777216*e[t+3]+(e[t+2]<<16|e[t+1]<<8|e[t])},writeUint:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255,e[t+2]=r>>16&255,e[t+3]=r>>24&255},readASCII:function(e,t,r){for(var i=\"\",o=0;o<r;o++)i+=String.fromCharCode(e[t+o]);return i},writeASCII:function(e,t,r){for(var i=0;i<r.length;i++)e[t+i]=r.charCodeAt(i)},pad:function(e){return e.length<2?\"0\"+e:e},readUTF8:function(e,t,r){for(var i,o=\"\",a=0;a<r;a++)o+=\"%\"+UZIP.bin.pad(e[t+a].toString(16));try{i=decodeURIComponent(o)}catch(i){return UZIP.bin.readASCII(e,t,r)}return i},writeUTF8:function(e,t,r){for(var i=r.length,o=0,a=0;a<i;a++){var s=r.charCodeAt(a);if(0==(4294967168&s))e[t+o]=s,o++;else if(0==(4294965248&s))e[t+o]=192|s>>6,e[t+o+1]=128|s>>0&63,o+=2;else if(0==(4294901760&s))e[t+o]=224|s>>12,e[t+o+1]=128|s>>6&63,e[t+o+2]=128|s>>0&63,o+=3;else{if(0!=(4292870144&s))throw\"e\";e[t+o]=240|s>>18,e[t+o+1]=128|s>>12&63,e[t+o+2]=128|s>>6&63,e[t+o+3]=128|s>>0&63,o+=4}}return o},sizeUTF8:function(e){for(var t=e.length,r=0,i=0;i<t;i++){var o=e.charCodeAt(i);if(0==(4294967168&o))r++;else if(0==(4294965248&o))r+=2;else if(0==(4294901760&o))r+=3;else{if(0!=(4292870144&o))throw\"e\";r+=4}}return r}},UZIP.F={},UZIP.F.deflateRaw=function(e,t,r,i){var o=[[0,0,0,0,0],[4,4,8,4,0],[4,5,16,8,0],[4,6,16,16,0],[4,10,16,32,0],[8,16,32,32,0],[8,16,128,128,0],[8,32,128,256,0],[32,128,258,1024,1],[32,258,258,4096,1]][i],a=UZIP.F.U,s=UZIP.F._goodIndex;UZIP.F._hash;var f=UZIP.F._putsE,l=0,c=r<<3,u=0,h=e.length;if(0==i){for(;l<h;){f(t,c,l+(_=Math.min(65535,h-l))==h?1:0),c=UZIP.F._copyExact(e,l,_,t,c+8),l+=_}return c>>>3}var d=a.lits,A=a.strt,g=a.prev,p=0,m=0,w=0,v=0,b=0,y=0;for(h>2&&(A[y=UZIP.F._hash(e,0)]=0),l=0;l<h;l++){if(b=y,l+1<h-2){y=UZIP.F._hash(e,l+1);var E=l+1&32767;g[E]=A[y],A[y]=E}if(u<=l){(p>14e3||m>26697)&&h-l>100&&(u<l&&(d[p]=l-u,p+=2,u=l),c=UZIP.F._writeBlock(l==h-1||u==h?1:0,d,p,v,e,w,l-w,t,c),p=m=v=0,w=l);var F=0;l<h-2&&(F=UZIP.F._bestMatch(e,l,g,b,Math.min(o[2],h-l),o[3]));var _=F>>>16,B=65535&F;if(0!=F){B=65535&F;var U=s(_=F>>>16,a.of0);a.lhst[257+U]++;var C=s(B,a.df0);a.dhst[C]++,v+=a.exb[U]+a.dxb[C],d[p]=_<<23|l-u,d[p+1]=B<<16|U<<8|C,p+=2,u=l+_}else a.lhst[e[l]]++;m++}}for(w==l&&0!=e.length||(u<l&&(d[p]=l-u,p+=2,u=l),c=UZIP.F._writeBlock(1,d,p,v,e,w,l-w,t,c),p=0,m=0,p=m=v=0,w=l);0!=(7&c);)c++;return c>>>3},UZIP.F._bestMatch=function(e,t,r,i,o,a){var s=32767&t,f=r[s],l=s-f+32768&32767;if(f==s||i!=UZIP.F._hash(e,t-l))return 0;for(var c=0,u=0,h=Math.min(32767,t);l<=h&&0!=--a&&f!=s;){if(0==c||e[t+c]==e[t+c-l]){var d=UZIP.F._howLong(e,t,l);if(d>c){if(u=l,(c=d)>=o)break;l+2<d&&(d=l+2);for(var A=0,g=0;g<d-2;g++){var p=t-l+g+32768&32767,m=p-r[p]+32768&32767;m>A&&(A=m,f=p)}}}l+=(s=f)-(f=r[s])+32768&32767}return c<<16|u},UZIP.F._howLong=function(e,t,r){if(e[t]!=e[t-r]||e[t+1]!=e[t+1-r]||e[t+2]!=e[t+2-r])return 0;var i=t,o=Math.min(e.length,t+258);for(t+=3;t<o&&e[t]==e[t-r];)t++;return t-i},UZIP.F._hash=function(e,t){return(e[t]<<8|e[t+1])+(e[t+2]<<4)&65535},UZIP.saved=0,UZIP.F._writeBlock=function(e,t,r,i,o,a,s,f,l){var c,u,h,d,A,g,p,m,w,v=UZIP.F.U,b=UZIP.F._putsF,y=UZIP.F._putsE;v.lhst[256]++,u=(c=UZIP.F.getTrees())[0],h=c[1],d=c[2],A=c[3],g=c[4],p=c[5],m=c[6],w=c[7];var E=32+(0==(l+3&7)?0:8-(l+3&7))+(s<<3),F=i+UZIP.F.contSize(v.fltree,v.lhst)+UZIP.F.contSize(v.fdtree,v.dhst),_=i+UZIP.F.contSize(v.ltree,v.lhst)+UZIP.F.contSize(v.dtree,v.dhst);_+=14+3*p+UZIP.F.contSize(v.itree,v.ihst)+(2*v.ihst[16]+3*v.ihst[17]+7*v.ihst[18]);for(var B=0;B<286;B++)v.lhst[B]=0;for(B=0;B<30;B++)v.dhst[B]=0;for(B=0;B<19;B++)v.ihst[B]=0;var U=E<F&&E<_?0:F<_?1:2;if(b(f,l,e),b(f,l+1,U),l+=3,0==U){for(;0!=(7&l);)l++;l=UZIP.F._copyExact(o,a,s,f,l)}else{var C,I;if(1==U&&(C=v.fltree,I=v.fdtree),2==U){UZIP.F.makeCodes(v.ltree,u),UZIP.F.revCodes(v.ltree,u),UZIP.F.makeCodes(v.dtree,h),UZIP.F.revCodes(v.dtree,h),UZIP.F.makeCodes(v.itree,d),UZIP.F.revCodes(v.itree,d),C=v.ltree,I=v.dtree,y(f,l,A-257),y(f,l+=5,g-1),y(f,l+=5,p-4),l+=4;for(var Q=0;Q<p;Q++)y(f,l+3*Q,v.itree[1+(v.ordr[Q]<<1)]);l+=3*p,l=UZIP.F._codeTiny(m,v.itree,f,l),l=UZIP.F._codeTiny(w,v.itree,f,l)}for(var M=a,x=0;x<r;x+=2){for(var S=t[x],R=S>>>23,T=M+(8388607&S);M<T;)l=UZIP.F._writeLit(o[M++],C,f,l);if(0!=R){var O=t[x+1],P=O>>16,H=O>>8&255,L=255&O;y(f,l=UZIP.F._writeLit(257+H,C,f,l),R-v.of0[H]),l+=v.exb[H],b(f,l=UZIP.F._writeLit(L,I,f,l),P-v.df0[L]),l+=v.dxb[L],M+=R}}l=UZIP.F._writeLit(256,C,f,l)}return l},UZIP.F._copyExact=function(e,t,r,i,o){var a=o>>>3;return i[a]=r,i[a+1]=r>>>8,i[a+2]=255-i[a],i[a+3]=255-i[a+1],a+=4,i.set(new Uint8Array(e.buffer,t,r),a),o+(r+4<<3)},UZIP.F.getTrees=function(){for(var e=UZIP.F.U,t=UZIP.F._hufTree(e.lhst,e.ltree,15),r=UZIP.F._hufTree(e.dhst,e.dtree,15),i=[],o=UZIP.F._lenCodes(e.ltree,i),a=[],s=UZIP.F._lenCodes(e.dtree,a),f=0;f<i.length;f+=2)e.ihst[i[f]]++;for(f=0;f<a.length;f+=2)e.ihst[a[f]]++;for(var l=UZIP.F._hufTree(e.ihst,e.itree,7),c=19;c>4&&0==e.itree[1+(e.ordr[c-1]<<1)];)c--;return[t,r,l,o,s,c,i,a]},UZIP.F.getSecond=function(e){for(var t=[],r=0;r<e.length;r+=2)t.push(e[r+1]);return t},UZIP.F.nonZero=function(e){for(var t=\"\",r=0;r<e.length;r+=2)0!=e[r+1]&&(t+=(r>>1)+\",\");return t},UZIP.F.contSize=function(e,t){for(var r=0,i=0;i<t.length;i++)r+=t[i]*e[1+(i<<1)];return r},UZIP.F._codeTiny=function(e,t,r,i){for(var o=0;o<e.length;o+=2){var a=e[o],s=e[o+1];i=UZIP.F._writeLit(a,t,r,i);var f=16==a?2:17==a?3:7;a>15&&(UZIP.F._putsE(r,i,s,f),i+=f)}return i},UZIP.F._lenCodes=function(e,t){for(var r=e.length;2!=r&&0==e[r-1];)r-=2;for(var i=0;i<r;i+=2){var o=e[i+1],a=i+3<r?e[i+3]:-1,s=i+5<r?e[i+5]:-1,f=0==i?-1:e[i-1];if(0==o&&a==o&&s==o){for(var l=i+5;l+2<r&&e[l+2]==o;)l+=2;(c=Math.min(l+1-i>>>1,138))<11?t.push(17,c-3):t.push(18,c-11),i+=2*c-2}else if(o==f&&a==o&&s==o){for(l=i+5;l+2<r&&e[l+2]==o;)l+=2;var c=Math.min(l+1-i>>>1,6);t.push(16,c-3),i+=2*c-2}else t.push(o,0)}return r>>>1},UZIP.F._hufTree=function(e,t,r){var i=[],o=e.length,a=t.length,s=0;for(s=0;s<a;s+=2)t[s]=0,t[s+1]=0;for(s=0;s<o;s++)0!=e[s]&&i.push({lit:s,f:e[s]});var f=i.length,l=i.slice(0);if(0==f)return 0;if(1==f){var c=i[0].lit;l=0==c?1:0;return t[1+(c<<1)]=1,t[1+(l<<1)]=1,1}i.sort((function(e,t){return e.f-t.f}));var u=i[0],h=i[1],d=0,A=1,g=2;for(i[0]={lit:-1,f:u.f+h.f,l:u,r:h,d:0};A!=f-1;)u=d!=A&&(g==f||i[d].f<i[g].f)?i[d++]:i[g++],h=d!=A&&(g==f||i[d].f<i[g].f)?i[d++]:i[g++],i[A++]={lit:-1,f:u.f+h.f,l:u,r:h};var p=UZIP.F.setDepth(i[A-1],0);for(p>r&&(UZIP.F.restrictDepth(l,r,p),p=r),s=0;s<f;s++)t[1+(l[s].lit<<1)]=l[s].d;return p},UZIP.F.setDepth=function(e,t){return-1!=e.lit?(e.d=t,t):Math.max(UZIP.F.setDepth(e.l,t+1),UZIP.F.setDepth(e.r,t+1))},UZIP.F.restrictDepth=function(e,t,r){var i=0,o=1<<r-t,a=0;for(e.sort((function(e,t){return t.d==e.d?e.f-t.f:t.d-e.d})),i=0;i<e.length&&e[i].d>t;i++){var s=e[i].d;e[i].d=t,a+=o-(1<<r-s)}for(a>>>=r-t;a>0;){(s=e[i].d)<t?(e[i].d++,a-=1<<t-s-1):i++}for(;i>=0;i--)e[i].d==t&&a<0&&(e[i].d--,a++);0!=a&&console.log(\"debt left\")},UZIP.F._goodIndex=function(e,t){var r=0;return t[16|r]<=e&&(r|=16),t[8|r]<=e&&(r|=8),t[4|r]<=e&&(r|=4),t[2|r]<=e&&(r|=2),t[1|r]<=e&&(r|=1),r},UZIP.F._writeLit=function(e,t,r,i){return UZIP.F._putsF(r,i,t[e<<1]),i+t[1+(e<<1)]},UZIP.F.inflate=function(e,t){var r=Uint8Array;if(3==e[0]&&0==e[1])return t||new r(0);var i=UZIP.F,o=i._bitsF,a=i._bitsE,s=i._decodeTiny,f=i.makeCodes,l=i.codes2map,c=i._get17,u=i.U,h=null==t;h&&(t=new r(e.length>>>2<<3));for(var d,A,g=0,p=0,m=0,w=0,v=0,b=0,y=0,E=0,F=0;0==g;)if(g=o(e,F,1),p=o(e,F+1,2),F+=3,0!=p){if(h&&(t=UZIP.F._check(t,E+(1<<17))),1==p&&(d=u.flmap,A=u.fdmap,b=511,y=31),2==p){m=a(e,F,5)+257,w=a(e,F+5,5)+1,v=a(e,F+10,4)+4,F+=14;for(var _=0;_<38;_+=2)u.itree[_]=0,u.itree[_+1]=0;var B=1;for(_=0;_<v;_++){var U=a(e,F+3*_,3);u.itree[1+(u.ordr[_]<<1)]=U,U>B&&(B=U)}F+=3*v,f(u.itree,B),l(u.itree,B,u.imap),d=u.lmap,A=u.dmap,F=s(u.imap,(1<<B)-1,m+w,e,F,u.ttree);var C=i._copyOut(u.ttree,0,m,u.ltree);b=(1<<C)-1;var I=i._copyOut(u.ttree,m,w,u.dtree);y=(1<<I)-1,f(u.ltree,C),l(u.ltree,C,d),f(u.dtree,I),l(u.dtree,I,A)}for(;;){var Q=d[c(e,F)&b];F+=15&Q;var M=Q>>>4;if(M>>>8==0)t[E++]=M;else{if(256==M)break;var x=E+M-254;if(M>264){var S=u.ldef[M-257];x=E+(S>>>3)+a(e,F,7&S),F+=7&S}var R=A[c(e,F)&y];F+=15&R;var T=R>>>4,O=u.ddef[T],P=(O>>>4)+o(e,F,15&O);for(F+=15&O,h&&(t=UZIP.F._check(t,E+(1<<17)));E<x;)t[E]=t[E++-P],t[E]=t[E++-P],t[E]=t[E++-P],t[E]=t[E++-P];E=x}}}else{0!=(7&F)&&(F+=8-(7&F));var H=4+(F>>>3),L=e[H-4]|e[H-3]<<8;h&&(t=UZIP.F._check(t,E+L)),t.set(new r(e.buffer,e.byteOffset+H,L),E),F=H+L<<3,E+=L}return t.length==E?t:t.slice(0,E)},UZIP.F._check=function(e,t){var r=e.length;if(t<=r)return e;var i=new Uint8Array(Math.max(r<<1,t));return i.set(e,0),i},UZIP.F._decodeTiny=function(e,t,r,i,o,a){for(var s=UZIP.F._bitsE,f=UZIP.F._get17,l=0;l<r;){var c=e[f(i,o)&t];o+=15&c;var u=c>>>4;if(u<=15)a[l]=u,l++;else{var h=0,d=0;16==u?(d=3+s(i,o,2),o+=2,h=a[l-1]):17==u?(d=3+s(i,o,3),o+=3):18==u&&(d=11+s(i,o,7),o+=7);for(var A=l+d;l<A;)a[l]=h,l++}}return o},UZIP.F._copyOut=function(e,t,r,i){for(var o=0,a=0,s=i.length>>>1;a<r;){var f=e[a+t];i[a<<1]=0,i[1+(a<<1)]=f,f>o&&(o=f),a++}for(;a<s;)i[a<<1]=0,i[1+(a<<1)]=0,a++;return o},UZIP.F.makeCodes=function(e,t){for(var r,i,o,a,s=UZIP.F.U,f=e.length,l=s.bl_count,c=0;c<=t;c++)l[c]=0;for(c=1;c<f;c+=2)l[e[c]]++;var u=s.next_code;for(r=0,l[0]=0,i=1;i<=t;i++)r=r+l[i-1]<<1,u[i]=r;for(o=0;o<f;o+=2)0!=(a=e[o+1])&&(e[o]=u[a],u[a]++)},UZIP.F.codes2map=function(e,t,r){for(var i=e.length,o=UZIP.F.U.rev15,a=0;a<i;a+=2)if(0!=e[a+1])for(var s=a>>1,f=e[a+1],l=s<<4|f,c=t-f,u=e[a]<<c,h=u+(1<<c);u!=h;){r[o[u]>>>15-t]=l,u++}},UZIP.F.revCodes=function(e,t){for(var r=UZIP.F.U.rev15,i=15-t,o=0;o<e.length;o+=2){var a=e[o]<<t-e[o+1];e[o]=r[a]>>>i}},UZIP.F._putsE=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},UZIP.F._putsF=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},UZIP.F._bitsE=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<<r)-1},UZIP.F._bitsF=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<<r)-1},UZIP.F._get17=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},UZIP.F._get25=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},UZIP.F.U=(r=Uint16Array,i=Uint32Array,{next_code:new r(16),bl_count:new r(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new r(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new i(32),flmap:new r(512),fltree:[],fdmap:new r(32),fdtree:[],lmap:new r(32768),ltree:[],ttree:[],dmap:new r(32768),dtree:[],imap:new r(512),itree:[],rev15:new r(32768),lhst:new i(286),dhst:new i(30),ihst:new i(19),lits:new i(15e3),strt:new r(65536),prev:new r(32768)}),function(){for(var e=UZIP.F.U,t=0;t<32768;t++){var r=t;r=(4278255360&(r=(4042322160&(r=(3435973836&(r=(2863311530&r)>>>1|(1431655765&r)<<1))>>>2|(858993459&r)<<2))>>>4|(252645135&r)<<4))>>>8|(16711935&r)<<8,e.rev15[t]=(r>>>16|r<<16)>>>17}function pushV(e,t,r){for(;0!=t--;)e.push(0,r)}for(t=0;t<32;t++)e.ldef[t]=e.of0[t]<<3|e.exb[t],e.ddef[t]=e.df0[t]<<4|e.dxb[t];pushV(e.fltree,144,8),pushV(e.fltree,112,9),pushV(e.fltree,24,7),pushV(e.fltree,8,8),UZIP.F.makeCodes(e.fltree,9),UZIP.F.codes2map(e.fltree,9,e.flmap),UZIP.F.revCodes(e.fltree,9),pushV(e.fdtree,32,5),UZIP.F.makeCodes(e.fdtree,5),UZIP.F.codes2map(e.fdtree,5,e.fdmap),UZIP.F.revCodes(e.fdtree,5),pushV(e.itree,19,0),pushV(e.ltree,286,0),pushV(e.dtree,30,0),pushV(e.ttree,320,0)}()}();var UZIP=_mergeNamespaces({__proto__:null,default:e},[e]);const UPNG=function(){var e={nextZero(e,t){for(;0!=e[t];)t++;return t},readUshort:(e,t)=>e[t]<<8|e[t+1],writeUshort(e,t,r){e[t]=r>>8&255,e[t+1]=255&r},readUint:(e,t)=>16777216*e[t]+(e[t+1]<<16|e[t+2]<<8|e[t+3]),writeUint(e,t,r){e[t]=r>>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=255&r},readASCII(e,t,r){let i=\"\";for(let o=0;o<r;o++)i+=String.fromCharCode(e[t+o]);return i},writeASCII(e,t,r){for(let i=0;i<r.length;i++)e[t+i]=r.charCodeAt(i)},readBytes(e,t,r){const i=[];for(let o=0;o<r;o++)i.push(e[t+o]);return i},pad:e=>e.length<2?`0${e}`:e,readUTF8(t,r,i){let o,a=\"\";for(let o=0;o<i;o++)a+=`%${e.pad(t[r+o].toString(16))}`;try{o=decodeURIComponent(a)}catch(o){return e.readASCII(t,r,i)}return o}};function decodeImage(t,r,i,o){const a=r*i,s=_getBPP(o),f=Math.ceil(r*s/8),l=new Uint8Array(4*a),c=new Uint32Array(l.buffer),{ctype:u}=o,{depth:h}=o,d=e.readUshort;if(6==u){const e=a<<2;if(8==h)for(var A=0;A<e;A+=4)l[A]=t[A],l[A+1]=t[A+1],l[A+2]=t[A+2],l[A+3]=t[A+3];if(16==h)for(A=0;A<e;A++)l[A]=t[A<<1]}else if(2==u){const e=o.tabs.tRNS;if(null==e){if(8==h)for(A=0;A<a;A++){var g=3*A;c[A]=255<<24|t[g+2]<<16|t[g+1]<<8|t[g]}if(16==h)for(A=0;A<a;A++){g=6*A;c[A]=255<<24|t[g+4]<<16|t[g+2]<<8|t[g]}}else{var p=e[0];const r=e[1],i=e[2];if(8==h)for(A=0;A<a;A++){var m=A<<2;g=3*A;c[A]=255<<24|t[g+2]<<16|t[g+1]<<8|t[g],t[g]==p&&t[g+1]==r&&t[g+2]==i&&(l[m+3]=0)}if(16==h)for(A=0;A<a;A++){m=A<<2,g=6*A;c[A]=255<<24|t[g+4]<<16|t[g+2]<<8|t[g],d(t,g)==p&&d(t,g+2)==r&&d(t,g+4)==i&&(l[m+3]=0)}}}else if(3==u){const e=o.tabs.PLTE,s=o.tabs.tRNS,c=s?s.length:0;if(1==h)for(var w=0;w<i;w++){var v=w*f,b=w*r;for(A=0;A<r;A++){m=b+A<<2;var y=3*(E=t[v+(A>>3)]>>7-((7&A)<<0)&1);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}}if(2==h)for(w=0;w<i;w++)for(v=w*f,b=w*r,A=0;A<r;A++){m=b+A<<2,y=3*(E=t[v+(A>>2)]>>6-((3&A)<<1)&3);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}if(4==h)for(w=0;w<i;w++)for(v=w*f,b=w*r,A=0;A<r;A++){m=b+A<<2,y=3*(E=t[v+(A>>1)]>>4-((1&A)<<2)&15);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}if(8==h)for(A=0;A<a;A++){var E;m=A<<2,y=3*(E=t[A]);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}}else if(4==u){if(8==h)for(A=0;A<a;A++){m=A<<2;var F=t[_=A<<1];l[m]=F,l[m+1]=F,l[m+2]=F,l[m+3]=t[_+1]}if(16==h)for(A=0;A<a;A++){var _;m=A<<2,F=t[_=A<<2];l[m]=F,l[m+1]=F,l[m+2]=F,l[m+3]=t[_+2]}}else if(0==u)for(p=o.tabs.tRNS?o.tabs.tRNS:-1,w=0;w<i;w++){const e=w*f,i=w*r;if(1==h)for(var B=0;B<r;B++){var U=(F=255*(t[e+(B>>>3)]>>>7-(7&B)&1))==255*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(2==h)for(B=0;B<r;B++){U=(F=85*(t[e+(B>>>2)]>>>6-((3&B)<<1)&3))==85*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(4==h)for(B=0;B<r;B++){U=(F=17*(t[e+(B>>>1)]>>>4-((1&B)<<2)&15))==17*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(8==h)for(B=0;B<r;B++){U=(F=t[e+B])==p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(16==h)for(B=0;B<r;B++){F=t[e+(B<<1)],U=d(t,e+(B<<1))==p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}}return l}function _decompress(e,r,i,o){const a=_getBPP(e),s=Math.ceil(i*a/8),f=new Uint8Array((s+1+e.interlace)*o);return r=e.tabs.CgBI?t(r,f):_inflate(r,f),0==e.interlace?r=_filterZero(r,e,0,i,o):1==e.interlace&&(r=function _readInterlace(e,t){const r=t.width,i=t.height,o=_getBPP(t),a=o>>3,s=Math.ceil(r*o/8),f=new Uint8Array(i*s);let l=0;const c=[0,0,4,0,2,0,1],u=[0,4,0,2,0,1,0],h=[8,8,8,4,4,2,2],d=[8,8,4,4,2,2,1];let A=0;for(;A<7;){const p=h[A],m=d[A];let w=0,v=0,b=c[A];for(;b<i;)b+=p,v++;let y=u[A];for(;y<r;)y+=m,w++;const E=Math.ceil(w*o/8);_filterZero(e,t,l,w,v);let F=0,_=c[A];for(;_<i;){let t=u[A],i=l+F*E<<3;for(;t<r;){var g;if(1==o)g=(g=e[i>>3])>>7-(7&i)&1,f[_*s+(t>>3)]|=g<<7-((7&t)<<0);if(2==o)g=(g=e[i>>3])>>6-(7&i)&3,f[_*s+(t>>2)]|=g<<6-((3&t)<<1);if(4==o)g=(g=e[i>>3])>>4-(7&i)&15,f[_*s+(t>>1)]|=g<<4-((1&t)<<2);if(o>=8){const r=_*s+t*a;for(let t=0;t<a;t++)f[r+t]=e[(i>>3)+t]}i+=o,t+=m}F++,_+=p}w*v!=0&&(l+=v*(1+E)),A+=1}return f}(r,e)),r}function _inflate(e,r){return t(new Uint8Array(e.buffer,2,e.length-6),r)}var t=function(){const e={H:{}};return e.H.N=function(t,r){const i=Uint8Array;let o,a,s=0,f=0,l=0,c=0,u=0,h=0,d=0,A=0,g=0;if(3==t[0]&&0==t[1])return r||new i(0);const p=e.H,m=p.b,w=p.e,v=p.R,b=p.n,y=p.A,E=p.Z,F=p.m,_=null==r;for(_&&(r=new i(t.length>>>2<<5));0==s;)if(s=m(t,g,1),f=m(t,g+1,2),g+=3,0!=f){if(_&&(r=e.H.W(r,A+(1<<17))),1==f&&(o=F.J,a=F.h,h=511,d=31),2==f){l=w(t,g,5)+257,c=w(t,g+5,5)+1,u=w(t,g+10,4)+4,g+=14;let e=1;for(var B=0;B<38;B+=2)F.Q[B]=0,F.Q[B+1]=0;for(B=0;B<u;B++){const r=w(t,g+3*B,3);F.Q[1+(F.X[B]<<1)]=r,r>e&&(e=r)}g+=3*u,b(F.Q,e),y(F.Q,e,F.u),o=F.w,a=F.d,g=v(F.u,(1<<e)-1,l+c,t,g,F.v);const r=p.V(F.v,0,l,F.C);h=(1<<r)-1;const i=p.V(F.v,l,c,F.D);d=(1<<i)-1,b(F.C,r),y(F.C,r,o),b(F.D,i),y(F.D,i,a)}for(;;){const e=o[E(t,g)&h];g+=15&e;const i=e>>>4;if(i>>>8==0)r[A++]=i;else{if(256==i)break;{let e=A+i-254;if(i>264){const r=F.q[i-257];e=A+(r>>>3)+w(t,g,7&r),g+=7&r}const o=a[E(t,g)&d];g+=15&o;const s=o>>>4,f=F.c[s],l=(f>>>4)+m(t,g,15&f);for(g+=15&f;A<e;)r[A]=r[A++-l],r[A]=r[A++-l],r[A]=r[A++-l],r[A]=r[A++-l];A=e}}}}else{0!=(7&g)&&(g+=8-(7&g));const o=4+(g>>>3),a=t[o-4]|t[o-3]<<8;_&&(r=e.H.W(r,A+a)),r.set(new i(t.buffer,t.byteOffset+o,a),A),g=o+a<<3,A+=a}return r.length==A?r:r.slice(0,A)},e.H.W=function(e,t){const r=e.length;if(t<=r)return e;const i=new Uint8Array(r<<1);return i.set(e,0),i},e.H.R=function(t,r,i,o,a,s){const f=e.H.e,l=e.H.Z;let c=0;for(;c<i;){const e=t[l(o,a)&r];a+=15&e;const i=e>>>4;if(i<=15)s[c]=i,c++;else{let e=0,t=0;16==i?(t=3+f(o,a,2),a+=2,e=s[c-1]):17==i?(t=3+f(o,a,3),a+=3):18==i&&(t=11+f(o,a,7),a+=7);const r=c+t;for(;c<r;)s[c]=e,c++}}return a},e.H.V=function(e,t,r,i){let o=0,a=0;const s=i.length>>>1;for(;a<r;){const r=e[a+t];i[a<<1]=0,i[1+(a<<1)]=r,r>o&&(o=r),a++}for(;a<s;)i[a<<1]=0,i[1+(a<<1)]=0,a++;return o},e.H.n=function(t,r){const i=e.H.m,o=t.length;let a,s,f;let l;const c=i.j;for(var u=0;u<=r;u++)c[u]=0;for(u=1;u<o;u+=2)c[t[u]]++;const h=i.K;for(a=0,c[0]=0,s=1;s<=r;s++)a=a+c[s-1]<<1,h[s]=a;for(f=0;f<o;f+=2)l=t[f+1],0!=l&&(t[f]=h[l],h[l]++)},e.H.A=function(t,r,i){const o=t.length,a=e.H.m.r;for(let e=0;e<o;e+=2)if(0!=t[e+1]){const o=e>>1,s=t[e+1],f=o<<4|s,l=r-s;let c=t[e]<<l;const u=c+(1<<l);for(;c!=u;){i[a[c]>>>15-r]=f,c++}}},e.H.l=function(t,r){const i=e.H.m.r,o=15-r;for(let e=0;e<t.length;e+=2){const a=t[e]<<r-t[e+1];t[e]=i[a]>>>o}},e.H.M=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},e.H.I=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},e.H.e=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<<r)-1},e.H.b=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<<r)-1},e.H.Z=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},e.H.i=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},e.H.m=function(){const e=Uint16Array,t=Uint32Array;return{K:new e(16),j:new e(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new e(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new t(32),J:new e(512),_:[],h:new e(32),$:[],w:new e(32768),C:[],v:[],d:new e(32768),D:[],u:new e(512),Q:[],r:new e(32768),s:new t(286),Y:new t(30),a:new t(19),t:new t(15e3),k:new e(65536),g:new e(32768)}}(),function(){const t=e.H.m;for(var r=0;r<32768;r++){let e=r;e=(2863311530&e)>>>1|(1431655765&e)<<1,e=(3435973836&e)>>>2|(858993459&e)<<2,e=(4042322160&e)>>>4|(252645135&e)<<4,e=(4278255360&e)>>>8|(16711935&e)<<8,t.r[r]=(e>>>16|e<<16)>>>17}function n(e,t,r){for(;0!=t--;)e.push(0,r)}for(r=0;r<32;r++)t.q[r]=t.S[r]<<3|t.T[r],t.c[r]=t.p[r]<<4|t.z[r];n(t._,144,8),n(t._,112,9),n(t._,24,7),n(t._,8,8),e.H.n(t._,9),e.H.A(t._,9,t.J),e.H.l(t._,9),n(t.$,32,5),e.H.n(t.$,5),e.H.A(t.$,5,t.h),e.H.l(t.$,5),n(t.Q,19,0),n(t.C,286,0),n(t.D,30,0),n(t.v,320,0)}(),e.H.N}();function _getBPP(e){return[1,null,3,1,2,null,4][e.ctype]*e.depth}function _filterZero(e,t,r,i,o){let a=_getBPP(t);const s=Math.ceil(i*a/8);let f,l;a=Math.ceil(a/8);let c=e[r],u=0;if(c>1&&(e[r]=[0,0,1][c-2]),3==c)for(u=a;u<s;u++)e[u+1]=e[u+1]+(e[u+1-a]>>>1)&255;for(let t=0;t<o;t++)if(f=r+t*s,l=f+t+1,c=e[l-1],u=0,0==c)for(;u<s;u++)e[f+u]=e[l+u];else if(1==c){for(;u<a;u++)e[f+u]=e[l+u];for(;u<s;u++)e[f+u]=e[l+u]+e[f+u-a]}else if(2==c)for(;u<s;u++)e[f+u]=e[l+u]+e[f+u-s];else if(3==c){for(;u<a;u++)e[f+u]=e[l+u]+(e[f+u-s]>>>1);for(;u<s;u++)e[f+u]=e[l+u]+(e[f+u-s]+e[f+u-a]>>>1)}else{for(;u<a;u++)e[f+u]=e[l+u]+_paeth(0,e[f+u-s],0);for(;u<s;u++)e[f+u]=e[l+u]+_paeth(e[f+u-a],e[f+u-s],e[f+u-a-s])}return e}function _paeth(e,t,r){const i=e+t-r,o=i-e,a=i-t,s=i-r;return o*o<=a*a&&o*o<=s*s?e:a*a<=s*s?t:r}function _IHDR(t,r,i){i.width=e.readUint(t,r),r+=4,i.height=e.readUint(t,r),r+=4,i.depth=t[r],r++,i.ctype=t[r],r++,i.compress=t[r],r++,i.filter=t[r],r++,i.interlace=t[r],r++}function _copyTile(e,t,r,i,o,a,s,f,l){const c=Math.min(t,o),u=Math.min(r,a);let h=0,d=0;for(let r=0;r<u;r++)for(let a=0;a<c;a++)if(s>=0&&f>=0?(h=r*t+a<<2,d=(f+r)*o+s+a<<2):(h=(-f+r)*t-s+a<<2,d=r*o+a<<2),0==l)i[d]=e[h],i[d+1]=e[h+1],i[d+2]=e[h+2],i[d+3]=e[h+3];else if(1==l){var A=e[h+3]*(1/255),g=e[h]*A,p=e[h+1]*A,m=e[h+2]*A,w=i[d+3]*(1/255),v=i[d]*w,b=i[d+1]*w,y=i[d+2]*w;const t=1-A,r=A+w*t,o=0==r?0:1/r;i[d+3]=255*r,i[d+0]=(g+v*t)*o,i[d+1]=(p+b*t)*o,i[d+2]=(m+y*t)*o}else if(2==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];A==w&&g==v&&p==b&&m==y?(i[d]=0,i[d+1]=0,i[d+2]=0,i[d+3]=0):(i[d]=g,i[d+1]=p,i[d+2]=m,i[d+3]=A)}else if(3==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];if(A==w&&g==v&&p==b&&m==y)continue;if(A<220&&w>20)return!1}return!0}return{decode:function decode(r){const i=new Uint8Array(r);let o=8;const a=e,s=a.readUshort,f=a.readUint,l={tabs:{},frames:[]},c=new Uint8Array(i.length);let u,h=0,d=0;const A=[137,80,78,71,13,10,26,10];for(var g=0;g<8;g++)if(i[g]!=A[g])throw\"The input is not a PNG file!\";for(;o<i.length;){const e=a.readUint(i,o);o+=4;const r=a.readASCII(i,o,4);if(o+=4,\"IHDR\"==r)_IHDR(i,o,l);else if(\"iCCP\"==r){for(var p=o;0!=i[p];)p++;a.readASCII(i,o,p-o),i[p+1];const s=i.slice(p+2,o+e);let f=null;try{f=_inflate(s)}catch(e){f=t(s)}l.tabs[r]=f}else if(\"CgBI\"==r)l.tabs[r]=i.slice(o,o+4);else if(\"IDAT\"==r){for(g=0;g<e;g++)c[h+g]=i[o+g];h+=e}else if(\"acTL\"==r)l.tabs[r]={num_frames:f(i,o),num_plays:f(i,o+4)},u=new Uint8Array(i.length);else if(\"fcTL\"==r){if(0!=d)(E=l.frames[l.frames.length-1]).data=_decompress(l,u.slice(0,d),E.rect.width,E.rect.height),d=0;const e={x:f(i,o+12),y:f(i,o+16),width:f(i,o+4),height:f(i,o+8)};let t=s(i,o+22);t=s(i,o+20)/(0==t?100:t);const r={rect:e,delay:Math.round(1e3*t),dispose:i[o+24],blend:i[o+25]};l.frames.push(r)}else if(\"fdAT\"==r){for(g=0;g<e-4;g++)u[d+g]=i[o+g+4];d+=e-4}else if(\"pHYs\"==r)l.tabs[r]=[a.readUint(i,o),a.readUint(i,o+4),i[o+8]];else if(\"cHRM\"==r){l.tabs[r]=[];for(g=0;g<8;g++)l.tabs[r].push(a.readUint(i,o+4*g))}else if(\"tEXt\"==r||\"zTXt\"==r){null==l.tabs[r]&&(l.tabs[r]={});var m=a.nextZero(i,o),w=a.readASCII(i,o,m-o),v=o+e-m-1;if(\"tEXt\"==r)y=a.readASCII(i,m+1,v);else{var b=_inflate(i.slice(m+2,m+2+v));y=a.readUTF8(b,0,b.length)}l.tabs[r][w]=y}else if(\"iTXt\"==r){null==l.tabs[r]&&(l.tabs[r]={});m=0,p=o;m=a.nextZero(i,p);w=a.readASCII(i,p,m-p);const t=i[p=m+1];var y;i[p+1],p+=2,m=a.nextZero(i,p),a.readASCII(i,p,m-p),p=m+1,m=a.nextZero(i,p),a.readUTF8(i,p,m-p);v=e-((p=m+1)-o);if(0==t)y=a.readUTF8(i,p,v);else{b=_inflate(i.slice(p,p+v));y=a.readUTF8(b,0,b.length)}l.tabs[r][w]=y}else if(\"PLTE\"==r)l.tabs[r]=a.readBytes(i,o,e);else if(\"hIST\"==r){const e=l.tabs.PLTE.length/3;l.tabs[r]=[];for(g=0;g<e;g++)l.tabs[r].push(s(i,o+2*g))}else if(\"tRNS\"==r)3==l.ctype?l.tabs[r]=a.readBytes(i,o,e):0==l.ctype?l.tabs[r]=s(i,o):2==l.ctype&&(l.tabs[r]=[s(i,o),s(i,o+2),s(i,o+4)]);else if(\"gAMA\"==r)l.tabs[r]=a.readUint(i,o)/1e5;else if(\"sRGB\"==r)l.tabs[r]=i[o];else if(\"bKGD\"==r)0==l.ctype||4==l.ctype?l.tabs[r]=[s(i,o)]:2==l.ctype||6==l.ctype?l.tabs[r]=[s(i,o),s(i,o+2),s(i,o+4)]:3==l.ctype&&(l.tabs[r]=i[o]);else if(\"IEND\"==r)break;o+=e,a.readUint(i,o),o+=4}var E;return 0!=d&&((E=l.frames[l.frames.length-1]).data=_decompress(l,u.slice(0,d),E.rect.width,E.rect.height)),l.data=_decompress(l,c,l.width,l.height),delete l.compress,delete l.interlace,delete l.filter,l},toRGBA8:function toRGBA8(e){const t=e.width,r=e.height;if(null==e.tabs.acTL)return[decodeImage(e.data,t,r,e).buffer];const i=[];null==e.frames[0].data&&(e.frames[0].data=e.data);const o=t*r*4,a=new Uint8Array(o),s=new Uint8Array(o),f=new Uint8Array(o);for(let c=0;c<e.frames.length;c++){const u=e.frames[c],h=u.rect.x,d=u.rect.y,A=u.rect.width,g=u.rect.height,p=decodeImage(u.data,A,g,e);if(0!=c)for(var l=0;l<o;l++)f[l]=a[l];if(0==u.blend?_copyTile(p,A,g,a,t,r,h,d,0):1==u.blend&&_copyTile(p,A,g,a,t,r,h,d,1),i.push(a.buffer.slice(0)),0==u.dispose);else if(1==u.dispose)_copyTile(s,A,g,a,t,r,h,d,0);else if(2==u.dispose)for(l=0;l<o;l++)a[l]=f[l]}return i},_paeth:_paeth,_copyTile:_copyTile,_bin:e}}();!function(){const{_copyTile:e}=UPNG,{_bin:t}=UPNG,r=UPNG._paeth;var i={table:function(){const e=new Uint32Array(256);for(let t=0;t<256;t++){let r=t;for(let e=0;e<8;e++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update(e,t,r,o){for(let a=0;a<o;a++)e=i.table[255&(e^t[r+a])]^e>>>8;return e},crc:(e,t,r)=>4294967295^i.update(4294967295,e,t,r)};function addErr(e,t,r,i){t[r]+=e[0]*i>>4,t[r+1]+=e[1]*i>>4,t[r+2]+=e[2]*i>>4,t[r+3]+=e[3]*i>>4}function N(e){return Math.max(0,Math.min(255,e))}function D(e,t){const r=e[0]-t[0],i=e[1]-t[1],o=e[2]-t[2],a=e[3]-t[3];return r*r+i*i+o*o+a*a}function dither(e,t,r,i,o,a,s){null==s&&(s=1);const f=i.length,l=[];for(var c=0;c<f;c++){const e=i[c];l.push([e>>>0&255,e>>>8&255,e>>>16&255,e>>>24&255])}for(c=0;c<f;c++){let e=4294967295;for(var u=0,h=0;h<f;h++){var d=D(l[c],l[h]);h!=c&&d<e&&(e=d,u=h)}}const A=new Uint32Array(o.buffer),g=new Int16Array(t*r*4),p=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5];for(c=0;c<p.length;c++)p[c]=255*((p[c]+.5)/16-.5);for(let o=0;o<r;o++)for(let w=0;w<t;w++){var m;c=4*(o*t+w);if(2!=s)m=[N(e[c]+g[c]),N(e[c+1]+g[c+1]),N(e[c+2]+g[c+2]),N(e[c+3]+g[c+3])];else{d=p[4*(3&o)+(3&w)];m=[N(e[c]+d),N(e[c+1]+d),N(e[c+2]+d),N(e[c+3]+d)]}u=0;let v=16777215;for(h=0;h<f;h++){const e=D(m,l[h]);e<v&&(v=e,u=h)}const b=l[u],y=[m[0]-b[0],m[1]-b[1],m[2]-b[2],m[3]-b[3]];1==s&&(w!=t-1&&addErr(y,g,c+4,7),o!=r-1&&(0!=w&&addErr(y,g,c+4*t-4,3),addErr(y,g,c+4*t,5),w!=t-1&&addErr(y,g,c+4*t+4,1))),a[c>>2]=u,A[c>>2]=i[u]}}function _main(e,r,o,a,s){null==s&&(s={});const{crc:f}=i,l=t.writeUint,c=t.writeUshort,u=t.writeASCII;let h=8;const d=e.frames.length>1;let A,g=!1,p=33+(d?20:0);if(null!=s.sRGB&&(p+=13),null!=s.pHYs&&(p+=21),null!=s.iCCP&&(A=pako.deflate(s.iCCP),p+=21+A.length+4),3==e.ctype){for(var m=e.plte.length,w=0;w<m;w++)e.plte[w]>>>24!=255&&(g=!0);p+=8+3*m+4+(g?8+1*m+4:0)}for(var v=0;v<e.frames.length;v++){d&&(p+=38),p+=(F=e.frames[v]).cimg.length+12,0!=v&&(p+=4)}p+=12;const b=new Uint8Array(p),y=[137,80,78,71,13,10,26,10];for(w=0;w<8;w++)b[w]=y[w];if(l(b,h,13),h+=4,u(b,h,\"IHDR\"),h+=4,l(b,h,r),h+=4,l(b,h,o),h+=4,b[h]=e.depth,h++,b[h]=e.ctype,h++,b[h]=0,h++,b[h]=0,h++,b[h]=0,h++,l(b,h,f(b,h-17,17)),h+=4,null!=s.sRGB&&(l(b,h,1),h+=4,u(b,h,\"sRGB\"),h+=4,b[h]=s.sRGB,h++,l(b,h,f(b,h-5,5)),h+=4),null!=s.iCCP){const e=13+A.length;l(b,h,e),h+=4,u(b,h,\"iCCP\"),h+=4,u(b,h,\"ICC profile\"),h+=11,h+=2,b.set(A,h),h+=A.length,l(b,h,f(b,h-(e+4),e+4)),h+=4}if(null!=s.pHYs&&(l(b,h,9),h+=4,u(b,h,\"pHYs\"),h+=4,l(b,h,s.pHYs[0]),h+=4,l(b,h,s.pHYs[1]),h+=4,b[h]=s.pHYs[2],h++,l(b,h,f(b,h-13,13)),h+=4),d&&(l(b,h,8),h+=4,u(b,h,\"acTL\"),h+=4,l(b,h,e.frames.length),h+=4,l(b,h,null!=s.loop?s.loop:0),h+=4,l(b,h,f(b,h-12,12)),h+=4),3==e.ctype){l(b,h,3*(m=e.plte.length)),h+=4,u(b,h,\"PLTE\"),h+=4;for(w=0;w<m;w++){const t=3*w,r=e.plte[w],i=255&r,o=r>>>8&255,a=r>>>16&255;b[h+t+0]=i,b[h+t+1]=o,b[h+t+2]=a}if(h+=3*m,l(b,h,f(b,h-3*m-4,3*m+4)),h+=4,g){l(b,h,m),h+=4,u(b,h,\"tRNS\"),h+=4;for(w=0;w<m;w++)b[h+w]=e.plte[w]>>>24&255;h+=m,l(b,h,f(b,h-m-4,m+4)),h+=4}}let E=0;for(v=0;v<e.frames.length;v++){var F=e.frames[v];d&&(l(b,h,26),h+=4,u(b,h,\"fcTL\"),h+=4,l(b,h,E++),h+=4,l(b,h,F.rect.width),h+=4,l(b,h,F.rect.height),h+=4,l(b,h,F.rect.x),h+=4,l(b,h,F.rect.y),h+=4,c(b,h,a[v]),h+=2,c(b,h,1e3),h+=2,b[h]=F.dispose,h++,b[h]=F.blend,h++,l(b,h,f(b,h-30,30)),h+=4);const t=F.cimg;l(b,h,(m=t.length)+(0==v?0:4)),h+=4;const r=h;u(b,h,0==v?\"IDAT\":\"fdAT\"),h+=4,0!=v&&(l(b,h,E++),h+=4),b.set(t,h),h+=m,l(b,h,f(b,r,h-r)),h+=4}return l(b,h,0),h+=4,u(b,h,\"IEND\"),h+=4,l(b,h,f(b,h-4,4)),h+=4,b.buffer}function compressPNG(e,t,r){for(let i=0;i<e.frames.length;i++){const o=e.frames[i];o.rect.width;const a=o.rect.height,s=new Uint8Array(a*o.bpl+a);o.cimg=_filterZero(o.img,a,o.bpp,o.bpl,s,t,r)}}function compress(t,r,i,o,a){const s=a[0],f=a[1],l=a[2],c=a[3],u=a[4],h=a[5];let d=6,A=8,g=255;for(var p=0;p<t.length;p++){const e=new Uint8Array(t[p]);for(var m=e.length,w=0;w<m;w+=4)g&=e[w+3]}const v=255!=g,b=function framize(t,r,i,o,a,s){const f=[];for(var l=0;l<t.length;l++){const h=new Uint8Array(t[l]),A=new Uint32Array(h.buffer);var c;let g=0,p=0,m=r,w=i,v=o?1:0;if(0!=l){const b=s||o||1==l||0!=f[l-2].dispose?1:2;let y=0,E=1e9;for(let e=0;e<b;e++){var u=new Uint8Array(t[l-1-e]);const o=new Uint32Array(t[l-1-e]);let s=r,f=i,c=-1,h=-1;for(let e=0;e<i;e++)for(let t=0;t<r;t++){A[d=e*r+t]!=o[d]&&(t<s&&(s=t),t>c&&(c=t),e<f&&(f=e),e>h&&(h=e))}-1==c&&(s=f=c=h=0),a&&(1==(1&s)&&s--,1==(1&f)&&f--);const v=(c-s+1)*(h-f+1);v<E&&(E=v,y=e,g=s,p=f,m=c-s+1,w=h-f+1)}u=new Uint8Array(t[l-1-y]);1==y&&(f[l-1].dispose=2),c=new Uint8Array(m*w*4),e(u,r,i,c,m,w,-g,-p,0),v=e(h,r,i,c,m,w,-g,-p,3)?1:0,1==v?_prepareDiff(h,r,i,c,{x:g,y:p,width:m,height:w}):e(h,r,i,c,m,w,-g,-p,0)}else c=h.slice(0);f.push({rect:{x:g,y:p,width:m,height:w},img:c,blend:v,dispose:0})}if(o)for(l=0;l<f.length;l++){if(1==(A=f[l]).blend)continue;const e=A.rect,o=f[l-1].rect,s=Math.min(e.x,o.x),c=Math.min(e.y,o.y),u={x:s,y:c,width:Math.max(e.x+e.width,o.x+o.width)-s,height:Math.max(e.y+e.height,o.y+o.height)-c};f[l-1].dispose=1,l-1!=0&&_updateFrame(t,r,i,f,l-1,u,a),_updateFrame(t,r,i,f,l,u,a)}let h=0;if(1!=t.length)for(var d=0;d<f.length;d++){var A;h+=(A=f[d]).rect.width*A.rect.height}return f}(t,r,i,s,f,l),y={},E=[],F=[];if(0!=o){const e=[];for(w=0;w<b.length;w++)e.push(b[w].img.buffer);const t=function concatRGBA(e){let t=0;for(var r=0;r<e.length;r++)t+=e[r].byteLength;const i=new Uint8Array(t);let o=0;for(r=0;r<e.length;r++){const t=new Uint8Array(e[r]),a=t.length;for(let e=0;e<a;e+=4){let r=t[e],a=t[e+1],s=t[e+2];const f=t[e+3];0==f&&(r=a=s=0),i[o+e]=r,i[o+e+1]=a,i[o+e+2]=s,i[o+e+3]=f}o+=a}return i.buffer}(e),r=quantize(t,o);for(w=0;w<r.plte.length;w++)E.push(r.plte[w].est.rgba);let i=0;for(w=0;w<b.length;w++){const e=(B=b[w]).img.length;var _=new Uint8Array(r.inds.buffer,i>>2,e>>2);F.push(_);const t=new Uint8Array(r.abuf,i,e);h&&dither(B.img,B.rect.width,B.rect.height,E,t,_),B.img.set(t),i+=e}}else for(p=0;p<b.length;p++){var B=b[p];const e=new Uint32Array(B.img.buffer);var U=B.rect.width;m=e.length,_=new Uint8Array(m);F.push(_);for(w=0;w<m;w++){const t=e[w];if(0!=w&&t==e[w-1])_[w]=_[w-1];else if(w>U&&t==e[w-U])_[w]=_[w-U];else{let e=y[t];if(null==e&&(y[t]=e=E.length,E.push(t),E.length>=300))break;_[w]=e}}}const C=E.length;C<=256&&0==u&&(A=C<=2?1:C<=4?2:C<=16?4:8,A=Math.max(A,c));for(p=0;p<b.length;p++){(B=b[p]).rect.x,B.rect.y;U=B.rect.width;const e=B.rect.height;let t=B.img;new Uint32Array(t.buffer);let r=4*U,i=4;if(C<=256&&0==u){r=Math.ceil(A*U/8);var I=new Uint8Array(r*e);const o=F[p];for(let t=0;t<e;t++){w=t*r;const e=t*U;if(8==A)for(var Q=0;Q<U;Q++)I[w+Q]=o[e+Q];else if(4==A)for(Q=0;Q<U;Q++)I[w+(Q>>1)]|=o[e+Q]<<4-4*(1&Q);else if(2==A)for(Q=0;Q<U;Q++)I[w+(Q>>2)]|=o[e+Q]<<6-2*(3&Q);else if(1==A)for(Q=0;Q<U;Q++)I[w+(Q>>3)]|=o[e+Q]<<7-1*(7&Q)}t=I,d=3,i=1}else if(0==v&&1==b.length){I=new Uint8Array(U*e*3);const o=U*e;for(w=0;w<o;w++){const e=3*w,r=4*w;I[e]=t[r],I[e+1]=t[r+1],I[e+2]=t[r+2]}t=I,d=2,i=3,r=3*U}B.img=t,B.bpl=r,B.bpp=i}return{ctype:d,depth:A,plte:E,frames:b}}function _updateFrame(t,r,i,o,a,s,f){const l=Uint8Array,c=Uint32Array,u=new l(t[a-1]),h=new c(t[a-1]),d=a+1<t.length?new l(t[a+1]):null,A=new l(t[a]),g=new c(A.buffer);let p=r,m=i,w=-1,v=-1;for(let e=0;e<s.height;e++)for(let t=0;t<s.width;t++){const i=s.x+t,f=s.y+e,l=f*r+i,c=g[l];0==c||0==o[a-1].dispose&&h[l]==c&&(null==d||0!=d[4*l+3])||(i<p&&(p=i),i>w&&(w=i),f<m&&(m=f),f>v&&(v=f))}-1==w&&(p=m=w=v=0),f&&(1==(1&p)&&p--,1==(1&m)&&m--),s={x:p,y:m,width:w-p+1,height:v-m+1};const b=o[a];b.rect=s,b.blend=1,b.img=new Uint8Array(s.width*s.height*4),0==o[a-1].dispose?(e(u,r,i,b.img,s.width,s.height,-s.x,-s.y,0),_prepareDiff(A,r,i,b.img,s)):e(A,r,i,b.img,s.width,s.height,-s.x,-s.y,0)}function _prepareDiff(t,r,i,o,a){e(t,r,i,o,a.width,a.height,-a.x,-a.y,2)}function _filterZero(e,t,r,i,o,a,s){const f=[];let l,c=[0,1,2,3,4];-1!=a?c=[a]:(t*i>5e5||1==r)&&(c=[0]),s&&(l={level:0});const u=UZIP;for(var h=0;h<c.length;h++){for(let a=0;a<t;a++)_filterLine(o,e,a,i,r,c[h]);f.push(u.deflate(o,l))}let d,A=1e9;for(h=0;h<f.length;h++)f[h].length<A&&(d=h,A=f[h].length);return f[d]}function _filterLine(e,t,i,o,a,s){const f=i*o;let l=f+i;if(e[l]=s,l++,0==s)if(o<500)for(var c=0;c<o;c++)e[l+c]=t[f+c];else e.set(new Uint8Array(t.buffer,f,o),l);else if(1==s){for(c=0;c<a;c++)e[l+c]=t[f+c];for(c=a;c<o;c++)e[l+c]=t[f+c]-t[f+c-a]+256&255}else if(0==i){for(c=0;c<a;c++)e[l+c]=t[f+c];if(2==s)for(c=a;c<o;c++)e[l+c]=t[f+c];if(3==s)for(c=a;c<o;c++)e[l+c]=t[f+c]-(t[f+c-a]>>1)+256&255;if(4==s)for(c=a;c<o;c++)e[l+c]=t[f+c]-r(t[f+c-a],0,0)+256&255}else{if(2==s)for(c=0;c<o;c++)e[l+c]=t[f+c]+256-t[f+c-o]&255;if(3==s){for(c=0;c<a;c++)e[l+c]=t[f+c]+256-(t[f+c-o]>>1)&255;for(c=a;c<o;c++)e[l+c]=t[f+c]+256-(t[f+c-o]+t[f+c-a]>>1)&255}if(4==s){for(c=0;c<a;c++)e[l+c]=t[f+c]+256-r(0,t[f+c-o],0)&255;for(c=a;c<o;c++)e[l+c]=t[f+c]+256-r(t[f+c-a],t[f+c-o],t[f+c-a-o])&255}}}function quantize(e,t){const r=new Uint8Array(e),i=r.slice(0),o=new Uint32Array(i.buffer),a=getKDtree(i,t),s=a[0],f=a[1],l=r.length,c=new Uint8Array(l>>2);let u;if(r.length<2e7)for(var h=0;h<l;h+=4){u=getNearest(s,d=r[h]*(1/255),A=r[h+1]*(1/255),g=r[h+2]*(1/255),p=r[h+3]*(1/255)),c[h>>2]=u.ind,o[h>>2]=u.est.rgba}else for(h=0;h<l;h+=4){var d=r[h]*(1/255),A=r[h+1]*(1/255),g=r[h+2]*(1/255),p=r[h+3]*(1/255);for(u=s;u.left;)u=planeDst(u.est,d,A,g,p)<=0?u.left:u.right;c[h>>2]=u.ind,o[h>>2]=u.est.rgba}return{abuf:i.buffer,inds:c,plte:f}}function getKDtree(e,t,r){null==r&&(r=1e-4);const i=new Uint32Array(e.buffer),o={i0:0,i1:e.length,bst:null,est:null,tdst:0,left:null,right:null};o.bst=stats(e,o.i0,o.i1),o.est=estats(o.bst);const a=[o];for(;a.length<t;){let t=0,o=0;for(var s=0;s<a.length;s++)a[s].est.L>t&&(t=a[s].est.L,o=s);if(t<r)break;const f=a[o],l=splitPixels(e,i,f.i0,f.i1,f.est.e,f.est.eMq255);if(f.i0>=l||f.i1<=l){f.est.L=0;continue}const c={i0:f.i0,i1:l,bst:null,est:null,tdst:0,left:null,right:null};c.bst=stats(e,c.i0,c.i1),c.est=estats(c.bst);const u={i0:l,i1:f.i1,bst:null,est:null,tdst:0,left:null,right:null};u.bst={R:[],m:[],N:f.bst.N-c.bst.N};for(s=0;s<16;s++)u.bst.R[s]=f.bst.R[s]-c.bst.R[s];for(s=0;s<4;s++)u.bst.m[s]=f.bst.m[s]-c.bst.m[s];u.est=estats(u.bst),f.left=c,f.right=u,a[o]=c,a.push(u)}a.sort(((e,t)=>t.bst.N-e.bst.N));for(s=0;s<a.length;s++)a[s].ind=s;return[o,a]}function getNearest(e,t,r,i,o){if(null==e.left)return e.tdst=function dist(e,t,r,i,o){const a=t-e[0],s=r-e[1],f=i-e[2],l=o-e[3];return a*a+s*s+f*f+l*l}(e.est.q,t,r,i,o),e;const a=planeDst(e.est,t,r,i,o);let s=e.left,f=e.right;a>0&&(s=e.right,f=e.left);const l=getNearest(s,t,r,i,o);if(l.tdst<=a*a)return l;const c=getNearest(f,t,r,i,o);return c.tdst<l.tdst?c:l}function planeDst(e,t,r,i,o){const{e:a}=e;return a[0]*t+a[1]*r+a[2]*i+a[3]*o-e.eMq}function splitPixels(e,t,r,i,o,a){for(i-=4;r<i;){for(;vecDot(e,r,o)<=a;)r+=4;for(;vecDot(e,i,o)>a;)i-=4;if(r>=i)break;const s=t[r>>2];t[r>>2]=t[i>>2],t[i>>2]=s,r+=4,i-=4}for(;vecDot(e,r,o)>a;)r-=4;return r+4}function vecDot(e,t,r){return e[t]*r[0]+e[t+1]*r[1]+e[t+2]*r[2]+e[t+3]*r[3]}function stats(e,t,r){const i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o=[0,0,0,0],a=r-t>>2;for(let a=t;a<r;a+=4){const t=e[a]*(1/255),r=e[a+1]*(1/255),s=e[a+2]*(1/255),f=e[a+3]*(1/255);o[0]+=t,o[1]+=r,o[2]+=s,o[3]+=f,i[0]+=t*t,i[1]+=t*r,i[2]+=t*s,i[3]+=t*f,i[5]+=r*r,i[6]+=r*s,i[7]+=r*f,i[10]+=s*s,i[11]+=s*f,i[15]+=f*f}return i[4]=i[1],i[8]=i[2],i[9]=i[6],i[12]=i[3],i[13]=i[7],i[14]=i[11],{R:i,m:o,N:a}}function estats(e){const{R:t}=e,{m:r}=e,{N:i}=e,a=r[0],s=r[1],f=r[2],l=r[3],c=0==i?0:1/i,u=[t[0]-a*a*c,t[1]-a*s*c,t[2]-a*f*c,t[3]-a*l*c,t[4]-s*a*c,t[5]-s*s*c,t[6]-s*f*c,t[7]-s*l*c,t[8]-f*a*c,t[9]-f*s*c,t[10]-f*f*c,t[11]-f*l*c,t[12]-l*a*c,t[13]-l*s*c,t[14]-l*f*c,t[15]-l*l*c],h=u,d=o;let A=[Math.random(),Math.random(),Math.random(),Math.random()],g=0,p=0;if(0!=i)for(let e=0;e<16&&(A=d.multVec(h,A),p=Math.sqrt(d.dot(A,A)),A=d.sml(1/p,A),!(0!=e&&Math.abs(p-g)<1e-9));e++)g=p;const m=[a*c,s*c,f*c,l*c];return{Cov:u,q:m,e:A,L:g,eMq255:d.dot(d.sml(255,m),A),eMq:d.dot(A,m),rgba:(Math.round(255*m[3])<<24|Math.round(255*m[2])<<16|Math.round(255*m[1])<<8|Math.round(255*m[0])<<0)>>>0}}var o={multVec:(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],e[4]*t[0]+e[5]*t[1]+e[6]*t[2]+e[7]*t[3],e[8]*t[0]+e[9]*t[1]+e[10]*t[2]+e[11]*t[3],e[12]*t[0]+e[13]*t[1]+e[14]*t[2]+e[15]*t[3]],dot:(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],sml:(e,t)=>[e*t[0],e*t[1],e*t[2],e*t[3]]};UPNG.encode=function encode(e,t,r,i,o,a,s){null==i&&(i=0),null==s&&(s=!1);const f=compress(e,t,r,i,[!1,!1,!1,0,s,!1]);return compressPNG(f,-1),_main(f,t,r,o,a)},UPNG.encodeLL=function encodeLL(e,t,r,i,o,a,s,f){const l={ctype:0+(1==i?0:2)+(0==o?0:4),depth:a,frames:[]},c=(i+o)*a,u=c*t;for(let i=0;i<e.length;i++)l.frames.push({rect:{x:0,y:0,width:t,height:r},img:new Uint8Array(e[i]),blend:0,dispose:1,bpp:Math.ceil(c/8),bpl:Math.ceil(u/8)});return compressPNG(l,0,!0),_main(l,t,r,s,f)},UPNG.encode.compress=compress,UPNG.encode.dither=dither,UPNG.quantize=quantize,UPNG.quantize.getKDtree=getKDtree,UPNG.quantize.getNearest=getNearest}();const r={toArrayBuffer(e,t){const i=e.width,o=e.height,a=i<<2,s=e.getContext(\"2d\").getImageData(0,0,i,o),f=new Uint32Array(s.data.buffer),l=(32*i+31)/32<<2,c=l*o,u=122+c,h=new ArrayBuffer(u),d=new DataView(h),A=1<<20;let g,p,m,w,v=A,b=0,y=0,E=0;function set16(e){d.setUint16(y,e,!0),y+=2}function set32(e){d.setUint32(y,e,!0),y+=4}function seek(e){y+=e}set16(19778),set32(u),seek(4),set32(122),set32(108),set32(i),set32(-o>>>0),set16(1),set16(32),set32(3),set32(c),set32(2835),set32(2835),seek(8),set32(16711680),set32(65280),set32(255),set32(4278190080),set32(1466527264),function convert(){for(;b<o&&v>0;){for(w=122+b*l,g=0;g<a;)v--,p=f[E++],m=p>>>24,d.setUint32(w+g,p<<8|m),g+=4;b++}E<f.length?(v=A,setTimeout(convert,r._dly)):t(h)}()},toBlob(e,t){this.toArrayBuffer(e,(e=>{t(new Blob([e],{type:\"image/bmp\"}))}))},_dly:9};var i={CHROME:\"CHROME\",FIREFOX:\"FIREFOX\",DESKTOP_SAFARI:\"DESKTOP_SAFARI\",IE:\"IE\",IOS:\"IOS\",ETC:\"ETC\"},o={[i.CHROME]:16384,[i.FIREFOX]:11180,[i.DESKTOP_SAFARI]:16384,[i.IE]:8192,[i.IOS]:4096,[i.ETC]:8192};const a=\"undefined\"!=typeof window,s=\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,f=a&&window.cordova&&window.cordova.require&&window.cordova.require(\"cordova/modulemapper\"),CustomFile=(a||s)&&(f&&f.getOriginalSymbol(window,\"File\")||\"undefined\"!=typeof File&&File),CustomFileReader=(a||s)&&(f&&f.getOriginalSymbol(window,\"FileReader\")||\"undefined\"!=typeof FileReader&&FileReader);function getFilefromDataUrl(e,t,r=Date.now()){return new Promise((i=>{const o=e.split(\",\"),a=o[0].match(/:(.*?);/)[1],s=globalThis.atob(o[1]);let f=s.length;const l=new Uint8Array(f);for(;f--;)l[f]=s.charCodeAt(f);const c=new Blob([l],{type:a});c.name=t,c.lastModified=r,i(c)}))}function getDataUrlFromFile(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=()=>t(i.result),i.onerror=e=>r(e),i.readAsDataURL(e)}))}function loadImage(e){return new Promise(((t,r)=>{const i=new Image;i.onload=()=>t(i),i.onerror=e=>r(e),i.src=e}))}function getBrowserName(){if(void 0!==getBrowserName.cachedResult)return getBrowserName.cachedResult;let e=i.ETC;const{userAgent:t}=navigator;return/Chrom(e|ium)/i.test(t)?e=i.CHROME:/iP(ad|od|hone)/i.test(t)&&/WebKit/i.test(t)?e=i.IOS:/Safari/i.test(t)?e=i.DESKTOP_SAFARI:/Firefox/i.test(t)?e=i.FIREFOX:(/MSIE/i.test(t)||!0==!!document.documentMode)&&(e=i.IE),getBrowserName.cachedResult=e,getBrowserName.cachedResult}function approximateBelowMaximumCanvasSizeOfBrowser(e,t){const r=getBrowserName(),i=o[r];let a=e,s=t,f=a*s;const l=a>s?s/a:a/s;for(;f>i*i;){const e=(i+a)/2,t=(i+s)/2;e<t?(s=t,a=t*l):(s=e*l,a=e),f=a*s}return{width:a,height:s}}function getNewCanvasAndCtx(e,t){let r,i;try{if(r=new OffscreenCanvas(e,t),i=r.getContext(\"2d\"),null===i)throw new Error(\"getContext of OffscreenCanvas returns null\")}catch(e){r=document.createElement(\"canvas\"),i=r.getContext(\"2d\")}return r.width=e,r.height=t,[r,i]}function drawImageInCanvas(e,t){const{width:r,height:i}=approximateBelowMaximumCanvasSizeOfBrowser(e.width,e.height),[o,a]=getNewCanvasAndCtx(r,i);return t&&/jpe?g/.test(t)&&(a.fillStyle=\"white\",a.fillRect(0,0,o.width,o.height)),a.drawImage(e,0,0,o.width,o.height),o}function isIOS(){return void 0!==isIOS.cachedResult||(isIOS.cachedResult=[\"iPad Simulator\",\"iPhone Simulator\",\"iPod Simulator\",\"iPad\",\"iPhone\",\"iPod\"].includes(navigator.platform)||navigator.userAgent.includes(\"Mac\")&&\"undefined\"!=typeof document&&\"ontouchend\"in document),isIOS.cachedResult}function drawFileInCanvas(e,t={}){return new Promise((function(r,o){let a,s;var $Try_2_Post=function(){try{return s=drawImageInCanvas(a,t.fileType||e.type),r([a,s])}catch(e){return o(e)}},$Try_2_Catch=function(t){try{0;var $Try_3_Catch=function(e){try{throw e}catch(e){return o(e)}};try{let t;return getDataUrlFromFile(e).then((function(e){try{return t=e,loadImage(t).then((function(e){try{return a=e,function(){try{return $Try_2_Post()}catch(e){return o(e)}}()}catch(e){return $Try_3_Catch(e)}}),$Try_3_Catch)}catch(e){return $Try_3_Catch(e)}}),$Try_3_Catch)}catch(e){$Try_3_Catch(e)}}catch(e){return o(e)}};try{if(isIOS()||[i.DESKTOP_SAFARI,i.MOBILE_SAFARI].includes(getBrowserName()))throw new Error(\"Skip createImageBitmap on IOS and Safari\");return createImageBitmap(e).then((function(e){try{return a=e,$Try_2_Post()}catch(e){return $Try_2_Catch()}}),$Try_2_Catch)}catch(e){$Try_2_Catch()}}))}function canvasToFile(e,t,i,o,a=1){return new Promise((function(s,f){let l;if(\"image/png\"===t){let c,u,h;return c=e.getContext(\"2d\"),({data:u}=c.getImageData(0,0,e.width,e.height)),h=UPNG.encode([u.buffer],e.width,e.height,4096*a),l=new Blob([h],{type:t}),l.name=i,l.lastModified=o,$If_4.call(this)}{if(\"image/bmp\"===t)return new Promise((t=>r.toBlob(e,t))).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_5.call(this)}catch(e){return f(e)}}.bind(this),f);{if(\"function\"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return e.convertToBlob({type:t,quality:a}).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f);{let d;return d=e.toDataURL(t,a),getFilefromDataUrl(d,i,o).then(function(e){try{return l=e,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f)}function $If_6(){return $If_5.call(this)}}function $If_5(){return $If_4.call(this)}}function $If_4(){return s(l)}}))}function cleanupCanvasMemory(e){e.width=0,e.height=0}function isAutoOrientationInBrowser(){return new Promise((function(e,t){let r,i,o,a,s;return void 0!==isAutoOrientationInBrowser.cachedResult?e(isAutoOrientationInBrowser.cachedResult):(r=\"data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==\",getFilefromDataUrl(\"data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==\",\"test.jpg\",Date.now()).then((function(r){try{return i=r,drawFileInCanvas(i).then((function(r){try{return o=r[1],canvasToFile(o,i.type,i.name,i.lastModified).then((function(r){try{return a=r,cleanupCanvasMemory(o),drawFileInCanvas(a).then((function(r){try{return s=r[0],isAutoOrientationInBrowser.cachedResult=1===s.width&&2===s.height,e(isAutoOrientationInBrowser.cachedResult)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t))}))}function getExifOrientation(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=e=>{const r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return t(-2);const i=r.byteLength;let o=2;for(;o<i;){if(r.getUint16(o+2,!1)<=8)return t(-1);const e=r.getUint16(o,!1);if(o+=2,65505==e){if(1165519206!=r.getUint32(o+=2,!1))return t(-1);const e=18761==r.getUint16(o+=6,!1);o+=r.getUint32(o+4,e);const i=r.getUint16(o,e);o+=2;for(let a=0;a<i;a++)if(274==r.getUint16(o+12*a,e))return t(r.getUint16(o+12*a+8,e))}else{if(65280!=(65280&e))break;o+=r.getUint16(o,!1)}}return t(-1)},i.onerror=e=>r(e),i.readAsArrayBuffer(e)}))}function handleMaxWidthOrHeight(e,t){const{width:r}=e,{height:i}=e,{maxWidthOrHeight:o}=t;let a,s=e;return isFinite(o)&&(r>o||i>o)&&([s,a]=getNewCanvasAndCtx(r,i),r>i?(s.width=o,s.height=i/r*o):(s.width=r/i*o,s.height=o),a.drawImage(e,0,0,s.width,s.height),cleanupCanvasMemory(e)),s}function followExifOrientation(e,t){const{width:r}=e,{height:i}=e,[o,a]=getNewCanvasAndCtx(r,i);switch(t>4&&t<9?(o.width=i,o.height=r):(o.width=r,o.height=i),t){case 2:a.transform(-1,0,0,1,r,0);break;case 3:a.transform(-1,0,0,-1,r,i);break;case 4:a.transform(1,0,0,-1,0,i);break;case 5:a.transform(0,1,1,0,0,0);break;case 6:a.transform(0,1,-1,0,i,0);break;case 7:a.transform(0,-1,-1,0,i,r);break;case 8:a.transform(0,-1,1,0,0,r)}return a.drawImage(e,0,0,r,i),cleanupCanvasMemory(e),o}function compress(e,t,r=0){return new Promise((function(i,o){let a,s,f,l,c,u,h,d,A,g,p,m,w,v,b,y,E,F,_,B;function incProgress(e=5){if(t.signal&&t.signal.aborted)throw t.signal.reason;a+=e,t.onProgress(Math.min(a,100))}function setProgress(e){if(t.signal&&t.signal.aborted)throw t.signal.reason;a=Math.min(Math.max(e,a),100),t.onProgress(a)}return a=r,s=t.maxIteration||10,f=1024*t.maxSizeMB*1024,incProgress(),drawFileInCanvas(e,t).then(function(r){try{return[,l]=r,incProgress(),c=handleMaxWidthOrHeight(l,t),incProgress(),new Promise((function(r,i){var o;if(!(o=t.exifOrientation))return getExifOrientation(e).then(function(e){try{return o=e,$If_2.call(this)}catch(e){return i(e)}}.bind(this),i);function $If_2(){return r(o)}return $If_2.call(this)})).then(function(r){try{return u=r,incProgress(),isAutoOrientationInBrowser().then(function(r){try{return h=r?c:followExifOrientation(c,u),incProgress(),d=t.initialQuality||1,A=t.fileType||e.type,canvasToFile(h,A,e.name,e.lastModified,d).then(function(r){try{{if(g=r,incProgress(),p=g.size>f,m=g.size>e.size,!p&&!m)return setProgress(100),i(g);var a;function $Loop_3(){if(s--&&(b>f||b>w)){let t,r;return t=B?.95*_.width:_.width,r=B?.95*_.height:_.height,[E,F]=getNewCanvasAndCtx(t,r),F.drawImage(_,0,0,t,r),d*=\"image/png\"===A?.85:.95,canvasToFile(E,A,e.name,e.lastModified,d).then((function(e){try{return y=e,cleanupCanvasMemory(_),_=E,b=y.size,setProgress(Math.min(99,Math.floor((v-b)/(v-f)*100))),$Loop_3}catch(e){return o(e)}}),o)}return[1]}return w=e.size,v=g.size,b=v,_=h,B=!t.alwaysKeepResolution&&p,(a=function(e){for(;e;){if(e.then)return void e.then(a,o);try{if(e.pop){if(e.length)return e.pop()?$Loop_3_exit.call(this):e;e=$Loop_3}else e=e.call(this)}catch(e){return o(e)}}}.bind(this))($Loop_3);function $Loop_3_exit(){return cleanupCanvasMemory(_),cleanupCanvasMemory(E),cleanupCanvasMemory(c),cleanupCanvasMemory(h),cleanupCanvasMemory(l),setProgress(100),i(y)}}}catch(u){return o(u)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}))}const l=\"\\nlet scriptImported = false\\nself.addEventListener('message', async (e) => {\\n const { file, id, imageCompressionLibUrl, options } = e.data\\n options.onProgress = (progress) => self.postMessage({ progress, id })\\n try {\\n if (!scriptImported) {\\n // console.log('[worker] importScripts', imageCompressionLibUrl)\\n self.importScripts(imageCompressionLibUrl)\\n scriptImported = true\\n }\\n // console.log('[worker] self', self)\\n const compressedFile = await imageCompression(file, options)\\n self.postMessage({ file: compressedFile, id })\\n } catch (e) {\\n // console.error('[worker] error', e)\\n self.postMessage({ error: e.message + '\\\\n' + e.stack, id })\\n }\\n})\\n\";let c;function compressOnWebWorker(e,t){return new Promise(((r,i)=>{c||(c=function createWorkerScriptURL(e){const t=[];return\"function\"==typeof e?t.push(`(${e})()`):t.push(e),URL.createObjectURL(new Blob(t))}(l));const o=new Worker(c);o.addEventListener(\"message\",(function handler(e){if(t.signal&&t.signal.aborted)o.terminate();else if(void 0===e.data.progress){if(e.data.error)return i(new Error(e.data.error)),void o.terminate();r(e.data.file),o.terminate()}else t.onProgress(e.data.progress)})),o.addEventListener(\"error\",i),t.signal&&t.signal.addEventListener(\"abort\",(()=>{i(t.signal.reason),o.terminate()})),o.postMessage({file:e,imageCompressionLibUrl:t.libURL,options:{...t,onProgress:void 0,signal:void 0}})}))}function imageCompression(e,t){return new Promise((function(r,i){let o,a,s,f,l,c;if(o={...t},s=0,({onProgress:f}=o),o.maxSizeMB=o.maxSizeMB||Number.POSITIVE_INFINITY,l=\"boolean\"!=typeof o.useWebWorker||o.useWebWorker,delete o.useWebWorker,o.onProgress=e=>{s=e,\"function\"==typeof f&&f(s)},!(e instanceof Blob||e instanceof CustomFile))return i(new Error(\"The file given is not an instance of Blob or File\"));if(!/^image/.test(e.type))return i(new Error(\"The file given is not an image\"));if(c=\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!l||\"function\"!=typeof Worker||c)return compress(e,o).then(function(e){try{return a=e,$If_4.call(this)}catch(e){return i(e)}}.bind(this),i);var u=function(){try{return $If_4.call(this)}catch(e){return i(e)}}.bind(this),$Try_1_Catch=function(t){try{return compress(e,o).then((function(e){try{return a=e,u()}catch(e){return i(e)}}),i)}catch(e){return i(e)}};try{return o.libURL=o.libURL||\"https://cdn.jsdelivr.net/npm/[email protected]/dist/browser-image-compression.js\",compressOnWebWorker(e,o).then((function(e){try{return a=e,u()}catch(e){return $Try_1_Catch()}}),$Try_1_Catch)}catch(e){$Try_1_Catch()}function $If_4(){try{a.name=e.name,a.lastModified=e.lastModified}catch(e){}try{o.preserveExif&&\"image/jpeg\"===e.type&&(!o.fileType||o.fileType&&o.fileType===e.type)&&(a=copyExifWithoutOrientation(e,a))}catch(e){}return r(a)}}))}imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation,imageCompression.cleanupCanvasMemory=cleanupCanvasMemory,imageCompression.isAutoOrientationInBrowser=isAutoOrientationInBrowser,imageCompression.approximateBelowMaximumCanvasSizeOfBrowser=approximateBelowMaximumCanvasSizeOfBrowser,imageCompression.copyExifWithoutOrientation=copyExifWithoutOrientation,imageCompression.getBrowserName=getBrowserName,imageCompression.version=\"2.0.2\";\n//# sourceMappingURL=browser-image-compression.mjs.map\n\n\n//# sourceURL=webpack:///./node_modules/browser-image-compression/dist/browser-image-compression.mjs?"); 90 91 /***/ }), 92 93 /***/ "./node_modules/wasm-feature-detect/dist/esm/index.js": 94 /*!************************************************************!*\ 95 !*** ./node_modules/wasm-feature-detect/dist/esm/index.js ***! 96 \************************************************************/ 97 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 98 99 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"bigInt\": () => (/* binding */ bigInt),\n/* harmony export */ \"bulkMemory\": () => (/* binding */ bulkMemory),\n/* harmony export */ \"exceptions\": () => (/* binding */ exceptions),\n/* harmony export */ \"extendedConst\": () => (/* binding */ extendedConst),\n/* harmony export */ \"gc\": () => (/* binding */ gc),\n/* harmony export */ \"memory64\": () => (/* binding */ memory64),\n/* harmony export */ \"multiValue\": () => (/* binding */ multiValue),\n/* harmony export */ \"mutableGlobals\": () => (/* binding */ mutableGlobals),\n/* harmony export */ \"referenceTypes\": () => (/* binding */ referenceTypes),\n/* harmony export */ \"relaxedSimd\": () => (/* binding */ relaxedSimd),\n/* harmony export */ \"saturatedFloatToInt\": () => (/* binding */ saturatedFloatToInt),\n/* harmony export */ \"signExtensions\": () => (/* binding */ signExtensions),\n/* harmony export */ \"simd\": () => (/* binding */ simd),\n/* harmony export */ \"streamingCompilation\": () => (/* binding */ streamingCompilation),\n/* harmony export */ \"tailCall\": () => (/* binding */ tailCall),\n/* harmony export */ \"threads\": () => (/* binding */ threads)\n/* harmony export */ });\nconst bigInt=()=>(async e=>{try{return(await WebAssembly.instantiate(e)).instance.exports.b(BigInt(0))===BigInt(0)}catch(e){return!1}})(new Uint8Array([0,97,115,109,1,0,0,0,1,6,1,96,1,126,1,126,3,2,1,0,7,5,1,1,98,0,0,10,6,1,4,0,32,0,11])),bulkMemory=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,3,1,0,1,10,14,1,12,0,65,0,65,0,65,0,252,10,0,0,11])),exceptions=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,6,64,25,11,11])),extendedConst=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,5,3,1,0,1,11,9,1,0,65,1,65,2,106,11,0])),gc=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,10,2,95,1,125,0,96,0,1,107,0,3,2,1,1,10,12,1,10,0,67,0,0,0,0,251,7,0,11])),memory64=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,5,3,1,4,1])),multiValue=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,6,1,96,0,2,127,127,3,2,1,0,10,8,1,6,0,65,0,65,0,11])),mutableGlobals=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,2,8,1,1,97,1,98,3,127,1,6,6,1,127,1,65,0,11,7,5,1,1,97,3,1])),referenceTypes=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,7,1,5,0,208,112,26,11])),relaxedSimd=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,15,1,13,0,65,1,253,15,65,2,253,15,253,128,2,11])),saturatedFloatToInt=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,12,1,10,0,67,0,0,0,0,252,0,26,11])),signExtensions=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,65,0,192,26,11])),simd=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11])),streamingCompilation=()=>(async()=>\"compileStreaming\"in WebAssembly)(),tailCall=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,6,1,4,0,18,0,11])),threads=()=>(async e=>{try{return\"undefined\"!=typeof MessageChannel&&(new MessageChannel).port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(e)}catch(e){return!1}})(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]));\n\n\n//# sourceURL=webpack:///./node_modules/wasm-feature-detect/dist/esm/index.js?"); 50 100 51 101 /***/ }) … … 93 143 /******/ })(); 94 144 /******/ 145 /******/ /* webpack/runtime/ensure chunk */ 146 /******/ (() => { 147 /******/ __webpack_require__.f = {}; 148 /******/ // This file contains only the entry chunk. 149 /******/ // The chunk loading function for additional chunks 150 /******/ __webpack_require__.e = (chunkId) => { 151 /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { 152 /******/ __webpack_require__.f[key](chunkId, promises); 153 /******/ return promises; 154 /******/ }, [])); 155 /******/ }; 156 /******/ })(); 157 /******/ 95 158 /******/ /* webpack/runtime/get javascript chunk filename */ 96 159 /******/ (() => { … … 117 180 /******/ (() => { 118 181 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 182 /******/ })(); 183 /******/ 184 /******/ /* webpack/runtime/load script */ 185 /******/ (() => { 186 /******/ var inProgress = {}; 187 /******/ // data-webpack is not used as build has no uniqueName 188 /******/ // loadScript function to load a script via script tag 189 /******/ __webpack_require__.l = (url, done, key, chunkId) => { 190 /******/ if(inProgress[url]) { inProgress[url].push(done); return; } 191 /******/ var script, needAttach; 192 /******/ if(key !== undefined) { 193 /******/ var scripts = document.getElementsByTagName("script"); 194 /******/ for(var i = 0; i < scripts.length; i++) { 195 /******/ var s = scripts[i]; 196 /******/ if(s.getAttribute("src") == url) { script = s; break; } 197 /******/ } 198 /******/ } 199 /******/ if(!script) { 200 /******/ needAttach = true; 201 /******/ script = document.createElement('script'); 202 /******/ 203 /******/ script.charset = 'utf-8'; 204 /******/ script.timeout = 120; 205 /******/ if (__webpack_require__.nc) { 206 /******/ script.setAttribute("nonce", __webpack_require__.nc); 207 /******/ } 208 /******/ 209 /******/ script.src = url; 210 /******/ } 211 /******/ inProgress[url] = [done]; 212 /******/ var onScriptComplete = (prev, event) => { 213 /******/ // avoid mem leaks in IE. 214 /******/ script.onerror = script.onload = null; 215 /******/ clearTimeout(timeout); 216 /******/ var doneFns = inProgress[url]; 217 /******/ delete inProgress[url]; 218 /******/ script.parentNode && script.parentNode.removeChild(script); 219 /******/ doneFns && doneFns.forEach((fn) => (fn(event))); 220 /******/ if(prev) return prev(event); 221 /******/ } 222 /******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); 223 /******/ script.onerror = onScriptComplete.bind(null, script.onerror); 224 /******/ script.onload = onScriptComplete.bind(null, script.onload); 225 /******/ needAttach && document.head.appendChild(script); 226 /******/ }; 119 227 /******/ })(); 120 228 /******/ … … 161 269 /******/ }; 162 270 /******/ 163 /******/ // no chunk on demand loading 271 /******/ __webpack_require__.f.j = (chunkId, promises) => { 272 /******/ // JSONP chunk loading for javascript 273 /******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined; 274 /******/ if(installedChunkData !== 0) { // 0 means "already installed". 275 /******/ 276 /******/ // a Promise means "currently loading". 277 /******/ if(installedChunkData) { 278 /******/ promises.push(installedChunkData[2]); 279 /******/ } else { 280 /******/ if(true) { // all chunks have JS 281 /******/ // setup Promise in chunk cache 282 /******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject])); 283 /******/ promises.push(installedChunkData[2] = promise); 284 /******/ 285 /******/ // start chunk loading 286 /******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId); 287 /******/ // create error before stack unwound to get useful stacktrace later 288 /******/ var error = new Error(); 289 /******/ var loadingEnded = (event) => { 290 /******/ if(__webpack_require__.o(installedChunks, chunkId)) { 291 /******/ installedChunkData = installedChunks[chunkId]; 292 /******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined; 293 /******/ if(installedChunkData) { 294 /******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); 295 /******/ var realSrc = event && event.target && event.target.src; 296 /******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'; 297 /******/ error.name = 'ChunkLoadError'; 298 /******/ error.type = errorType; 299 /******/ error.request = realSrc; 300 /******/ installedChunkData[1](error); 301 /******/ } 302 /******/ } 303 /******/ }; 304 /******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId); 305 /******/ } else installedChunks[chunkId] = 0; 306 /******/ } 307 /******/ } 308 /******/ }; 164 309 /******/ 165 310 /******/ // no prefetching … … 173 318 /******/ // no on chunks loaded 174 319 /******/ 175 /******/ // no jsonp function 320 /******/ // install a JSONP callback for chunk loading 321 /******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { 322 /******/ var [chunkIds, moreModules, runtime] = data; 323 /******/ // add "moreModules" to the modules object, 324 /******/ // then flag all "chunkIds" as loaded and fire callback 325 /******/ var moduleId, chunkId, i = 0; 326 /******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { 327 /******/ for(moduleId in moreModules) { 328 /******/ if(__webpack_require__.o(moreModules, moduleId)) { 329 /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; 330 /******/ } 331 /******/ } 332 /******/ if(runtime) var result = runtime(__webpack_require__); 333 /******/ } 334 /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); 335 /******/ for(;i < chunkIds.length; i++) { 336 /******/ chunkId = chunkIds[i]; 337 /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { 338 /******/ installedChunks[chunkId][0](); 339 /******/ } 340 /******/ installedChunks[chunkId] = 0; 341 /******/ } 342 /******/ 343 /******/ } 344 /******/ 345 /******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || []; 346 /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); 347 /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); 176 348 /******/ })(); 177 349 /******/ -
squeeze/trunk/assets/js/assets_js_worker_js.bundle.js
r3311866 r3345284 17 17 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 18 18 19 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _jsquash_avif__WEBPACK_IMPORTED_MODULE_ 1__ = __webpack_require__(/*! @jsquash/avif */ \"./node_modules/@jsquash/avif/decode.js\");\n/* harmony import */ var _jsquash_avif__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @jsquash/avif */ \"./node_modules/@jsquash/avif/encode.js\");\n/* harmony import */ var _jsquash_webp__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @jsquash/webp */ \"./node_modules/@jsquash/webp/decode.js\");\n/* harmony import */ var _jsquash_webp__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @jsquash/webp */ \"./node_modules/@jsquash/webp/encode.js\");\n/* harmony import */ var _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @jsquash/jpeg */ \"./node_modules/@jsquash/jpeg/decode.js\");\n/* harmony import */ var _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @jsquash/jpeg */ \"./node_modules/@jsquash/jpeg/encode.js\");\n/* harmony import */ var _jsquash_png__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @jsquash/png */ \"./node_modules/@jsquash/png/decode.js\");\n/* harmony import */ var _jsquash_png__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @jsquash/png */ \"./node_modules/@jsquash/png/encode.js\");\n/* harmony import */ var _jsquash_resize__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @jsquash/resize */ \"./node_modules/@jsquash/resize/index.js\");\n/* harmony import */ var browser_image_compression__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! browser-image-compression */ \"./node_modules/browser-image-compression/dist/browser-image-compression.mjs\");\n// Description: Web Worker for image compression\r\n\r\n\r\n\r\n\r\n\r\n//import optimise from '@jsquash/oxipng/optimise';\r\n\r\n\r\n\r\n\"use strict\";\r\n\r\nlet options; // plugin options\r\n\r\n/**\r\n * Decode image buffer and return image data\r\n * @param {string} sourceType - avif, jpeg, png, webp\r\n * @param {object} fileBuffer - The ArrayBuffer object is used to represent a generic raw binary data buffer.\r\n * @returns {object | Error} - Image data object or throws an Error\r\n */\r\nconst decode = async (sourceType, fileBuffer) => {\r\n switch (sourceType) {\r\n case 'avif':\r\n return await _jsquash_avif__WEBPACK_IMPORTED_MODULE_1__[\"default\"](fileBuffer);\r\n case 'jpeg':\r\n return await _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_2__[\"default\"](fileBuffer);\r\n case 'png':\r\n return await _jsquash_png__WEBPACK_IMPORTED_MODULE_3__[\"default\"](fileBuffer);\r\n case 'webp':\r\n return await _jsquash_webp__WEBPACK_IMPORTED_MODULE_4__[\"default\"](fileBuffer);\r\n default:\r\n throw new Error(`Unknown source type: ${sourceType}`);\r\n }\r\n}\r\n\r\n/**\r\n * \r\n * @param {string} outputType - avif, jpeg, png, webp \r\n * @param {object} imageData - Image data object after decoding\r\n * @returns {ArrayBuffer | false} - Compressed image buffer or false if error\r\n */\r\nconst encode = async (outputType, imageData) => {\r\n try {\r\n switch (outputType) {\r\n case 'avif':\r\n const avifOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('avif')) {\r\n const keyName = key.replace('avif_', '')\r\n avifOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_avif__WEBPACK_IMPORTED_MODULE_5__[\"default\"](imageData, avifOptions);\r\n case 'jpeg':\r\n const jpegOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('jpeg')) {\r\n const keyName = key.replace('jpeg_', '')\r\n jpegOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_6__[\"default\"](imageData, jpegOptions);\r\n case 'png':\r\n const pngOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('png')) {\r\n const keyName = key.replace('png_', '')\r\n pngOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_png__WEBPACK_IMPORTED_MODULE_7__[\"default\"](imageData, pngOptions);\r\n case 'webp':\r\n const webpOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('webp')) {\r\n const keyName = key.replace('webp_', '')\r\n webpOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_webp__WEBPACK_IMPORTED_MODULE_8__[\"default\"](imageData, webpOptions);\r\n default:\r\n throw new Error(`Unknown output type: ${outputType}`);\r\n }\r\n } catch (error) {\r\n //console.error(error)\r\n throw new Error(`Error encoding image: ${error.message}`)\r\n }\r\n\r\n}\r\n\r\n/**\r\n * Convert image buffer from one format to another\r\n * @param {string} sourceType - avif, jpeg, png, webp\r\n * @param {string} outputType - avif, jpeg, png, webp\r\n * @param {object} fileBuffer - The ArrayBuffer object is used to represent a generic raw binary data buffer.\r\n * @returns {Promise} - Compressed image buffer or false if error\r\n */\r\nconst convert = async (sourceType, outputType, fileBuffer, resizeOptions) => {\r\n try {\r\n if (outputType === 'png') { // TBD: https://github.com/jamsinclair/jSquash/tree/main/packages/oxipng#activate-multithreading\r\n\r\n //fileBuffer = await optimise(fileBuffer, pngOptions);\r\n\r\n \r\n return fileBuffer;\r\n\r\n }\r\n\r\n const imageData = await decode(sourceType, fileBuffer);\r\n\r\n \r\n return encode(outputType, imageData);\r\n } catch (error) {\r\n console.error('Error during image processing:', error);\r\n throw new Error('Failed to process image, check the console for more information.');\r\n }\r\n}\r\n\r\n/**\r\n * Convert Blob to base64 encoded image string\r\n * @param {object} blob - The Blob object represents a blob, which is a file-like object of immutable, raw data.\r\n * @returns {Promise<string>} - Base64 encoded image string\r\n */\r\nconst blobToBase64 = (blob) => {\r\n return new Promise((resolve, _) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => resolve(reader.result);\r\n reader.readAsDataURL(blob);\r\n });\r\n}\r\n\r\nconst showOutput = async (imageBuffer, outputType) => {\r\n if (!imageBuffer) {\r\n return false;\r\n }\r\n const imageBlob = new Blob([imageBuffer], { type: `image/${outputType}` });\r\n const base64String = await blobToBase64(imageBlob);\r\n\r\n return base64String;\r\n}\r\n\r\nconst fetchImageBuffer = async (url, name, mime, outputType) => {\r\n const response = await fetch(url);\r\n if (!response.ok) {\r\n return false;\r\n }\r\n\r\n const blob = await response.blob();\r\n\r\n if (outputType === 'png') {\r\n // For PNG, we need to return blob\r\n return blob;\r\n }\r\n\r\n const metadata = {\r\n type: mime\r\n }\r\n\r\n const imageObj = new File([blob], name, metadata);\r\n const fileBuffer = await imageObj.arrayBuffer();\r\n\r\n return fileBuffer;\r\n}\r\n\r\n/**\r\n * Compresses a JPEG image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.url - The URL of the image.\r\n * @param {string} params.name - The name of the image file.\r\n * @param {string} params.sourceType - The source type of the image.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {string} params.mime - The MIME type of the image.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressJPEG = async ({ fileBuffer, name, sourceType, outputType, mime, resizeOptions }) => {\r\n const imageBuffer = await convert(sourceType, outputType, fileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n\r\n return base64;\r\n}\r\n\r\n/**\r\n * Compresses a PNG image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.url - The URL of the image.\r\n * @param {Object} params.options - The options for PNG compression.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressPNG = async ({ imageFile, outputType, resizeOptions }) => {\r\n const pngOptions = {};\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('png')) {\r\n const keyName = key.replace('png_', '');\r\n pngOptions[keyName] = value;\r\n }\r\n }\r\n /*\r\n const fileBuffer = await fetch(url).then(res => res.arrayBuffer());\r\n const imageBuffer = await convert(outputType, outputType, fileBuffer, resizeOptions, pngOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n\r\n return base64;\r\n //*/\r\n const browserImageCompressionOptions = {\r\n //maxSizeMB: 0.5,\r\n maxWidthOrHeight: Number.POSITIVE_INFINITY,\r\n initialQuality: pngOptions?.quality,\r\n useWebWorker: false,\r\n }\r\n //const imageFile = await fetch(url).then(res => res.blob());\r\n try {\r\n const compressedFile = await (0,browser_image_compression__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(imageFile, browserImageCompressionOptions);\r\n const fileBuffer = await compressedFile.arrayBuffer();\r\n const imageBuffer = await convert(outputType, outputType, fileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n //const base64 = await blobToBase64(compressedFile);\r\n return base64;\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n}\r\n\r\n/**\r\n * Compresses a WEBP image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.url - The URL of the image.\r\n * @param {string} params.name - The name of the image file.\r\n * @param {string} params.sourceType - The source type of the image.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {string} params.mime - The MIME type of the image.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressWEBP = async ({ fileBuffer, name, sourceType, outputType, mime, resizeOptions }) => {\r\n\r\n const imageBuffer = await convert(sourceType, outputType, fileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n\r\n return base64;\r\n}\r\n\r\n/**\r\n * Compresses an AVIF image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.url - The URL of the image.\r\n * @param {string} params.name - The name of the image file.\r\n * @param {string} params.sourceType - The source type of the image.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {string} params.mime - The MIME type of the image.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressAVIF = async ({ fileBuffer, name, sourceType, outputType, mime, resizeOptions }) => {\r\n\r\n const imageBuffer = await convert(sourceType, outputType, fileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n\r\n return base64;\r\n}\r\n\r\n\r\n\r\nconst compressAndAssign = async (compressFunction, { url, name, sourceType, outputType, mime, isPreview, file }) => {\r\n\r\n let fileBuffer;\r\n\r\n if (url) {\r\n fileBuffer = await fetchImageBuffer(url, name, mime, outputType);\r\n } else if (file) {\r\n // If file is provided, use it directly\r\n const fileObj = new File([file], name, { type: mime });\r\n fileBuffer = await fileObj.arrayBuffer();\r\n }\r\n\r\n if (!fileBuffer || fileBuffer.byteLength === 0) {\r\n throw new Error(`Fetched image from ${url} is empty.`);\r\n }\r\n\r\n const resizeOptions = {};\r\n let base64;\r\n\r\n if (compressFunction === compressPNG) {\r\n base64 = await compressFunction({ imageFile: fileBuffer, outputType, resizeOptions });\r\n } else {\r\n base64 = await compressFunction({ fileBuffer, name, sourceType, outputType, mime, resizeOptions });\r\n }\r\n\r\n return base64;\r\n}\r\n\r\nconst compressAndAssignThumbs = async (compressFunction, { name, sourceType, outputType, mime, sizes, isAllSizes = false }, skipFull = false) => {\r\n const compressThumbs = options.compress_thumbs;\r\n const base64Sizes = {}\r\n\r\n if (!sizes) {\r\n return base64Sizes;\r\n }\r\n\r\n for (const [key, value] of Object.entries(sizes)) {\r\n if (!(key in compressThumbs) && !isAllSizes) {\r\n continue;\r\n }\r\n\r\n if (skipFull && key === 'full') { // skip full size if no scaled image\r\n continue;\r\n }\r\n\r\n const sizeURL = value.url;\r\n const sizeWidth = value.width;\r\n const sizeHeight = value.height;\r\n const sizeName = `${name}-${sizeWidth}x${sizeHeight}`;\r\n let sizeBase64;\r\n let fileBuffer;\r\n\r\n if (sizeURL) {\r\n fileBuffer = await fetchImageBuffer(sizeURL, name, mime, outputType);\r\n }\r\n\r\n if (!fileBuffer || fileBuffer.byteLength === 0) {\r\n console.warn(`Fetched image from ${sizeURL} is empty.`)\r\n continue;\r\n }\r\n\r\n if (compressFunction === compressPNG) {\r\n sizeBase64 = await compressFunction({ imageFile: fileBuffer, outputType });\r\n } else {\r\n sizeBase64 = await compressFunction({ fileBuffer: fileBuffer, name: sizeName, sourceType, outputType, mime });\r\n }\r\n\r\n Object.assign(base64Sizes, { [key]: { 'url': sizeURL, 'base64': sizeBase64 } });\r\n }\r\n\r\n return base64Sizes;\r\n}\r\n\r\nonmessage = async function (e) {\r\n //console.log('Worker: Message received from main script', e.data, );\r\n const { format, url, name, sourceType, outputType, mime, sizes, skipFull, isPreview, file } = e.data;\r\n options = e.data.options;\r\n //console.log(options.max_width, options.max_height, 'max_width max_height');\r\n\r\n try {\r\n let base64, base64Sizes, base64Webp, base64SizesWebp;\r\n\r\n switch (format) {\r\n case 'avif':\r\n base64 = await compressAndAssign(compressAVIF, { url, name, sourceType, outputType, mime, isPreview, file });\r\n base64Sizes = await compressAndAssignThumbs(compressAVIF, { name, sourceType, outputType, mime, sizes }, skipFull);\r\n break;\r\n case 'jpeg':\r\n base64 = await compressAndAssign(compressJPEG, { url, name, sourceType, outputType, mime, isPreview, file });\r\n base64Sizes = await compressAndAssignThumbs(compressJPEG, { name, sourceType, outputType, mime, sizes }, skipFull);\r\n \r\n if (options.auto_webp) {\r\n base64Webp = await compressAndAssign(compressWEBP, { url, name, sourceType, outputType: 'webp', mime, isPreview, file });\r\n base64SizesWebp = await compressAndAssignThumbs(compressWEBP, { name, sourceType, outputType: 'webp', mime, sizes, isAllSizes: true }, skipFull);\r\n }\r\n\r\n break;\r\n case 'png':\r\n base64 = await compressAndAssign(compressPNG, { url, name, sourceType, outputType, mime, isPreview, file });\r\n base64Sizes = await compressAndAssignThumbs(compressPNG, { name, sourceType, outputType, mime, sizes }, skipFull);\r\n \r\n if (options.auto_webp) {\r\n base64Webp = await compressAndAssign(compressWEBP, { url, name, sourceType, outputType: 'webp', mime, isPreview, file });\r\n base64SizesWebp = await compressAndAssignThumbs(compressWEBP, { name, sourceType, outputType: 'webp', mime, sizes, isAllSizes: true }, skipFull);\r\n }\r\n \r\n break;\r\n case 'webp':\r\n base64 = await compressAndAssign(compressWEBP, { url, name, sourceType, outputType, mime, isPreview, file });\r\n base64Sizes = await compressAndAssignThumbs(compressWEBP, { name, sourceType, outputType, mime, sizes }, skipFull);\r\n break;\r\n }\r\n\r\n postMessage({\r\n 'base64': base64,\r\n 'base64Sizes': base64Sizes,\r\n 'base64Webp': base64Webp,\r\n 'base64SizesWebp': base64SizesWebp\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n postMessage({\r\n 'error': error\r\n });\r\n }\r\n}\n\n//# sourceURL=webpack:///./assets/js/worker.js?");19 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _jsquash_avif__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @jsquash/avif */ \"./node_modules/@jsquash/avif/decode.js\");\n/* harmony import */ var _jsquash_avif__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @jsquash/avif */ \"./node_modules/@jsquash/avif/encode.js\");\n/* harmony import */ var _jsquash_webp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @jsquash/webp */ \"./node_modules/@jsquash/webp/decode.js\");\n/* harmony import */ var _jsquash_webp__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @jsquash/webp */ \"./node_modules/@jsquash/webp/encode.js\");\n/* harmony import */ var _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @jsquash/jpeg */ \"./node_modules/@jsquash/jpeg/decode.js\");\n/* harmony import */ var _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @jsquash/jpeg */ \"./node_modules/@jsquash/jpeg/encode.js\");\n/* harmony import */ var _jsquash_png__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @jsquash/png */ \"./node_modules/@jsquash/png/decode.js\");\n/* harmony import */ var _jsquash_png__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @jsquash/png */ \"./node_modules/@jsquash/png/encode.js\");\n/* harmony import */ var _jsquash_resize__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @jsquash/resize */ \"./node_modules/@jsquash/resize/index.js\");\n// Description: Web Worker for image compression\r\n\r\n\r\n\r\n\r\n\r\n//import optimise from '@jsquash/oxipng/optimise';\r\n\r\n\r\n\"use strict\";\r\n\r\nlet options; // plugin options\r\n\r\n// RPC stands for Remote Procedure Call.\r\n// It’s a fancy name for \"calling a function that runs somewhere else, as if it was local\".\r\n\r\n//This is a MessagePort object used to communicate with the main thread.\r\n//It’s initially null and must be assigned from the outside when the main thread sends it to this worker via postMessage(..., [port]).\r\nlet rpcPort = null; // will be set when main thread transfers a MessagePort\r\n\r\n//Just a sequential number to ensure that every request has a unique ID, even if multiple requests happen at the same timestamp.\r\nlet rpcCounter = 1;\r\n\r\n// makes unique ID for each RPC call\r\n// example: 1633036800000-abc123-1\r\nfunction makeId() {\r\n return `${Date.now()}-${Math.random().toString(36).slice(2)}-${rpcCounter++}`;\r\n}\r\n\r\n/**\r\n * Call main thread to run imageCompression(...) there.\r\n * imageCompression function cannot be called directly from the worker. - causing error on mobile\r\n * - fileOrArrayBuffer: Blob or ArrayBuffer\r\n * - mime: e.g. 'image/png' or 'image/jpeg'\r\n * - options: options to pass to imageCompression\r\n * Returns: Promise<ArrayBuffer> (compressed image as ArrayBuffer)\r\n */\r\nfunction compressOnMainThread(fileOrArrayBuffer, mime = 'image/png', options = {}) {\r\n\r\n //If rpcPort hasn’t been set yet, reject the Promise immediately.\r\n //This prevents trying to send messages when there’s no communication channel.\r\n if (!rpcPort) {\r\n return Promise.reject(new Error('No RPC port available to main thread. Ensure main thread transferred a MessagePort.'));\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const id = makeId();\r\n\r\n // Listen for messages from the main thread\r\n function onMsg(ev) {\r\n const d = ev.data;\r\n if (!d || d.id !== id) return; // ignores unrelated messages by checking d.id.\r\n rpcPort.removeEventListener('message', onMsg); // Removes the event listener (avoids memory leaks).\r\n if (d.ok) resolve(d.arrayBuffer); // Resolves with the compressed image data if d.ok is true.\r\n else reject(d.error || new Error('Compression failed on main thread')); // Rejects if there was an error.\r\n }\r\n\r\n rpcPort.addEventListener('message', onMsg);\r\n\r\n // In some cases (like MessageChannel in a worker), you must call .start() to begin receiving messages.\r\n // In others, it’s automatic — hence the try/catch.\r\n try { rpcPort.start(); } catch (e) { /* start may be no-op */ }\r\n\r\n // Transfer ArrayBuffer if present for zero-copy\r\n if (fileOrArrayBuffer instanceof ArrayBuffer) {\r\n // It’s transferable, meaning ownership moves to the main thread without copying.\r\n // Faster and memory-efficient.\r\n rpcPort.postMessage({ id, action: 'imageCompression', fileOrArrayBuffer, mime, options }, [fileOrArrayBuffer]);\r\n } else {\r\n // Blob cannot be transferred, post it as-is (main thread will accept)\r\n rpcPort.postMessage({ id, action: 'imageCompression', fileOrArrayBuffer, mime, options });\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Decode image buffer and return image data\r\n * @param {string} sourceType - avif, jpeg, png, webp\r\n * @param {object} fileBuffer - The ArrayBuffer object is used to represent a generic raw binary data buffer.\r\n * @returns {object | Error} - Image data object or throws an Error\r\n */\r\nconst decode = async (sourceType, fileBuffer) => {\r\n switch (sourceType) {\r\n case 'avif':\r\n return await _jsquash_avif__WEBPACK_IMPORTED_MODULE_0__[\"default\"](fileBuffer);\r\n case 'jpeg':\r\n return await _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_1__[\"default\"](fileBuffer);\r\n case 'png':\r\n return await _jsquash_png__WEBPACK_IMPORTED_MODULE_2__[\"default\"](fileBuffer);\r\n case 'webp':\r\n return await _jsquash_webp__WEBPACK_IMPORTED_MODULE_3__[\"default\"](fileBuffer);\r\n default:\r\n throw new Error(`Unknown source type: ${sourceType}`);\r\n }\r\n}\r\n\r\n/**\r\n * \r\n * @param {string} outputType - avif, jpeg, png, webp \r\n * @param {object} imageData - Image data object after decoding\r\n * @returns {ArrayBuffer | false} - Compressed image buffer or false if error\r\n */\r\nconst encode = async (outputType, imageData) => {\r\n try {\r\n switch (outputType) {\r\n case 'avif':\r\n const avifOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('avif')) {\r\n const keyName = key.replace('avif_', '')\r\n avifOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_avif__WEBPACK_IMPORTED_MODULE_4__[\"default\"](imageData, avifOptions);\r\n case 'jpeg':\r\n const jpegOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('jpeg')) {\r\n const keyName = key.replace('jpeg_', '')\r\n jpegOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_jpeg__WEBPACK_IMPORTED_MODULE_5__[\"default\"](imageData, jpegOptions);\r\n case 'png':\r\n const pngOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('png')) {\r\n const keyName = key.replace('png_', '')\r\n pngOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_png__WEBPACK_IMPORTED_MODULE_6__[\"default\"](imageData, pngOptions);\r\n case 'webp':\r\n const webpOptions = {}\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('webp')) {\r\n const keyName = key.replace('webp_', '')\r\n webpOptions[keyName] = value\r\n }\r\n }\r\n return await _jsquash_webp__WEBPACK_IMPORTED_MODULE_7__[\"default\"](imageData, webpOptions);\r\n default:\r\n throw new Error(`Unknown output type: ${outputType}`);\r\n }\r\n } catch (error) {\r\n //console.error(error)\r\n throw new Error(`Error encoding image: ${error.message}`)\r\n }\r\n\r\n}\r\n\r\n/**\r\n * Convert image buffer from one format to another\r\n * @param {string} sourceType - avif, jpeg, png, webp\r\n * @param {string} outputType - avif, jpeg, png, webp\r\n * @param {object} fileBuffer - The ArrayBuffer object is used to represent a generic raw binary data buffer.\r\n * @returns {Promise} - Compressed image buffer or false if error\r\n */\r\nconst convert = async (sourceType, outputType, fileBuffer, resizeOptions) => {\r\n try {\r\n //console.log(`Converting from ${sourceType} to ${outputType}`);\r\n if (outputType === 'png') {\r\n\r\n \r\n return fileBuffer;\r\n\r\n }\r\n\r\n //*\r\n if (sourceType === 'jpeg') {\r\n fileBuffer = await compressOnMainThread(\r\n fileBuffer,\r\n 'image/jpeg',\r\n {useWebWorker: true}\r\n );\r\n }\r\n //*/\r\n\r\n const imageData = await decode(sourceType, fileBuffer);\r\n\r\n \r\n return encode(outputType, imageData);\r\n } catch (error) {\r\n console.error('Error during image processing:', error);\r\n throw new Error('Failed to process image, check the console for more information. ' + error);\r\n }\r\n}\r\n\r\n/**\r\n * Convert Blob to base64 encoded image string\r\n * @param {object} blob - The Blob object represents a blob, which is a file-like object of immutable, raw data.\r\n * @returns {Promise<string>} - Base64 encoded image string\r\n */\r\nconst blobToBase64 = (blob) => {\r\n return new Promise((resolve, _) => {\r\n const reader = new FileReader();\r\n reader.onloadend = () => resolve(reader.result);\r\n reader.readAsDataURL(blob);\r\n });\r\n}\r\n\r\nconst showOutput = async (imageBuffer, outputType) => {\r\n if (!imageBuffer) {\r\n return false;\r\n }\r\n const imageBlob = new Blob([imageBuffer], { type: `image/${outputType}` });\r\n const base64String = await blobToBase64(imageBlob);\r\n\r\n return base64String;\r\n}\r\n\r\nconst fetchImageBuffer = async (url, name, mime, outputType) => {\r\n const response = await fetch(url);\r\n if (!response.ok) {\r\n return false;\r\n }\r\n\r\n const blob = await response.blob();\r\n\r\n if (outputType === 'png') {\r\n // For PNG, we need to return blob\r\n return blob;\r\n }\r\n\r\n const metadata = {\r\n type: mime\r\n }\r\n\r\n const imageObj = new File([blob], name, metadata);\r\n const fileBuffer = await imageObj.arrayBuffer();\r\n\r\n return fileBuffer;\r\n}\r\n\r\n/**\r\n * Compresses a JPEG image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.sourceType - The source type of the image.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressJPEG = async ({ fileBuffer, sourceType, outputType, resizeOptions }) => {\r\n const imageBuffer = await convert(sourceType, outputType, fileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n\r\n return base64;\r\n}\r\n\r\n/**\r\n * Compresses a PNG image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressPNG = async ({ fileBuffer, outputType, resizeOptions }) => {\r\n const pngOptions = {};\r\n for (const [key, value] of Object.entries(options)) {\r\n if (key.includes('png')) {\r\n const keyName = key.replace('png_', '');\r\n pngOptions[keyName] = value;\r\n }\r\n }\r\n \r\n const browserImageCompressionOptions = {\r\n maxSizeMB: Number.POSITIVE_INFINITY,\r\n maxWidthOrHeight: Number.POSITIVE_INFINITY,\r\n initialQuality: pngOptions?.quality,\r\n useWebWorker: true,\r\n }\r\n\r\n //if (fileBuffer instanceof ArrayBuffer) { // for thumbnails\r\n //fileBuffer = new Blob([fileBuffer], { type: 'image/png' });\r\n //}\r\n\r\n try {\r\n // Use main thread to run imageCompression to avoid \"Image\" missing in worker on iOS\r\n const compressedFileBuffer = await compressOnMainThread(\r\n fileBuffer,\r\n 'image/png',\r\n browserImageCompressionOptions\r\n );\r\n\r\n const imageBuffer = await convert('png', outputType, compressedFileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n return base64;\r\n } catch (error) {\r\n console.error(error);\r\n throw new Error('Failed to process PNG, check the console for more information.');\r\n }\r\n}\r\n\r\n/**\r\n * Compresses a WEBP image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.sourceType - The source type of the image.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressWEBP = async ({ fileBuffer, sourceType, outputType, resizeOptions }) => {\r\n\r\n const imageBuffer = await convert(sourceType, outputType, fileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n\r\n return base64;\r\n}\r\n\r\n/**\r\n * Compresses an AVIF image.\r\n * @param {Object} params - The parameters for compression.\r\n * @param {string} params.sourceType - The source type of the image.\r\n * @param {string} params.outputType - The desired output type.\r\n * @param {Object} params.resizeOptions - The options for resizing the image.\r\n * @returns {Promise<string>} - The base64 encoded compressed image.\r\n */\r\nconst compressAVIF = async ({ fileBuffer, sourceType, outputType, resizeOptions }) => {\r\n\r\n const imageBuffer = await convert(sourceType, outputType, fileBuffer, resizeOptions);\r\n const base64 = await showOutput(imageBuffer, outputType);\r\n\r\n return base64;\r\n}\r\n\r\n\r\n\r\n// get proportional dimensions for thumbnail\r\n// based on original image dimensions and thumbnail size name\r\nconst getThumbnailDimensions = (thumbnailDimensions, originalImageDimensions) => {\r\n const { width: originalWidth, height: originalHeight } = originalImageDimensions;\r\n const aspectRatioHeight = originalHeight / originalWidth;\r\n const aspectRatioWidth = originalWidth / originalHeight;\r\n let sizeWidth, sizeHeight;\r\n\r\n thumbnailDimensions.width = thumbnailDimensions.width === 0 ? 9999 : thumbnailDimensions.width;\r\n thumbnailDimensions.height = thumbnailDimensions.height === 0 ? 9999 : thumbnailDimensions.height;\r\n \r\n if (originalWidth > originalHeight) {\r\n sizeWidth = thumbnailDimensions.width;\r\n sizeHeight = Math.round((originalHeight / originalWidth) * sizeWidth);\r\n }\r\n else {\r\n sizeHeight = thumbnailDimensions.height;\r\n sizeWidth = Math.round((originalWidth / originalHeight) * sizeHeight);\r\n }\r\n\r\n // Ensure both dimensions are within the max values\r\n if (sizeWidth > thumbnailDimensions.width) {\r\n sizeWidth = thumbnailDimensions.width;\r\n sizeHeight = thumbnailDimensions.width * aspectRatioHeight;\r\n }\r\n\r\n if (sizeHeight > thumbnailDimensions.height) {\r\n sizeHeight = thumbnailDimensions.height;\r\n sizeWidth = thumbnailDimensions.height / aspectRatioWidth;\r\n }\r\n return { width: sizeWidth, height: sizeHeight };\r\n}\r\n\r\nconst getImageDimensions = async (file) => {\r\n let blob;\r\n if (file instanceof Blob) {\r\n blob = file;\r\n } else if (file instanceof ArrayBuffer) {\r\n blob = new Blob([file]);\r\n } else {\r\n throw new Error('Unsupported file type for getImageDimensions');\r\n }\r\n const bitmap = await createImageBitmap(blob);\r\n return { width: bitmap.width, height: bitmap.height };\r\n}\r\n\r\nconst compressAndAssign = async (compressFunction, { url, name, sourceType, outputType, mime, isPreview, file }) => {\r\n\r\n //console.log('Compressing image:', name, sourceType, outputType);\r\n\r\n if (!url && !file) {\r\n return '';\r\n }\r\n\r\n let fileBuffer;\r\n\r\n if (url) {\r\n fileBuffer = await fetchImageBuffer(url, name, mime, outputType);\r\n } else if (file) {\r\n // If file is provided, use it directly\r\n fileBuffer = await file.arrayBuffer();\r\n }\r\n\r\n if (!fileBuffer || fileBuffer.byteLength === 0) {\r\n throw new Error(`Fetched image from ${url} is empty.`);\r\n }\r\n\r\n const resizeOptions = {};\r\n let base64;\r\n\r\n if (compressFunction === compressPNG) {\r\n base64 = await compressFunction({ fileBuffer, outputType, resizeOptions });\r\n } else {\r\n base64 = await compressFunction({ fileBuffer, sourceType, outputType, resizeOptions, file });\r\n }\r\n\r\n return base64;\r\n}\r\n\r\nconst compressAndAssignThumbs = async (compressFunction, { name, sourceType, outputType, mime, sizes, isAllSizes = false, file }, skipFull = false) => {\r\n const compressThumbs = options.compress_thumbs;\r\n const base64Sizes = {}\r\n let imageDimensions;\r\n\r\n if (!sizes) {\r\n return base64Sizes;\r\n }\r\n\r\n if (file) {\r\n imageDimensions = await getImageDimensions(file);\r\n }\r\n\r\n for (const [key, value] of Object.entries(sizes)) {\r\n if (!(key in compressThumbs) && !isAllSizes) {\r\n continue;\r\n }\r\n\r\n if (skipFull && key === 'full') { // skip full size if no scaled image\r\n continue;\r\n }\r\n\r\n //console.log('Processing size:', key, value);\r\n\r\n const sizeURL = value.url;\r\n const sizeWidth = value.width;\r\n const sizeHeight = value.height;\r\n const sizeCrop = value.crop || false;\r\n let sizeBase64;\r\n let fileBuffer;\r\n //const resizeOptions = {};\r\n const resizeOptions = {};\r\n\r\n if (resizeOptions?.needResize) {\r\n continue;\r\n }\r\n\r\n if (sizeURL) {\r\n fileBuffer = await fetchImageBuffer(sizeURL, name, mime, outputType);\r\n } else if (file) {\r\n // this method is used for squeezing thumbnails before generating them, so we need to calculate dimensions based on original image\r\n const sizeDimensions = getThumbnailDimensions({width: sizeWidth, height: sizeHeight}, imageDimensions);\r\n //console.log('sizeDimensions', sizeDimensions, sizeWidth, sizeHeight, imageDimensions);\r\n\r\n // If file is provided, use it directly\r\n const fileObj = new File([file], name, { type: mime });\r\n fileBuffer = await fileObj.arrayBuffer();\r\n resizeOptions['needResize'] = true;\r\n resizeOptions['fitMethod'] = 'contain';\r\n resizeOptions['width'] = sizeCrop ? sizeWidth : Math.round(sizeDimensions.width);\r\n resizeOptions['height'] = sizeCrop ? sizeHeight : Math.round(sizeDimensions.height);\r\n }\r\n\r\n if (!fileBuffer || fileBuffer.byteLength === 0) {\r\n console.warn(`Fetched image from ${sizeURL} is empty.`)\r\n continue;\r\n }\r\n\r\n if (compressFunction === compressPNG) {\r\n sizeBase64 = await compressFunction({ fileBuffer, outputType, resizeOptions });\r\n } else {\r\n sizeBase64 = await compressFunction({ fileBuffer, sourceType, outputType, mime, resizeOptions });\r\n }\r\n\r\n Object.assign(base64Sizes, { [key]: { 'url': sizeURL, 'base64': sizeBase64, 'width': resizeOptions['width'] ?? sizeWidth, 'height': resizeOptions['height'] ?? sizeHeight } });\r\n \r\n }\r\n\r\n return base64Sizes;\r\n}\r\n\r\nonmessage = async function (e) {\r\n if (e.ports && e.ports[0]) {\r\n rpcPort = e.ports[0];\r\n try { rpcPort.start(); } catch (err) { /* some browsers require start() */ }\r\n }\r\n\r\n const action = e.data.action;\r\n\r\n if (action === 'compress') {\r\n\r\n //console.log('Worker: Message received from main script', JSON.stringify(e.data, null, 2));\r\n const { format, url, name, sourceType, outputType, mime, sizes, skipFull, isPreview, file, base64Compressed, base64WebpCompressed, type } = e.data;\r\n options = e.data.options;\r\n\r\n try {\r\n let base64 = base64Compressed || ''; // base64Compressed is used for already compressed image, e.g. during image upload\r\n let base64Webp = base64WebpCompressed || '';\r\n let base64Sizes, base64SizesWebp;\r\n const base64Args = { url, name, sourceType, outputType, mime, isPreview, file };\r\n const base64SizesArgs = { name, sourceType, outputType, mime, sizes, file };\r\n\r\n switch (format) {\r\n case 'avif':\r\n base64 = base64 ? base64Compressed : await compressAndAssign(compressAVIF, base64Args);\r\n base64Sizes = await compressAndAssignThumbs(compressAVIF, base64SizesArgs, skipFull);\r\n break;\r\n case 'jpeg':\r\n if ( options.direct_webp && type !== 'path' ) {\r\n base64Args.outputType = 'webp';\r\n base64SizesArgs.outputType = 'webp';\r\n //base64SizesArgs.isAllSizes = true; // to convert all sizes to webp\r\n base64 = base64 ? base64Compressed : await compressAndAssign(compressJPEG, base64Args);\r\n base64Sizes = await compressAndAssignThumbs(compressJPEG, base64SizesArgs, skipFull);\r\n } else {\r\n base64 = base64 ? base64Compressed : await compressAndAssign(compressJPEG, base64Args); // take compressed image if available (e.g. during image upload)\r\n base64Sizes = await compressAndAssignThumbs(compressJPEG, base64SizesArgs, skipFull);\r\n\r\n if (options.auto_webp) {\r\n base64Args.outputType = 'webp';\r\n base64SizesArgs.outputType = 'webp';\r\n base64SizesArgs.isAllSizes = true; // to convert all sizes to webp\r\n base64Webp = base64Webp ? base64WebpCompressed : await compressAndAssign(compressJPEG, base64Args);\r\n base64SizesWebp = await compressAndAssignThumbs(compressJPEG, base64SizesArgs, skipFull);\r\n }\r\n }\r\n\r\n break;\r\n case 'png':\r\n if ( options.direct_webp && type !== 'path' ) {\r\n base64Args.outputType = 'webp';\r\n base64SizesArgs.outputType = 'webp';\r\n //base64SizesArgs.isAllSizes = true; // to compress all sizes to webp\r\n base64 = base64 ? base64Compressed : await compressAndAssign(compressPNG, base64Args);\r\n base64Sizes = await compressAndAssignThumbs(compressPNG, base64SizesArgs, skipFull);\r\n } else {\r\n base64 = base64 ? base64Compressed : await compressAndAssign(compressPNG, base64Args); // take compressed image if available (e.g. during image upload)\r\n base64Sizes = await compressAndAssignThumbs(compressPNG, base64SizesArgs, skipFull);\r\n\r\n if (options.auto_webp) {\r\n base64Args.outputType = 'webp';\r\n base64SizesArgs.outputType = 'webp';\r\n base64SizesArgs.isAllSizes = true; // to compress all sizes to webp\r\n base64Webp = base64Webp ? base64WebpCompressed : await compressAndAssign(compressPNG, base64Args);\r\n base64SizesWebp = await compressAndAssignThumbs(compressPNG, base64SizesArgs, skipFull);\r\n }\r\n }\r\n \r\n break;\r\n case 'webp':\r\n base64 = base64 ? base64Compressed : await compressAndAssign(compressWEBP, base64Args);\r\n base64Sizes = await compressAndAssignThumbs(compressWEBP, base64SizesArgs, skipFull);\r\n break;\r\n }\r\n\r\n postMessage({\r\n 'base64': base64,\r\n 'base64Sizes': base64Sizes,\r\n 'base64Webp': base64Webp,\r\n 'base64SizesWebp': base64SizesWebp,\r\n 'isDirectWebp': options.direct_webp,\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n postMessage({\r\n 'error': error\r\n });\r\n }\r\n }\r\n}\n\n//# sourceURL=webpack:///./assets/js/worker.js?"); 20 20 21 21 /***/ }) … … 54 54 /******/ // Load entry module and return exports 55 55 /******/ // This entry module depends on other loaded chunks and execution need to be delayed 56 /******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_- 515c76"], () => (__webpack_require__("./assets/js/worker.js")))56 /******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-88b2ac"], () => (__webpack_require__("./assets/js/worker.js"))) 57 57 /******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__); 58 58 /******/ return __webpack_exports__; … … 219 219 /******/ var next = __webpack_require__.x; 220 220 /******/ __webpack_require__.x = () => { 221 /******/ return __webpack_require__.e("vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_- 515c76").then(next);221 /******/ return __webpack_require__.e("vendors-node_modules_jsquash_avif_decode_js-node_modules_jsquash_avif_encode_js-node_modules_-88b2ac").then(next); 222 222 /******/ }; 223 223 /******/ })(); -
squeeze/trunk/assets/js/editor.bundle.js
r3311866 r3345284 17 17 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 18 18 19 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _handlers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./handlers.js */ \"./assets/js/handlers.js\");\n\r\n\r\n\r\n\r\n\"use strict\";\r\n\r\nconst { sprintf, __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](squeezeOptions);\r\nconst compressOptions = JSON.parse(squeezeOptions.options);\r\n\r\nconst addFilter = wp.hooks.addFilter;\r\nconst createHigherOrderComponent = wp.compose.createHigherOrderComponent;\r\nconst { createElement: el, Fragment } = wp.element;\r\n\r\n// import Spinner component\r\nconst { Spinner } = wp.components;\r\n\r\n async function handleCompressOnUpload(media) {\r\n const fileSubType = media.mime_type.split('/')[1];\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.maybeCompressAttachment(media.media_type, fileSubType, compressOptions)) {\r\n console.log('Compressing image:', media.id, media.source_url);\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n\r\n try {\r\n const attachmentResponse = await Squeeze.getAttachment(media.id);\r\n if (attachmentResponse.success === false) {\r\n window.onbeforeunload = null;\r\n console.error(sprintf(__('Error fetching attachment: %s', 'squeeze'), attachmentResponse.data));\r\n return;\r\n }\r\n //console.log('Attachment data:', attachmentResponse);\r\n const attachmentData = attachmentResponse.data;\r\n\r\n if (attachmentData.is_squeezed) {\r\n console.log('Image already compressed:', attachmentData.id);\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n const attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n console.log('Image uploaded successfully:', uploadData);\r\n window.onbeforeunload = null;\r\n } else {\r\n window.onbeforeunload = null;\r\n console.error(sprintf(__('Error uploading image: %s', 'squeeze'), uploadData.data));\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n window.onbeforeunload = null;\r\n }\r\n }\r\n}\r\n\r\n// Add custom attribute to core/image block\r\nwp.hooks.addFilter(\r\n 'blocks.registerBlockType',\r\n 'my-namespace/add-compressing-attribute',\r\n (settings, name) => {\r\n if (name === 'core/image') {\r\n return {\r\n ...settings,\r\n attributes: {\r\n ...settings.attributes,\r\n isSqueezing: {\r\n type: 'boolean',\r\n default: false,\r\n },\r\n },\r\n };\r\n }\r\n return settings;\r\n }\r\n);\r\n\r\nconst withImageOnSelect = createHigherOrderComponent(\r\n function (BlockEdit) {\r\n return function (props) {\r\n const { attributes } = props;\r\n // Only target the core/image block\r\n if (props.name !== 'core/image') {\r\n // If not the core/image block, return the original BlockEdit\r\n return el(BlockEdit, props);\r\n }\r\n\r\n const { isSqueezing } = attributes;\r\n\r\n // While compressing, render the original editor plus a Spinner overlay\r\n if (isSqueezing) {\r\n //console.log('withImageOnSelect', props);\r\n\r\n return el(\r\n Fragment,\r\n {},\r\n // The normal block edit, dimmed\r\n el(\r\n 'div',\r\n { style: { position: 'relative' } },\r\n el(BlockEdit, props),\r\n el(\r\n 'div',\r\n { style: { position: 'absolute', backgroundColor: 'rgba(255,255,255,0.5)', pointerEvents: 'none', width: '100%', height: '100%', left: '0%', top: '0%' } },\r\n ),\r\n // Spinner absolutely centered\r\n el(\r\n 'div',\r\n {\r\n style: {\r\n position: 'absolute',\r\n top: '50%',\r\n left: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n pointerEvents: 'none',\r\n },\r\n },\r\n el(Spinner, { size: 50 }),\r\n __('Squeezing image…', 'squeeze')\r\n )\r\n ),\r\n\r\n );\r\n }\r\n\r\n return el(BlockEdit, props);\r\n\r\n };\r\n },\r\n 'withImageOnSelect'\r\n);\r\n\r\n// Inject our HOC into Gutenberg’s BlockEdit pipeline\r\naddFilter(\r\n 'editor.BlockEdit',\r\n 'myplugin/with-image-onselect',\r\n withImageOnSelect\r\n);\r\n\r\nwp.domReady(function () {\r\n wp.apiFetch.use(function (options, next) {\r\n //console.log('API Request:', options); // Log all requests\r\n const result = next(options);\r\n if (options.path && options.path.startsWith('/wp/v2/media') && options.method === 'POST') {\r\n result.then(function (response) {\r\n if (response && response.id && response.media_type === 'image') {\r\n const mediaId = response.id;\r\n setTimeout(() => {\r\n const blocks = wp.data.select('core/block-editor').getBlocks();\r\n blocks.forEach(block => { // TBD: add support for multiple images upload (gallery block)\r\n if (block.name === 'core/image' && block.attributes.id === mediaId) {\r\n wp.data.dispatch('core/block-editor').updateBlockAttributes(block.clientId, { isSqueezing: true });\r\n handleCompressOnUpload(response).then(() => {\r\n wp.data.dispatch('core/block-editor').updateBlockAttributes(block.clientId, { isSqueezing: false });\r\n });\r\n }\r\n });\r\n }, 100); // Delay to ensure block attributes are updated\r\n }\r\n });\r\n }\r\n return result;\r\n });\r\n});\n\n//# sourceURL=webpack:///./assets/js/editor.js?");19 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _handlers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./handlers.js */ \"./assets/js/handlers.js\");\n\r\n\r\n\r\n\r\n\"use strict\";\r\n\r\nconst { sprintf, __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](squeezeOptions);\r\nconst compressOptions = JSON.parse(squeezeOptions.options);\r\n\r\nconst addFilter = wp.hooks.addFilter;\r\nconst createHigherOrderComponent = wp.compose.createHigherOrderComponent;\r\nconst { createElement: el, Fragment } = wp.element;\r\n\r\n// import Spinner component\r\nconst { Spinner } = wp.components;\r\n\r\n// Add custom attribute to core/image and generateblocks/media blocks\r\nwp.hooks.addFilter(\r\n 'blocks.registerBlockType',\r\n 'squeeze/add-compressing-attribute',\r\n (settings, name) => {\r\n if (name === 'core/image' || name === 'generateblocks/media') {\r\n return {\r\n ...settings,\r\n attributes: {\r\n ...settings.attributes,\r\n isSqueezing: {\r\n type: 'boolean',\r\n default: false,\r\n },\r\n },\r\n };\r\n }\r\n return settings;\r\n }\r\n);\r\n\r\nconst withImageOnSelect = createHigherOrderComponent(\r\n function (BlockEdit) {\r\n return function (props) {\r\n const { attributes } = props;\r\n // Only target the core/image block\r\n if (props.name !== 'core/image' && props.name !== 'generateblocks/media') {\r\n // If not the core/image block, return the original BlockEdit\r\n return el(BlockEdit, props);\r\n }\r\n\r\n const { isSqueezing } = attributes;\r\n\r\n // While compressing, render the original editor plus a Spinner overlay\r\n if (isSqueezing) {\r\n\r\n return el(\r\n Fragment,\r\n {},\r\n // The normal block edit, dimmed\r\n el(\r\n 'div',\r\n { style: { position: 'relative' } },\r\n el(BlockEdit, props),\r\n el(\r\n 'div',\r\n { style: { position: 'absolute', backgroundColor: 'rgba(255,255,255,0.5)', pointerEvents: 'none', width: '100%', height: '100%', left: '0%', top: '0%' } },\r\n ),\r\n // Spinner absolutely centered\r\n el(\r\n 'div',\r\n {\r\n style: {\r\n position: 'absolute',\r\n top: '50%',\r\n left: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n pointerEvents: 'none',\r\n },\r\n },\r\n el(Spinner, { size: 50 }),\r\n __('Squeezing image…', 'squeeze')\r\n )\r\n ),\r\n\r\n );\r\n }\r\n\r\n return el(BlockEdit, props);\r\n\r\n };\r\n },\r\n 'withImageOnSelect'\r\n);\r\n\r\n// Inject our HOC into Gutenberg’s BlockEdit pipeline\r\naddFilter(\r\n 'editor.BlockEdit',\r\n 'squeeze/with-image-onselect',\r\n withImageOnSelect\r\n);\r\n\r\n/**\r\n * Handles the compression of thumbnails after the image has been uploaded.\r\n * This function checks if the file is an image, determines if it should be compressed,\r\n * fetches the attachment data, and then compresses and uploads the image.\r\n * It also handles the original file and WebP conversion if specified in the options.\r\n * @param {object} file - The file attachment object.\r\n * @returns {Promise<void>}\r\n */\r\nasync function handleCompressThumbs(file) {\r\n const fileType = file.mime_type.split('/')[0];\r\n const fileSubType = file.mime_type.split('/')[1];\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_1__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) {\r\n return;\r\n }\r\n\r\n //console.log('Compressing image:', file.id, file.source_url);\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n\r\n try {\r\n const attachmentResponse = await Squeeze.getAttachment(file.id);\r\n\r\n if (attachmentResponse.success === false) {\r\n window.onbeforeunload = null;\r\n console.error(sprintf(__('Error fetching attachment: %s', 'squeeze'), attachmentResponse.data));\r\n return;\r\n }\r\n\r\n const attachmentData = attachmentResponse.data;\r\n\r\n if (attachmentData.is_squeezed) {\r\n console.warn('Image already compressed:', attachmentData.id);\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n const attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.extendAttachment(attachment, file);\r\n\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n //console.log('Image uploaded successfully:', uploadData);\r\n window.onbeforeunload = null;\r\n } else {\r\n window.onbeforeunload = null;\r\n console.error(sprintf(__('Error uploading image: %s', 'squeeze'), uploadData.data));\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n window.onbeforeunload = null;\r\n }\r\n}\r\n\r\n/**\r\n * Walk through all blocks and compress thumbnails for the given media ID.\r\n * This function checks if the block or any of its inner blocks matches the media ID,\r\n * and if so, it compresses the thumbnails using handleCompressThumbs.\r\n * @param {integer} mediaId - The ID of the media item to compress.\r\n * @param {object} response - The response object containing the media data.\r\n * @returns {Promise<void>}\r\n */\r\nfunction squeezeAndUpdateThumbs(mediaId, response) {\r\n //console.log('squeezeAndUpdateThumbs', mediaId, response);\r\n return new Promise((resolve) => {\r\n setTimeout(() => {\r\n const blocks = wp.data.select('core/block-editor').getBlocks();\r\n // collect all handleCompressThumbs() calls\r\n const all = blocks.map(block => {\r\n // Check if the block or any of its innerBlocks matches the mediaId\r\n const matchesMedia = (block.attributes.id === mediaId) || (block.attributes.mediaId === mediaId);\r\n\r\n // Helper to recursively check innerBlocks\r\n function hasMatchingInnerBlock(innerBlocks) {\r\n if (!innerBlocks || !innerBlocks.length) return false;\r\n return innerBlocks.some(innerBlock => {\r\n if (\r\n innerBlock.attributes.id === mediaId ||\r\n innerBlock.attributes.mediaId === mediaId\r\n ) {\r\n return true;\r\n }\r\n return hasMatchingInnerBlock(innerBlock.innerBlocks);\r\n });\r\n }\r\n\r\n const isMatchingInnerBlock = hasMatchingInnerBlock(block.innerBlocks);\r\n\r\n if (!matchesMedia && !isMatchingInnerBlock) {\r\n return null;\r\n }\r\n\r\n // mark squeezing start\r\n if (isMatchingInnerBlock) {\r\n block.innerBlocks.forEach(innerBlock => {\r\n if (innerBlock.attributes.id === mediaId || innerBlock.attributes.mediaId === mediaId) {\r\n wp.data.dispatch('core/block-editor').updateBlockAttributes(innerBlock.clientId, { isSqueezing: true });\r\n }\r\n });\r\n } else {\r\n wp.data.dispatch('core/block-editor')\r\n .updateBlockAttributes(block.clientId, { isSqueezing: true });\r\n }\r\n // compress, then mark squeezing end\r\n return handleCompressThumbs(response)\r\n .then(() => {\r\n if (isMatchingInnerBlock) {\r\n block.innerBlocks.forEach(innerBlock => {\r\n if (innerBlock.attributes.id === mediaId || innerBlock.attributes.mediaId === mediaId) {\r\n wp.data.dispatch('core/block-editor').updateBlockAttributes(innerBlock.clientId, { isSqueezing: false });\r\n }\r\n });\r\n } else {\r\n wp.data.dispatch('core/block-editor')\r\n .updateBlockAttributes(block.clientId, { isSqueezing: false });\r\n }\r\n });\r\n }).filter(p => p); // remove nulls\r\n \r\n // when all compress‐promises settle (or immediately, if none)\r\n Promise.all(all).then(() => {\r\n resolve();\r\n });\r\n }, 100); // ensure attributes are ready\r\n });\r\n}\r\n\r\n// Compress the original before upload and thumbnails after upload\r\nwp.domReady(function () {\r\n // Middleware to intercept and modify the upload request\r\n wp.apiFetch.use(async (options, next) => {\r\n if (options.method === 'POST' && options.path.startsWith('/wp/v2/media')) {\r\n\r\n const formData = options.body;\r\n\r\n if (!(formData instanceof FormData) || !formData.has('file')) {\r\n return next(options);\r\n }\r\n\r\n const file = formData.get('file');\r\n\r\n if (file && !file.type.startsWith('image/')) {\r\n //console.log('Not an image file:', file);\r\n return next(options); // Proceed without modification\r\n }\r\n\r\n const fileType = file.type.split('/')[0];\r\n const fileSubType = file.type.split('/')[1];\r\n let originalFile = file;\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_1__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) {\r\n //console.log('Compression not needed for:', file.name);\r\n return next(options); // Proceed without modification\r\n }\r\n\r\n \r\n\r\n const noticeId = 'compression-notice';\r\n // Show compression notice\r\n wp.data.dispatch('core/notices').createNotice(\r\n 'info',\r\n __('Squeezing the image...', 'squeeze'),\r\n { id: noticeId, isDismissible: false }\r\n )\r\n\r\n try {\r\n //console.time('Compressing image:', file.name);\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n\r\n // Compress the file\r\n //console.log('Compressing image:', file.name, file.size, file.type);\r\n const base64Obj = await Squeeze.compressBeforeUpload(file);\r\n if (!base64Obj || !base64Obj.base64) {\r\n console.warn('Compression skipped or failed for:', file.name, base64Obj);\r\n return next(options); // Proceed without modification\r\n }\r\n\r\n if (compressOptions.backup_original) {\r\n //console.log('Backing up original file:', file.name);\r\n const originalBlob = file instanceof Blob ? file : new Blob([file], { type: file.type });\r\n const isDirectWebp = compressOptions?.direct_webp && file.type !== 'image/webp';\r\n // If direct WebP conversion is enabled, convert the original file to WebP\r\n originalFile = isDirectWebp ? await Squeeze.convertFileToWebp(originalBlob) : originalBlob; // Use the original file from the attachment\r\n }\r\n\r\n const newFormData = new FormData();\r\n const imageBlob = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.base64ToBlob(base64Obj.base64, file.type);\r\n\r\n newFormData.append('file', imageBlob, file.name);\r\n\r\n // Preserve other FormData fields (e.g., title, alt)\r\n for (const [key, value] of options.body.entries()) {\r\n if (key !== 'file') {\r\n newFormData.append(key, value);\r\n }\r\n }\r\n\r\n //console.log('New FormData:', newFormData);\r\n\r\n options.body = newFormData;\r\n\r\n const response = await next(options);\r\n\r\n if (response && response.id && response.media_type === 'image') {\r\n \r\n response.base64 = base64Obj.base64; // Add the base64 data to the response\r\n response.base64Webp = base64Obj?.base64Webp; // Add the WebP base64 data to the response\r\n if (compressOptions.backup_original) {\r\n response.originalFile = originalFile; // Add the original file to the response\r\n }\r\n\r\n const mediaId = response.id;\r\n squeezeAndUpdateThumbs(mediaId, response)\r\n .then(() => {\r\n // Dismiss the compression notice\r\n wp.data.dispatch('core/notices').removeNotice('compression-notice');\r\n window.onbeforeunload = null;\r\n //console.timeEnd('Compressing image:', file.name);\r\n })\r\n .catch(error => {\r\n console.error('Error during squeeze and update:', error);\r\n // Show error notice\r\n wp.data.dispatch('core/notices').createNotice(\r\n 'error',\r\n sprintf(__('Error squeezing the image: %s', 'squeeze'), error.message),\r\n { id: noticeId, isDismissible: true }\r\n );\r\n window.onbeforeunload = null;\r\n });\r\n\r\n }\r\n\r\n return response; // Return the modified response\r\n\r\n } catch (error) {\r\n wp.data.dispatch('core/notices').removeNotice('compression-notice');\r\n console.error('Error during image compression:', error);\r\n // Show error notice\r\n wp.data.dispatch('core/notices').createNotice(\r\n 'error',\r\n sprintf(__('Error squeezing the image: %s', 'squeeze'), error?.message || error),\r\n { id: noticeId, isDismissible: true }\r\n );\r\n window.onbeforeunload = null;\r\n return next(options); // Proceed without modification\r\n }\r\n }\r\n\r\n return next(options);\r\n\r\n });\r\n});\n\n//# sourceURL=webpack:///./assets/js/editor.js?"); 20 20 21 21 /***/ }), … … 27 27 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 28 28 29 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"handleBulkButtonClick\": () => (/* binding */ handleBulkButtonClick),\n/* harmony export */ \"handleBulkFromPage\": () => (/* binding */ handleBulkFromPage),\n/* harmony export */ \"handleBulkToggle\": () => (/* binding */ handleBulkToggle),\n/* harmony export */ \"handleButtonsClick\": () => (/* binding */ handleButtonsClick),\n/* harmony export */ \"handleClosePathDialog\": () => (/* binding */ handleClosePathDialog),\n/* harmony export */ \"handle DirectoryCheck\": () => (/* binding */ handleDirectoryCheck),\n/* harmony export */ \"handleDirectoryClick\": () => (/* binding */ handleDirectoryClick),\n/* harmony export */ \"handleFetchImagesFromPage\": () => (/* binding */ handleFetchImagesFromPage),\n/* harmony export */ \"handleMultiFileFormUpload\": () => (/* binding */ handleMultiFileFormUpload),\n/* harmony export */ \"handleOnLeave\": () => (/* binding */ handleOnLeave),\n/* harmony export */ \"handleRecursiveUpload\": () => (/* binding */ handleRecursiveUpload),\n/* harmony export */ \"handleRestoreBtnClick\": () => (/* binding */ handleRestoreBtnClick),\n/* harmony export */ \"handleSingleBtnClick\": () => (/* binding */ handleSingleBtnClick)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](squeezeOptions);\r\n\r\nconst updateUI = (initId, response) => {\r\n const statusEl = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.postsFilterForm?.querySelector(`#post-${initId} .column-squeeze .squeeze_status`);\r\n if (statusEl) statusEl.innerHTML = response.data;\r\n\r\n const gridItem = document.querySelector(`.media-frame.mode-grid .attachment[data-id=\"${initId}\"]`);\r\n if (gridItem) {\r\n const centered = gridItem.querySelector('.centered');\r\n const progress = gridItem.querySelector('.media-progress-bar');\r\n if (centered) centered.style.display = 'block';\r\n if (progress) progress.remove();\r\n gridItem.classList.remove('uploading');\r\n }\r\n};\r\n\r\nconst getTotalPages = (path) => {\r\n const selectors = {\r\n uncompressed: \"input[name='squeeze_bulk_uncompressed_pages']\",\r\n all: \"input[name='squeeze_bulk_total_pages']\"\r\n };\r\n const sel = selectors[path];\r\n const val = sel && document.querySelector(sel)?.value;\r\n return Number(val) || 1;\r\n};\r\n\r\nconst checkPaused = (data, page) => {\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused) return false;\r\n handleBulkPause(data, page);\r\n return true;\r\n};\r\n\r\nconst logAndThumbnail = async (filename, response, wrapper) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(response.data, {\r\n mediaLogWrapper: wrapper,\r\n iconId: response.success ? 'check-mark-circle-icon' : 'ban-sign-icon'\r\n });\r\n\r\n const titleEl = wrapper.querySelector('h3');\r\n if (titleEl && response.filename) {\r\n titleEl.textContent = `${__('Media', 'squeeze')} ${filename} (${response.filename}):`;\r\n }\r\n\r\n const thumbUrl = response.sizes?.thumbnail?.url || response.url;\r\n if (thumbUrl) {\r\n const thumb = document.createElement('div');\r\n thumb.classList.add('media-log-thumbnail');\r\n thumb.innerHTML = `<img src=\"${thumbUrl}\" alt=\"${filename}\"/>`;\r\n wrapper.appendChild(thumb);\r\n }\r\n};\r\n\r\nconst handleDirectoryCheck = (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.savePathBtn.disabled = !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.dirContainer.querySelector(\"input[type='checkbox']:checked\");\r\n};\r\n\r\nconst handleClosePathDialog = (event) => {\r\n if (!event.target.contains(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog)) return;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog.close();\r\n};\r\n\r\nconst handleBulkToggle = (event, process, mediaIDs, page = 1) => {\r\n const isPaused = event.target.dataset.running === 'true';\r\n\r\n event.target.dataset.running = isPaused ? 'false' : 'true';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, isPaused ? __('Resume bulk squeezing', 'squeeze') : __('Pause bulk squeezing', 'squeeze'), isPaused ? '#play-button-round-icon' : '#pause-button-icon');\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused = isPaused;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process = process;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = mediaIDs;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = page;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target = event.target;\r\n\r\n console.log('handleBulkToggle', _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData);\r\n\r\n return isPaused;\r\n};\r\n\r\n// Handle single compress button click\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleSingleBtnClick = async (event, Squeeze) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n const squeezeStatus = event.target.closest(\"td\").querySelector(\".squeeze_status\");\r\n\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async (data) => {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const response = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n //squeezeStatus.innerHTML = response?.data?.message ?? response;\r\n squeezeStatus.innerHTML = response?.data ?? response;\r\n\r\n if (event.target.closest(\"td.field\")) {\r\n const table = event.target.closest(\"td\")?.querySelector(\".squeeze_status .squeeze-comparison-table\");\r\n if (table) {\r\n const td = document.createElement(\"td\");\r\n td.classList.add(\"field\");\r\n td.style.width = \"100%\";\r\n td.appendChild(table);\r\n event.target.closest(\"tr\").appendChild(td);\r\n }\r\n }\r\n // TBD: add file size label to the attachment info\r\n /*\r\n if (event.target.closest('.attachment-info')) {\r\n const fileSizeLabel = event.target.closest('.attachment-info').querySelector('.file-size');\r\n if (fileSizeLabel) {\r\n const fileSize = response?.data?.sizes?.scaled?.compressed_size ?? response?.data?.sizes?.original?.compressed_size ?? null;\r\n if (fileSize) {\r\n const humanFileSize = SqueezeHelpers.humanFileSize(fileSize, true);\r\n fileSizeLabel.innerHTML = fileSizeLabel.innerHTML.replace(/(<\\/strong>\\s*)(.*)/, `$1${humanFileSize}`);\r\n }\r\n }\r\n }\r\n */\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error;\r\n } finally {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.removeAllButtons(event.target.closest(\"td\")?.querySelectorAll(`button`));\r\n window.onbeforeunload = null;\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error;\r\n event.target.remove();\r\n }\r\n};\r\n\r\nconst handleRestoreBtnClick = async (event) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n\r\n event.target.disabled = true;\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Restore in process...', 'squeeze');\r\n\r\n try {\r\n const response = await Squeeze.handleRestore(attachmentID);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = response.data;\r\n } catch (error) {\r\n console.error(error);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = error;\r\n } finally {\r\n event.target.closest('td').querySelector(`[name='squeeze_compress_again']`).disabled = false;\r\n event.target.remove();\r\n window.onbeforeunload = null;\r\n }\r\n};\r\n\r\nconst handleBulkButtonClick = async (event, process, mediaIDs, currentPage) => {\r\n if (mediaIDs.length === 0) return;\r\n\r\n const totalPages = getTotalPages(process);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableBulkButtons();\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process === process) {\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs/*.length > 0*/) {\r\n mediaIDs = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs;\r\n }\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page) {\r\n currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page;\r\n }\r\n }\r\n\r\n const isPaused = handleBulkToggle(event, process, mediaIDs, currentPage);\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await handleRecursiveUpload(process, mediaIDs, currentPage, true);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0 && finalResponse.page >= totalPages) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n};\r\n\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleButtonsClick = async (event, Squeeze) => {\r\n const singleBtnName = 'squeeze_compress_single';\r\n const compressAgainBtnName = 'squeeze_compress_again';\r\n const restoreBtnName = 'squeeze_restore';\r\n\r\n if (event.target.getAttribute(\"name\") === singleBtnName || event.target.getAttribute(\"name\") === compressAgainBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Squeezing...', 'squeeze');\r\n window.onbeforeunload = handleOnLeave;\r\n handleSingleBtnClick(event, Squeeze);\r\n }\r\n\r\n if (event.target.getAttribute(\"name\") === restoreBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n window.onbeforeunload = handleOnLeave;\r\n handleRestoreBtnClick(event);\r\n }\r\n};\r\n\r\nconst handleDirectoryClick = async (event) => {\r\n if (event.target !== event.currentTarget) return;\r\n\r\n const currentDir = event.target.closest(\".directory-item\");\r\n const currentPath = currentDir.dataset.path;\r\n const parentPath = currentDir.dataset.parent;\r\n\r\n if (parentPath === '/' || currentDir.classList.contains(\"loading\")) return;\r\n\r\n if (currentDir.classList.contains(\"loaded\")) {\r\n currentDir.classList.toggle(\"opened\");\r\n return;\r\n }\r\n\r\n currentDir.classList.add(\"loading\");\r\n\r\n const subDirs = await Squeeze.getDirectories(currentPath);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.renderDirectories(subDirs, currentDir, {\r\n handleDirectoryClick,\r\n handleDirectoryCheck\r\n });\r\n\r\n currentDir.classList.remove(\"loading\");\r\n currentDir.classList.add(\"loaded\", \"opened\");\r\n}\r\n\r\n/**\r\n * Hadnle warning on page leave\r\n*/\r\nconst handleOnLeave = () => {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const page = urlParams.get('page');\r\n const isUploadPage = window.location.href.includes('upload.php');\r\n const isMediaNewPage = window.location.href.includes('media-new.php');\r\n const isAttachmentPage = window.location.href.includes('post.php') && urlParams.get('action') === 'edit';\r\n\r\n if (page === 'squeeze-bulk' || isMediaNewPage || isAttachmentPage) {\r\n return __('Are you sure you want to leave this page? The squeezing process will be terminated!', 'squeeze');\r\n }\r\n if (isUploadPage) {\r\n return __('Are you sure you want to leave this page? The settings will not be saved!', 'squeeze');\r\n }\r\n};\r\n\r\nconst handleBulkPause = (data, currentPage) => {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(__('Bulk squeezing has been paused!', 'squeeze'), { isPause: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = data;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = currentPage;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target.disabled = false;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target, __('Resume bulk squeezing', 'squeeze'), '#play-button-round-icon');\r\n};\r\n\r\nconst handleUpdateChart = (uncompressedImagesCount) => {\r\n const chartValue = document.querySelector(\".squeeze-bulk-media-stats-chart-value > text\");\r\n const chartBar = document.querySelector(\".squeeze-bulk-media-stats-chart\");\r\n const squeezedImages = document.querySelector(\".squeeze-bulk-media-stats-item-value\");\r\n\r\n if (!chartValue || !chartBar) return;\r\n\r\n const imagesLeft = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages - uncompressedImagesCount;\r\n const percentage = parseFloat((imagesLeft / _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages) * 100).toFixed(2);\r\n const dasharray = percentage * 560 / 100;\r\n chartValue.textContent = `${percentage}%`;\r\n chartBar.style.setProperty('--squeeze-dasharray', dasharray);\r\n\r\n if (squeezedImages) {\r\n squeezedImages.textContent = `${imagesLeft} / ${_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages}`;\r\n }\r\n};\r\n\r\nconst handleRecursiveUpload = async (path, data, currentPage, isUpdateChart = false) => {\r\n\r\n if (!Array.isArray(data)) return { success: false, data: 'No data provided!', mediaIDs: [] }; // when bulk directory path has no images\r\n \r\n const totalPages = getTotalPages(path);\r\n\r\n if (data.length === 0) {\r\n currentPage += 1;\r\n if (currentPage > totalPages || !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId) return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n }\r\n }\r\n\r\n const initData = [...data]; // initial data\r\n\r\n const filename = data[0]?.filename ? data[0].filename : `ID #${data[0]}`;\r\n const mediaLogWrapper = await _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${__('Start squeezing...', 'squeeze')}`, { title: filename, isStart: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId = data[0] || 0; // update lastId to the last processed ID\r\n\r\n try {\r\n const response = await Squeeze.handleBulkUpload(path, data);\r\n\r\n await logAndThumbnail(filename, response, mediaLogWrapper);\r\n\r\n if (isUpdateChart && path !== 'all') {\r\n let uncompressedImagesCount = 0;\r\n if (path === 'uncompressed') {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages - 1 || 0;\r\n uncompressedImagesCount = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages;\r\n } else if (path === 'path') {\r\n uncompressedImagesCount = response.mediaIDs.length;\r\n }\r\n handleUpdateChart(uncompressedImagesCount);\r\n }\r\n\r\n if (checkPaused(data, currentPage)) {\r\n return { success: false, data: 'Process has been paused!', mediaIDs: data, page: currentPage };\r\n }\r\n\r\n updateUI(initData[0], response);\r\n\r\n if (response.mediaIDs.length > 0) {\r\n return handleRecursiveUpload(path, response.mediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { ...response, page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${error}`, { mediaLogWrapper, iconId: 'ban-sign-icon' });\r\n\r\n if (data.length > 0) {\r\n return handleRecursiveUpload(path, data, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { success: false, data: error, mediaIDs: [], page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n\r\nconst handleMultiFileFormUpload = (compressOptions) => {\r\n if (typeof wpUploaderInit === 'undefined' || typeof plupload === 'undefined' || typeof uploader === 'undefined') return;\r\n\r\n const SqueezeUploader = uploader;\r\n\r\n SqueezeUploader.bind('FilesAdded', function (up, files) { });\r\n\r\n SqueezeUploader.bind('FileUploaded', function (up, file, response) {\r\n const fileMime = file.type;\r\n const fileType = fileMime.split('/')[0];\r\n const fileSubType = fileMime.split('/')[1];\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) return;\r\n\r\n const fileID = file.id;\r\n const attachmentID = response.response;\r\n const mediaItem = document.getElementById(`media-item-${fileID}`);\r\n\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n /**\r\n * Wait for media item to load( 'async-upload.php' )\r\n * Ping every 1 second until the media item is loaded\r\n * @returns Promise\r\n */\r\n const waitForItemLoad = () => {\r\n return new Promise((resolve) => {\r\n let interval = setInterval(() => {\r\n if (mediaItem.querySelector('.media-item-wrapper')) {\r\n mediaItem.querySelector('.media-item-wrapper').innerHTML += `\r\n <div class=\"progress\">\r\n <div class=\"percent\">${__('Squeezing...', 'squeeze')}</div>\r\n <div class=\"bar\" style=\"width: 200px;\"></div>\r\n </div>\r\n `;\r\n clearInterval(interval);\r\n resolve();\r\n }\r\n }, 1000);\r\n });\r\n };\r\n\r\n waitForItemLoad().then(() => {\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async function (data) {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n window.onbeforeunload = null;\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${uploadData.data}</div>`;\r\n mediaItem.querySelector('.progress')?.remove();\r\n } else {\r\n alert(uploadData?.data ?? uploadData);\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n });\r\n\r\n SqueezeUploader.bind('UploadComplete', function (up, files) { });\r\n};\n\n//# sourceURL=webpack:///./assets/js/handlers.js?");29 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"handleBulkButtonClick\": () => (/* binding */ handleBulkButtonClick),\n/* harmony export */ \"handleBulkFromPage\": () => (/* binding */ handleBulkFromPage),\n/* harmony export */ \"handleBulkToggle\": () => (/* binding */ handleBulkToggle),\n/* harmony export */ \"handleButtonsClick\": () => (/* binding */ handleButtonsClick),\n/* harmony export */ \"handleClosePathDialog\": () => (/* binding */ handleClosePathDialog),\n/* harmony export */ \"handleCompressBeforeUpload\": () => (/* binding */ handleCompressBeforeUpload),\n/* harmony export */ \"handleDirectoryCheck\": () => (/* binding */ handleDirectoryCheck),\n/* harmony export */ \"handleDirectoryClick\": () => (/* binding */ handleDirectoryClick),\n/* harmony export */ \"handleFetchImagesFromPage\": () => (/* binding */ handleFetchImagesFromPage),\n/* harmony export */ \"handleMultiFileFormUpload\": () => (/* binding */ handleMultiFileFormUpload),\n/* harmony export */ \"handleOnLeave\": () => (/* binding */ handleOnLeave),\n/* harmony export */ \"handleRecursiveUpload\": () => (/* binding */ handleRecursiveUpload),\n/* harmony export */ \"handleRestoreBtnClick\": () => (/* binding */ handleRestoreBtnClick),\n/* harmony export */ \"handleSingleBtnClick\": () => (/* binding */ handleSingleBtnClick)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](squeezeOptions);\r\n\r\nconst updateUI = (initId, response) => {\r\n const statusEl = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.postsFilterForm?.querySelector(`#post-${initId} .column-squeeze .squeeze_status`);\r\n if (statusEl) statusEl.innerHTML = response?.data?.message ?? response?.data ?? response;\r\n\r\n const gridItem = document.querySelector(`.media-frame.mode-grid .attachment[data-id=\"${initId}\"]`);\r\n if (gridItem) {\r\n const centered = gridItem.querySelector('.centered');\r\n const progress = gridItem.querySelector('.media-progress-bar');\r\n if (centered) centered.style.display = 'block';\r\n if (progress) progress.remove();\r\n gridItem.classList.remove('uploading');\r\n }\r\n};\r\n\r\nconst getTotalPages = (path) => {\r\n const selectors = {\r\n uncompressed: \"input[name='squeeze_bulk_uncompressed_pages']\",\r\n all: \"input[name='squeeze_bulk_total_pages']\"\r\n };\r\n const sel = selectors[path];\r\n const val = sel && document.querySelector(sel)?.value;\r\n return Number(val) || 1;\r\n};\r\n\r\nconst checkPaused = (data, page) => {\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused) return false;\r\n handleBulkPause(data, page);\r\n return true;\r\n};\r\n\r\nconst logAndThumbnail = async (filename, response, wrapper) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(response?.data?.message ?? response?.data, {\r\n mediaLogWrapper: wrapper,\r\n iconId: response.success ? 'check-mark-circle-icon' : 'ban-sign-icon'\r\n });\r\n\r\n const titleEl = wrapper?.querySelector('h3');\r\n if (titleEl && response?.data?.filename) {\r\n titleEl.textContent = `${__('Media', 'squeeze')} ${filename} (${response.data.filename}):`;\r\n }\r\n\r\n const thumbUrl = response?.data?.sizes?.thumbnail?.url || response?.data?.url || response?.url;\r\n if (thumbUrl) {\r\n const thumb = document.createElement('div');\r\n thumb.classList.add('media-log-thumbnail');\r\n thumb.innerHTML = `<img src=\"${thumbUrl}\" alt=\"${filename}\"/>`;\r\n wrapper?.appendChild(thumb);\r\n }\r\n};\r\n\r\nconst handleDirectoryCheck = (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.savePathBtn.disabled = !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.dirContainer.querySelector(\"input[type='checkbox']:checked\");\r\n};\r\n\r\nconst handleClosePathDialog = (event) => {\r\n if (!event.target.contains(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog)) return;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog.close();\r\n};\r\n\r\nconst handleBulkToggle = (event, process, mediaIDs, page = 1) => {\r\n const isPaused = event.target.dataset.running === 'true';\r\n\r\n event.target.dataset.running = isPaused ? 'false' : 'true';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, isPaused ? __('Resume bulk squeezing', 'squeeze') : __('Pause bulk squeezing', 'squeeze'), isPaused ? '#play-button-round-icon' : '#pause-button-icon');\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused = isPaused;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process = process;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = mediaIDs;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = page;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target = event.target;\r\n\r\n //console.log('handleBulkToggle', cachedMediaData);\r\n\r\n return isPaused;\r\n};\r\n\r\n// Handle single compress button click\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleSingleBtnClick = async (event, Squeeze) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n const squeezeStatus = event.target.closest(\"td\").querySelector(\".squeeze_status\");\r\n\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async (data) => {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const response = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n squeezeStatus.innerHTML = response?.data?.message ?? response?.data ?? response;\r\n\r\n if (event.target.closest(\"td.field\")) {\r\n const table = event.target.closest(\"td\")?.querySelector(\".squeeze_status .squeeze-comparison-table\");\r\n if (table) {\r\n const td = document.createElement(\"td\");\r\n td.classList.add(\"field\");\r\n td.style.width = \"100%\";\r\n td.appendChild(table);\r\n event.target.closest(\"tr\").appendChild(td);\r\n }\r\n }\r\n // TBD: add file size label to the attachment info\r\n /*\r\n if (event.target.closest('.attachment-info')) {\r\n const fileSizeLabel = event.target.closest('.attachment-info').querySelector('.file-size');\r\n if (fileSizeLabel) {\r\n const fileSize = response?.data?.sizes?.scaled?.compressed_size ?? response?.data?.sizes?.original?.compressed_size ?? null;\r\n if (fileSize) {\r\n const humanFileSize = SqueezeHelpers.humanFileSize(fileSize, true);\r\n fileSizeLabel.innerHTML = fileSizeLabel.innerHTML.replace(/(<\\/strong>\\s*)(.*)/, `$1${humanFileSize}`);\r\n }\r\n }\r\n }\r\n */\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error?.message ?? error;\r\n } finally {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.removeAllButtons(event.target.closest(\"td\")?.querySelectorAll(`button`));\r\n window.onbeforeunload = null;\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error?.message ?? error;\r\n event.target.remove();\r\n }\r\n};\r\n\r\nconst handleRestoreBtnClick = async (event) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n\r\n event.target.disabled = true;\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Restore in process...', 'squeeze');\r\n\r\n try {\r\n const response = await Squeeze.handleRestore(attachmentID);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = response?.data ?? response;\r\n } catch (error) {\r\n console.error(error);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = error?.message ?? JSON.stringify(error, null, 2);\r\n } finally {\r\n event.target.closest('td').querySelector(`[name='squeeze_compress_again']`).disabled = false;\r\n event.target.remove();\r\n window.onbeforeunload = null;\r\n }\r\n};\r\n\r\nconst handleBulkButtonClick = async (event, process, mediaIDs, currentPage) => {\r\n if (mediaIDs.length === 0) return;\r\n\r\n const totalPages = getTotalPages(process);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableBulkButtons();\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process === process) {\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs/*.length > 0*/) {\r\n mediaIDs = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs;\r\n }\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page) {\r\n currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page;\r\n }\r\n }\r\n\r\n const isPaused = handleBulkToggle(event, process, mediaIDs, currentPage);\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await handleRecursiveUpload(process, mediaIDs, currentPage, true);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0 && finalResponse.page >= totalPages) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n};\r\n\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleButtonsClick = async (event, Squeeze) => {\r\n const singleBtnName = 'squeeze_compress_single';\r\n const compressAgainBtnName = 'squeeze_compress_again';\r\n const restoreBtnName = 'squeeze_restore';\r\n\r\n if (event.target.getAttribute(\"name\") === singleBtnName || event.target.getAttribute(\"name\") === compressAgainBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Squeezing...', 'squeeze');\r\n window.onbeforeunload = handleOnLeave;\r\n handleSingleBtnClick(event, Squeeze);\r\n }\r\n\r\n if (event.target.getAttribute(\"name\") === restoreBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n window.onbeforeunload = handleOnLeave;\r\n handleRestoreBtnClick(event);\r\n }\r\n};\r\n\r\nconst handleDirectoryClick = async (event) => {\r\n if (event.target !== event.currentTarget) return;\r\n\r\n const currentDir = event.target.closest(\".directory-item\");\r\n const currentPath = currentDir.dataset.path;\r\n const parentPath = currentDir.dataset.parent;\r\n\r\n if (parentPath === '/' || currentDir.classList.contains(\"loading\")) return;\r\n\r\n if (currentDir.classList.contains(\"loaded\")) {\r\n currentDir.classList.toggle(\"opened\");\r\n return;\r\n }\r\n\r\n currentDir.classList.add(\"loading\");\r\n\r\n const subDirs = await Squeeze.getDirectories(currentPath);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.renderDirectories(subDirs, currentDir, {\r\n handleDirectoryClick,\r\n handleDirectoryCheck\r\n });\r\n\r\n currentDir.classList.remove(\"loading\");\r\n currentDir.classList.add(\"loaded\", \"opened\");\r\n}\r\n\r\n/**\r\n * Hadnle warning on page leave\r\n*/\r\nconst handleOnLeave = () => {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const page = urlParams.get('page');\r\n const isUploadPage = window.location.href.includes('upload.php');\r\n const isMediaNewPage = window.location.href.includes('media-new.php');\r\n const isAttachmentPage = window.location.href.includes('post.php') && urlParams.get('action') === 'edit';\r\n\r\n if (page === 'squeeze-bulk' || isMediaNewPage || isAttachmentPage) {\r\n return __('Are you sure you want to leave this page? The squeezing process will be terminated!', 'squeeze');\r\n }\r\n if (isUploadPage) {\r\n return __('Are you sure you want to leave this page? The settings will not be saved!', 'squeeze');\r\n }\r\n};\r\n\r\nconst handleBulkPause = (data, currentPage) => {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(__('Bulk squeezing has been paused!', 'squeeze'), { isPause: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = data;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = currentPage;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target.disabled = false;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target, __('Resume bulk squeezing', 'squeeze'), '#play-button-round-icon');\r\n};\r\n\r\nconst handleUpdateChart = (uncompressedImagesCount) => {\r\n const chartValue = document.querySelector(\".squeeze-bulk-media-stats-chart-value > text\");\r\n const chartBar = document.querySelector(\".squeeze-bulk-media-stats-chart\");\r\n const squeezedImages = document.querySelector(\".squeeze-bulk-media-stats-item-value\");\r\n\r\n if (!chartValue || !chartBar) return;\r\n\r\n const imagesLeft = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages - uncompressedImagesCount;\r\n const percentage = parseFloat((imagesLeft / _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages) * 100).toFixed(2);\r\n const dasharray = percentage * 560 / 100;\r\n chartValue.textContent = `${percentage}%`;\r\n chartBar.style.setProperty('--squeeze-dasharray', dasharray);\r\n\r\n if (squeezedImages) {\r\n squeezedImages.textContent = `${imagesLeft} / ${_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages}`;\r\n }\r\n};\r\n\r\nconst handleRecursiveUpload = async (path, data, currentPage, isUpdateChart = false) => {\r\n\r\n if (!Array.isArray(data)) return { success: false, data: 'No data provided!', mediaIDs: [] }; // when bulk directory path has no images\r\n\r\n const totalPages = getTotalPages(path);\r\n\r\n if (data.length === 0) {\r\n currentPage += 1;\r\n if (currentPage > totalPages || !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId) return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n }\r\n }\r\n\r\n const initData = [...data]; // initial data\r\n\r\n const filename = data[0]?.filename ? data[0].filename : `ID #${data[0]}`;\r\n const mediaLogWrapper = await _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${__('Start squeezing...', 'squeeze')}`, { title: filename, isStart: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId = data[0] || 0; // update lastId to the last processed ID\r\n\r\n try {\r\n const response = await Squeeze.handleBulkUpload(path, data);\r\n\r\n //console.log('handleRecursiveUpload response', response);\r\n\r\n await logAndThumbnail(filename, response, mediaLogWrapper);\r\n\r\n if (isUpdateChart && path !== 'all') {\r\n let uncompressedImagesCount = 0;\r\n if (path === 'uncompressed') {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages - 1 || 0;\r\n uncompressedImagesCount = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages;\r\n } else if (path === 'path') {\r\n uncompressedImagesCount = response.mediaIDs.length;\r\n }\r\n handleUpdateChart(uncompressedImagesCount);\r\n }\r\n\r\n if (checkPaused(data, currentPage)) {\r\n return { success: false, data: 'Process has been paused!', mediaIDs: data, page: currentPage };\r\n }\r\n\r\n updateUI(initData[0], response);\r\n\r\n if (response.mediaIDs.length > 0) {\r\n return handleRecursiveUpload(path, response.mediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { ...response, page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${error}`, { mediaLogWrapper, iconId: 'ban-sign-icon' });\r\n\r\n if (data.length > 0) {\r\n return handleRecursiveUpload(path, data, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { success: false, data: error, mediaIDs: [], page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n\r\n/**\r\n * Handles the compression of image before upload using Squeeze.\r\n * It compresses only the original image, not the thumbnails.\r\n * \r\n * @param {object} up - The plupload instance\r\n * @param {object} pluploadFile - The file to be compressed\r\n * @param {object} compressOptions - The compression options object\r\n * @returns {boolean} - Returns false to prevent further processing of the file\r\n */\r\nconst handleCompressBeforeUpload = async (up, pluploadFile, compressOptions) => {\r\n if (typeof Squeeze === 'undefined') return;\r\n if (typeof Squeeze.compressBeforeUpload !== 'function') {\r\n console.warn('Squeeze.compressBeforeUpload is not a function');\r\n return;\r\n }\r\n \r\n if (pluploadFile?._isSqueezed || pluploadFile?._isExcluded || pluploadFile?._isFailed) {\r\n //console.warn('File is already compressed:', pluploadFile);\r\n return; // Skip files that are already compressed\r\n }\r\n // Check if the file is an image based on its MIME type\r\n if (!pluploadFile.type.startsWith('image/')) {\r\n //console.warn('File is not an image:', pluploadFile.name);\r\n return; // Skip non-image files\r\n }\r\n\r\n const file = pluploadFile.getNative() || pluploadFile.getSource();\r\n\r\n const type = file?.type?.split('/')[0] ?? '';\r\n const subtype = file?.type?.split('/')[1] ?? '';\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(type, subtype, compressOptions)) {\r\n //console.warn('Skipping compression for:', pluploadFile.name);\r\n return; // Skip compression for this file\r\n }\r\n\r\n //console.time('BeforeUpload')\r\n\r\n up.stop();\r\n window.onbeforeunload = handleOnLeave;\r\n \r\n \r\n\r\n try {\r\n let originalFile = file;\r\n const base64Obj = await Squeeze.compressBeforeUpload(file);\r\n if (!base64Obj || !base64Obj.base64) {\r\n console.warn('Compression skipped or failed for:', file.name);\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isFailed = true; // Mark the file as failed\r\n //window.onbeforeunload = null;\r\n setTimeout(() => up.start(), 0);\r\n return; // Skip further processing if compression failed or was skipped\r\n }\r\n \r\n const isDirectWebp = compressOptions?.direct_webp && file.type !== 'image/webp';\r\n const isBackupOriginal = compressOptions?.backup_original;\r\n\r\n if (isBackupOriginal) {\r\n // If backup original is enabled, convert the original file to WebP if it's not already\r\n if (isDirectWebp) {\r\n originalFile = await Squeeze.convertFileToWebp(file);\r\n } else {\r\n originalFile = file; // Keep the original file as is\r\n }\r\n pluploadFile.originalFile = originalFile; // Store the original file in the pluploadFile object\r\n }\r\n\r\n const compressedFile = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.base64ToFile(base64Obj.base64, file.name, file.type);\r\n const newSource = new mOxie.File(null, compressedFile);\r\n\r\n if (!newSource) {\r\n console.error('Failed to create new mOxie.File from base64 data');\r\n return; // Exit if newSource is not created\r\n }\r\n\r\n //console.log('Compressed file created:', newSource);\r\n\r\n // Override the file's getSource method to return the new compressed source\r\n pluploadFile.getSource = function () {\r\n return newSource;\r\n };\r\n\r\n // Reset status back to QUEUED\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isSqueezed = true; // Mark the file as compressed\r\n pluploadFile.base64 = base64Obj.base64; // Store the base64 data of the compressed image in the attachment\r\n pluploadFile.base64Webp = base64Obj?.base64Webp; // Store the WebP base64 data of the compressed image in the attachment\r\n \r\n // In the next tick, restart the queue\r\n setTimeout(() => up.start(), 0);\r\n\r\n //window.onbeforeunload = null;\r\n\r\n } catch (error) {\r\n console.error('Error during compression before upload:', error);\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isFailed = true; // Mark the file as failed\r\n setTimeout(() => up.start(), 0);\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nconst handleMultiFileFormUpload = (compressOptions) => {\r\n if (typeof wpUploaderInit === 'undefined' || typeof plupload === 'undefined' || typeof uploader === 'undefined') return;\r\n\r\n const SqueezeUploader = uploader;\r\n\r\n SqueezeUploader.bind('BeforeUpload', async function (up, pluploadFile) {\r\n handleCompressBeforeUpload(up, pluploadFile, compressOptions)\r\n });\r\n\r\n SqueezeUploader.bind('FileUploaded', function (up, file, response) {\r\n //console.log('FileUploaded', file, response);\r\n const fileMime = file.type;\r\n const fileType = fileMime.split('/')[0];\r\n const fileSubType = fileMime.split('/')[1];\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) return;\r\n\r\n /**\r\n * Wait for media item to load( 'async-upload.php' )\r\n * Ping every 1 second until the media item is loaded\r\n * @returns Promise\r\n */\r\n const waitForItemLoad = (addProgressBar = true) => {\r\n return new Promise((resolve) => {\r\n let interval = setInterval(() => {\r\n if (mediaItem.querySelector('.media-item-wrapper')) {\r\n if (addProgressBar) {\r\n mediaItem.querySelector('.media-item-wrapper').innerHTML += `\r\n <div class=\"progress\">\r\n <div class=\"percent\">${__('Squeezing...', 'squeeze')}</div>\r\n <div class=\"bar\" style=\"width: 200px;\"></div>\r\n </div>\r\n `;\r\n }\r\n clearInterval(interval);\r\n resolve();\r\n }\r\n }, 1000);\r\n });\r\n };\r\n\r\n const fileID = file.id;\r\n const attachmentID = response.response;\r\n const mediaItem = document.getElementById(`media-item-${fileID}`);\r\n\r\n if (file?._isExcluded) {\r\n console.warn('File is excluded from compression:', file.name);\r\n waitForItemLoad(false).then(() => {\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${__('File is excluded from compression:', 'squeeze')} ${file.name}</div>`;\r\n });\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n if (file?._isFailed) {\r\n console.warn('File compression failed:', file.name);\r\n waitForItemLoad(false).then(() => {\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${__('File compression failed:', 'squeeze')} ${file.name}</div>`;\r\n });\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n waitForItemLoad().then(() => {\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async function (data) {\r\n //console.log('Fetched attachment data:', data);\r\n const attachment = { attributes: data };\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.extendAttachment(attachment, file);\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n window.onbeforeunload = null;\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${uploadData?.data?.message}</div>`;\r\n mediaItem.querySelector('.progress')?.remove();\r\n } else {\r\n mediaItem.innerHTML += uploadData?.data?.message ?? uploadData?.data ?? uploadData;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n });\r\n}\r\n\r\n\n\n//# sourceURL=webpack:///./assets/js/handlers.js?"); 30 30 31 31 /***/ }), … … 37 37 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 38 38 39 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64SizeInBytes\": () => (/* binding */ base64SizeInBytes),\n/* harmony export */ \"base64ToBlob\": () => (/* binding */ base64ToBlob),\n/* harmony export */ \" cachedMediaData\": () => (/* binding */ cachedMediaData),\n/* harmony export */ \"disableAllButtons\": () => (/* binding */ disableAllButtons),\n/* harmony export */ \"disableBulkButtons\": () => (/* binding */ disableBulkButtons),\n/* harmony export */ \"elements\": () => (/* binding */ elements),\n/* harmony export */ \"humanFileSize\": () => (/* binding */ humanFileSize),\n/* harmony export */ \"isDocHidden\": () => (/* binding */ isDocHidden),\n/* harmony export */ \"logMessage\": () => (/* binding */ logMessage),\n/* harmony export */ \"maybeCompressAttachment\": () => (/* binding */ maybeCompressAttachment),\n/* harmony export */ \"populatePathInput\": () => (/* binding */ populatePathInput),\n/* harmony export */ \"removeAllButtons\": () => (/* binding */ removeAllButtons),\n/* harmony export */ \"renderDirectories\": () => (/* binding */ renderDirectories),\n/* harmony export */ \"renderTemplate\": () => (/* binding */ renderTemplate),\n/* harmony export */ \"restoreBulkButtons\": () => (/* binding */ restoreBulkButtons),\n/* harmony export */ \"updateButtonText\": () => (/* binding */ updateButtonText)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\n// move static helper functions here\r\nconst elements = {\r\n bulkBtn: document.querySelector(\"[name='squeeze_bulk']\"),\r\n bulkAgainBtn: document.querySelector(\"[name='squeeze_bulk_again']\"),\r\n bulkPathBtn: document.querySelector(\"[name='squeeze_bulk_path_button']\"),\r\n selectPathBtn: document.querySelector(\"[name='squeeze_select_path_button']\"),\r\n savePathBtn: document.querySelector(\"[name='squeeze_save_path_button']\"),\r\n pathDialog: document.getElementById(\"squeeze-path-dialog\"),\r\n closePathDialogBtn: document.querySelector(\"[name='squeeze_close_path_dialog_button']\"),\r\n pathInput: document.querySelector(\"[name='squeeze_bulk_path']\"),\r\n pathList: document.querySelector(\".squeeze-path-list\"),\r\n postsFilterForm: document.querySelector(\"#posts-filter\"),\r\n dirContainer: document.getElementById(\"squeeze-bulk-directory-list\"),\r\n bulkLogInput: document.querySelector(\"#squeeze-log-data\"),\r\n pauseBulkBtn: document.querySelector(\"[name='squeeze_pause_page_bulk']\")\r\n}\r\n\r\nconst cachedMediaData = {\r\n isPaused: false,\r\n page: 1,\r\n process: '',\r\n mediaIDs: [],\r\n lastId: 0,\r\n totalImages: document.querySelector(\"[name='squeeze_bulk_total_images']\")?.value || 0,\r\n uncompressedImages: document.querySelector(\"[name='squeeze_bulk_uncompressed_images']\")?.value || 0,\r\n target: null\r\n}\r\n\r\nconst loadTemplate = async (templatePath, data) => {\r\n const response = await fetch(templatePath);\r\n let template = await response.text();\r\n\r\n // Process sub-templates\r\n const subTemplateRegex = /\\{\\{\\>\\s*(.*?)\\s*\\}\\}/g;\r\n let match;\r\n while ((match = subTemplateRegex.exec(template)) !== null) {\r\n const subTemplatePath = `${squeezeOptions.templateBase}/${match[1].trim()}.html`;\r\n const subTemplate = await loadTemplate(subTemplatePath, data);\r\n template = template.replace(match[0], subTemplate);\r\n }\r\n\r\n // Function to safely evaluate conditions (supports boolean variables, expressions, AND/OR)\r\n const evaluateCondition = (condition, data) => {\r\n try {\r\n // Convert standalone boolean variables (e.g., webp_lossless) to data['webp_lossless']\r\n condition = condition.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match) =>\r\n match in data ? `data['${match}']` : match\r\n );\r\n\r\n return new Function(\"data\", `with(data) { return ${condition}; }`)(data);\r\n } catch (e) {\r\n console.error(\"Error evaluating condition:\", condition, e);\r\n return false;\r\n }\r\n };\r\n\r\n // Recursive function to process nested if-else conditions\r\n const processIfStatements = (template) => {\r\n return template.replace(/\\{\\{#if ([\\s\\S]*?)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g, (match, condition, content) => {\r\n condition = condition.trim();\r\n const conditionResult = evaluateCondition(condition, data);\r\n\r\n // Extract and split the if-else blocks\r\n const elseMatch = content.match(/\\{\\{#else\\}\\}([\\s\\S]*)/);\r\n const trueBlock = elseMatch ? content.replace(/\\{\\{#else\\}\\}([\\s\\S]*)/, \"\") : content;\r\n const falseBlock = elseMatch ? elseMatch[1] : \"\";\r\n\r\n // Process nested if statements recursively\r\n return processIfStatements(conditionResult ? trueBlock : falseBlock);\r\n });\r\n };\r\n\r\n // Apply recursive processing of if conditions\r\n template = processIfStatements(template);\r\n\r\n // Replace variables\r\n return template.replace(/\\{\\{(.*?)\\}\\}/g, (match, key) => data[key.trim()] || '');\r\n}\r\n\r\nconst renderTemplate = async (templatePath, data, target = null) => {\r\n const renderedHTML = await loadTemplate(templatePath, data);\r\n\r\n // Create a temporary container to parse HTML\r\n const tempContainer = document.createElement(\"template\");\r\n tempContainer.innerHTML = renderedHTML.trim();\r\n\r\n if (!target) {\r\n return tempContainer.content.firstChild;\r\n }\r\n\r\n target.appendChild(tempContainer.content.firstChild);\r\n\r\n // Return the last element of the rendered template\r\n return target.lastElementChild;\r\n}\r\n\r\nconst logMessage = async (msg, options = {}) => {\r\n const { mediaLogWrapper = null, isStart = false, isPause = false } = options;\r\n let { title = '', iconId = 'check-mark-circle-icon' } = options;\r\n\r\n if (!elements.bulkLogInput) return;\r\n\r\n if (isStart || isPause) {\r\n iconId = isPause ? 'pause-button-icon' : 'image-file-icon';\r\n title = isPause ? __('Bulk squeezing has been paused!', 'squeeze') : `${__('Media', 'squeeze')} ${title}:`;\r\n return await renderTemplate(squeezeOptions.templates.logWrapper, { title: title, msg: msg, iconId: iconId, isStart: isStart, isPause: isPause }, elements.bulkLogInput);\r\n } else {\r\n if (mediaLogWrapper) {\r\n const process = mediaLogWrapper.querySelector(\".media-log-process\");\r\n const step = await renderTemplate(squeezeOptions.templates.logStep, { msg: msg, iconId: iconId }, process);\r\n\r\n if (msg.includes('squeeze-comparison-table')) {\r\n const comparisonTable = step.querySelector('.squeeze-comparison-table');\r\n const toggleBtn = await renderTemplate(squeezeOptions.templates.logDetailsButton, { buttonText: __('Show details', 'squeeze') }, mediaLogWrapper);\r\n\r\n toggleBtn.addEventListener(\"click\", () => {\r\n comparisonTable.classList.toggle(\"show\");\r\n toggleBtn.textContent = comparisonTable.classList.contains(\"show\") ? __('Hide details', 'squeeze') : __('Show details', 'squeeze');\r\n });\r\n step.closest(\".media-log-wrapper\").appendChild(comparisonTable);\r\n step.closest(\".media-log-wrapper\").appendChild(toggleBtn);\r\n }\r\n } else {\r\n elements.bulkLogInput.innerHTML += msg + `<br>`;\r\n }\r\n }\r\n}\r\n\r\nconst restoreBulkButtons = () => {\r\n elements.bulkBtn.disabled = false;\r\n elements.bulkAgainBtn.disabled = false;\r\n elements.bulkPathBtn.disabled = false;\r\n elements.selectPathBtn.disabled = false;\r\n updateButtonText(elements.bulkBtn, __('Run Bulk Squeeze', 'squeeze'), '#play-button-round-icon');\r\n updateButtonText(elements.bulkAgainBtn, __('Repeat Bulk Squeeze', 'squeeze'), '#combine-left-right-outline-icon');\r\n updateButtonText(elements.bulkPathBtn, __('Run Directory Squeeze', 'squeeze'), '#play-button-round-icon');\r\n elements.bulkBtn.dataset.running = 'false';\r\n elements.bulkAgainBtn.dataset.running = 'false';\r\n elements.bulkPathBtn.dataset.running = 'false';\r\n\r\n cachedMediaData.process = '';\r\n cachedMediaData.mediaIDs = [];\r\n cachedMediaData.page = 1;\r\n}\r\n\r\nconst disableBulkButtons = () => {\r\n elements.bulkBtn.disabled = true;\r\n elements.bulkAgainBtn.disabled = true;\r\n elements.bulkPathBtn.disabled = true;\r\n elements.selectPathBtn.disabled = true;\r\n}\r\n\r\nconst disableAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst removeAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.remove());\r\n}\r\n\r\nconst updateButtonText = (button, text, svgAnchor = false) => {\r\n button.childNodes.forEach((node) => {\r\n if (node.nodeName === '#text' && node.textContent.trim() !== '') {\r\n node.textContent = text;\r\n }\r\n if (svgAnchor && node.nodeName === 'svg') {\r\n node.querySelector('use').setAttribute('xlink:href', svgAnchor);\r\n }\r\n });\r\n}\r\n\r\n// Function to render directories in the dialog\r\nconst renderDirectories = async (dirs, parentDir = null, listeners = {}) => {\r\n if (!dirs) return;\r\n if (typeof dirs === 'object') dirs = Object.values(dirs);\r\n if (!elements.dirContainer.classList.contains(\"loaded\")) elements.dirContainer.innerHTML = \"\";\r\n\r\n if (dirs.length === 0 && !parentDir) {\r\n const listItem = await renderTemplate(squeezeOptions.templates.directoryItemEmpty, { emptyText: __('No directories found!', 'squeeze') }, elements.dirContainer);\r\n return;\r\n }\r\n\r\n const selectedFolders = JSON.parse(elements.pathInput.value);\r\n let target;\r\n\r\n for (const dir of dirs) {\r\n const listItemClasses = [];\r\n\r\n if (dir.parent === '/') {\r\n listItemClasses.push(\"loaded\", \"opened\");\r\n }\r\n\r\n if (parentDir) {\r\n target = parentDir;\r\n } else if (dir.parent) {\r\n const parentElement = elements.dirContainer.querySelector(`[data-path=\"${dir.parent}\"]`);\r\n if (parentElement) {\r\n target = parentElement;\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n\r\n const listItem = await renderTemplate(\r\n squeezeOptions.templates.directoryItem,\r\n {\r\n parent: dir.parent,\r\n path: dir.path,\r\n label: dir.name,\r\n classes: listItemClasses.join(\" \"),\r\n isWritable: dir.is_writeable && !(Array.isArray(selectedFolders) && selectedFolders.includes(dir.path)),\r\n isChecked: dir.is_writeable && Array.isArray(selectedFolders) && selectedFolders.includes(dir.path),\r\n },\r\n target\r\n )\r\n\r\n listItem.querySelector(\"label\").addEventListener(\"click\", listeners.handleDirectoryClick);\r\n listItem.querySelector(\"input[type='checkbox']\")?.addEventListener(\"change\", listeners.handleDirectoryCheck);\r\n }\r\n\r\n elements.dirContainer.classList.add(\"loaded\");\r\n}\r\n\r\nconst populatePathInput = async () => {\r\n const path = elements.pathInput.value;\r\n if (!path) return;\r\n\r\n try {\r\n const selectedFolders = JSON.parse(path);\r\n const inputs = elements.pathList.querySelectorAll(\".squeeze-path-list__item\");\r\n\r\n inputs.forEach(input => input.remove());\r\n\r\n for (const folder of selectedFolders) {\r\n const input = await renderTemplate(squeezeOptions.templates.pathListItem, { folder: folder }, elements.pathList);\r\n }\r\n } catch (error) {\r\n alert(__('Error parsing path input!', 'squeeze'));\r\n console.error('Error parsing path input:', error);\r\n }\r\n}\r\n\r\nconst getHiddenProp = () => {\r\n var prefixes = ['webkit', 'moz', 'ms', 'o'];\r\n\r\n // if 'hidden' is natively supported just return it\r\n if ('hidden' in document) return 'hidden';\r\n\r\n // otherwise loop over all the known prefixes until we find one\r\n for (let i = 0; i < prefixes.length; i++) {\r\n if ((prefixes[i] + 'Hidden') in document)\r\n return prefixes[i] + 'Hidden';\r\n }\r\n\r\n // otherwise it's not supported\r\n return null;\r\n}\r\n\r\nconst isDocHidden = () => {\r\n const prop = getHiddenProp();\r\n if (!prop) return false;\r\n\r\n return document[prop];\r\n}\r\n\r\n/**\r\n * @see https://stackoverflow.com/a/20732091\r\n */\r\nconst humanFileSize = (size) => {\r\n let i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));\r\n return +((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];\r\n}\r\n\r\nconst base64SizeInBytes = (base64) => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64; \r\n\r\n // Calculate padding characters ('=' at the end of Base64)\r\n const padding = (base64String.match(/=+$/) || [\"\"])[0].length;\r\n\r\n // Compute byte size\r\n return (base64String.length * 3) / 4 - padding;\r\n}\r\n\r\nconst maybeCompressAttachment = (attachmentType, attachmentSubType, compressOptions) => {\r\n const isAutoCompress = compressOptions.auto_compress;\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType);\r\n\r\n return isImage && isAutoCompress;\r\n};\r\n\r\nconst base64ToBlob = (base64, type = 'image/jpeg') => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64;\r\n\r\n // Decode Base64 string\r\n const byteCharacters = atob(base64String);\r\n const byteNumbers = new Array(byteCharacters.length);\r\n \r\n for (let i = 0; i < byteCharacters.length; i++) {\r\n byteNumbers[i] = byteCharacters.charCodeAt(i);\r\n }\r\n\r\n const byteArray = new Uint8Array(byteNumbers);\r\n return new Blob([byteArray], { type: type });\r\n}\n\n//# sourceURL=webpack:///./assets/js/helpers.js?");39 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64SizeInBytes\": () => (/* binding */ base64SizeInBytes),\n/* harmony export */ \"base64ToBlob\": () => (/* binding */ base64ToBlob),\n/* harmony export */ \"base64ToFile\": () => (/* binding */ base64ToFile),\n/* harmony export */ \"cachedMediaData\": () => (/* binding */ cachedMediaData),\n/* harmony export */ \"disableAllButtons\": () => (/* binding */ disableAllButtons),\n/* harmony export */ \"disableBulkButtons\": () => (/* binding */ disableBulkButtons),\n/* harmony export */ \"elements\": () => (/* binding */ elements),\n/* harmony export */ \"extendAttachment\": () => (/* binding */ extendAttachment),\n/* harmony export */ \"fileToBase64\": () => (/* binding */ fileToBase64),\n/* harmony export */ \"getFileFromUrl\": () => (/* binding */ getFileFromUrl),\n/* harmony export */ \"handleRemovePathButton\": () => (/* binding */ handleRemovePathButton),\n/* harmony export */ \"humanFileSize\": () => (/* binding */ humanFileSize),\n/* harmony export */ \"isDocHidden\": () => (/* binding */ isDocHidden),\n/* harmony export */ \"logMessage\": () => (/* binding */ logMessage),\n/* harmony export */ \"maybeCompressAttachment\": () => (/* binding */ maybeCompressAttachment),\n/* harmony export */ \"objectToFormData\": () => (/* binding */ objectToFormData),\n/* harmony export */ \"populatePathInput\": () => (/* binding */ populatePathInput),\n/* harmony export */ \"removeAllButtons\": () => (/* binding */ removeAllButtons),\n/* harmony export */ \"renderDirectories\": () => (/* binding */ renderDirectories),\n/* harmony export */ \"renderTemplate\": () => (/* binding */ renderTemplate),\n/* harmony export */ \"restoreBulkButtons\": () => (/* binding */ restoreBulkButtons),\n/* harmony export */ \"updateButtonText\": () => (/* binding */ updateButtonText)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\n// move static helper functions here\r\nconst elements = {\r\n bulkBtn: document.querySelector(\"[name='squeeze_bulk']\"),\r\n bulkAgainBtn: document.querySelector(\"[name='squeeze_bulk_again']\"),\r\n bulkPathBtn: document.querySelector(\"[name='squeeze_bulk_path_button']\"),\r\n bulkPathRemoveBtns: document.querySelectorAll(\".squeeze-path-list__remove\"),\r\n selectPathBtn: document.querySelector(\"[name='squeeze_select_path_button']\"),\r\n savePathBtn: document.querySelector(\"[name='squeeze_save_path_button']\"),\r\n pathDialog: document.getElementById(\"squeeze-path-dialog\"),\r\n closePathDialogBtn: document.querySelector(\"[name='squeeze_close_path_dialog_button']\"),\r\n pathInput: document.querySelector(\"[name='squeeze_bulk_path']\"),\r\n pathList: document.querySelector(\".squeeze-path-list\"),\r\n postsFilterForm: document.querySelector(\"#posts-filter\"),\r\n dirContainer: document.getElementById(\"squeeze-bulk-directory-list\"),\r\n bulkLogInput: document.querySelector(\"#squeeze-log-data\"),\r\n pauseBulkBtn: document.querySelector(\"[name='squeeze_pause_page_bulk']\")\r\n}\r\n\r\nconst cachedMediaData = {\r\n isPaused: false,\r\n page: 1,\r\n process: '',\r\n mediaIDs: [],\r\n lastId: 0,\r\n totalImages: document.querySelector(\"[name='squeeze_bulk_total_images']\")?.value || 0,\r\n uncompressedImages: document.querySelector(\"[name='squeeze_bulk_uncompressed_images']\")?.value || 0,\r\n target: null\r\n}\r\n\r\nconst loadTemplate = async (templatePath, data) => {\r\n const response = await fetch(templatePath);\r\n let template = await response.text();\r\n\r\n // Process sub-templates\r\n const subTemplateRegex = /\\{\\{\\>\\s*(.*?)\\s*\\}\\}/g;\r\n let match;\r\n while ((match = subTemplateRegex.exec(template)) !== null) {\r\n const subTemplatePath = `${squeezeOptions.templateBase}/${match[1].trim()}.html`;\r\n const subTemplate = await loadTemplate(subTemplatePath, data);\r\n template = template.replace(match[0], subTemplate);\r\n }\r\n\r\n // Function to safely evaluate conditions (supports boolean variables, expressions, AND/OR)\r\n const evaluateCondition = (condition, data) => {\r\n try {\r\n // Convert standalone boolean variables (e.g., webp_lossless) to data['webp_lossless']\r\n condition = condition.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match) =>\r\n match in data ? `data['${match}']` : match\r\n );\r\n\r\n return new Function(\"data\", `with(data) { return ${condition}; }`)(data);\r\n } catch (e) {\r\n console.error(\"Error evaluating condition:\", condition, e);\r\n return false;\r\n }\r\n };\r\n\r\n // Recursive function to process nested if-else conditions\r\n const processIfStatements = (template) => {\r\n return template.replace(/\\{\\{#if ([\\s\\S]*?)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g, (match, condition, content) => {\r\n condition = condition.trim();\r\n const conditionResult = evaluateCondition(condition, data);\r\n\r\n // Extract and split the if-else blocks\r\n const elseMatch = content.match(/\\{\\{#else\\}\\}([\\s\\S]*)/);\r\n const trueBlock = elseMatch ? content.replace(/\\{\\{#else\\}\\}([\\s\\S]*)/, \"\") : content;\r\n const falseBlock = elseMatch ? elseMatch[1] : \"\";\r\n\r\n // Process nested if statements recursively\r\n return processIfStatements(conditionResult ? trueBlock : falseBlock);\r\n });\r\n };\r\n\r\n // Apply recursive processing of if conditions\r\n template = processIfStatements(template);\r\n\r\n // Replace variables\r\n return template.replace(/\\{\\{(.*?)\\}\\}/g, (match, key) => data[key.trim()] || '');\r\n}\r\n\r\nconst renderTemplate = async (templatePath, data, target = null) => {\r\n const renderedHTML = await loadTemplate(templatePath, data);\r\n\r\n // Create a temporary container to parse HTML\r\n const tempContainer = document.createElement(\"template\");\r\n tempContainer.innerHTML = renderedHTML.trim();\r\n\r\n if (!target) {\r\n return tempContainer.content.firstChild;\r\n }\r\n\r\n target.appendChild(tempContainer.content.firstChild);\r\n\r\n // Return the last element of the rendered template\r\n return target.lastElementChild;\r\n}\r\n\r\nconst logMessage = async (msg, options = {}) => {\r\n const { mediaLogWrapper = null, isStart = false, isPause = false } = options;\r\n let { title = '', iconId = 'check-mark-circle-icon' } = options;\r\n\r\n if (!elements.bulkLogInput) return;\r\n\r\n if (isStart || isPause) {\r\n iconId = isPause ? 'pause-button-icon' : 'image-file-icon';\r\n title = isPause ? __('Bulk squeezing has been paused!', 'squeeze') : `${__('Media', 'squeeze')} ${title}:`;\r\n return await renderTemplate(squeezeOptions.templates.logWrapper, { title: title, msg: msg, iconId: iconId, isStart: isStart, isPause: isPause }, elements.bulkLogInput);\r\n } else {\r\n if (mediaLogWrapper) {\r\n const process = mediaLogWrapper.querySelector(\".media-log-process\");\r\n const step = await renderTemplate(squeezeOptions.templates.logStep, { msg: msg, iconId: iconId }, process);\r\n\r\n if (msg && msg.includes('squeeze-comparison-table')) {\r\n const comparisonTable = step.querySelector('.squeeze-comparison-table');\r\n const toggleBtn = await renderTemplate(squeezeOptions.templates.logDetailsButton, { buttonText: __('Show details', 'squeeze') }, mediaLogWrapper);\r\n\r\n toggleBtn.addEventListener(\"click\", () => {\r\n comparisonTable.classList.toggle(\"show\");\r\n toggleBtn.textContent = comparisonTable.classList.contains(\"show\") ? __('Hide details', 'squeeze') : __('Show details', 'squeeze');\r\n });\r\n step.closest(\".media-log-wrapper\").appendChild(comparisonTable);\r\n step.closest(\".media-log-wrapper\").appendChild(toggleBtn);\r\n }\r\n } else {\r\n elements.bulkLogInput.innerHTML += msg + `<br>`;\r\n }\r\n }\r\n}\r\n\r\nconst restoreBulkButtons = () => {\r\n elements.bulkBtn.disabled = false;\r\n elements.bulkAgainBtn.disabled = false;\r\n elements.bulkPathBtn.disabled = false;\r\n elements.selectPathBtn.disabled = false;\r\n updateButtonText(elements.bulkBtn, __('Run Bulk Squeeze', 'squeeze'), '#play-button-round-icon');\r\n updateButtonText(elements.bulkAgainBtn, __('Repeat Bulk Squeeze', 'squeeze'), '#combine-left-right-outline-icon');\r\n updateButtonText(elements.bulkPathBtn, __('Run Directory Squeeze', 'squeeze'), '#play-button-round-icon');\r\n elements.bulkBtn.dataset.running = 'false';\r\n elements.bulkAgainBtn.dataset.running = 'false';\r\n elements.bulkPathBtn.dataset.running = 'false';\r\n elements.bulkPathRemoveBtns?.forEach((btn) => {\r\n btn.disabled = false;\r\n });\r\n\r\n cachedMediaData.process = '';\r\n cachedMediaData.mediaIDs = [];\r\n cachedMediaData.page = 1;\r\n}\r\n\r\nconst disableBulkButtons = () => {\r\n elements.bulkBtn.disabled = true;\r\n elements.bulkAgainBtn.disabled = true;\r\n elements.bulkPathBtn.disabled = true;\r\n elements.selectPathBtn.disabled = true;\r\n elements.bulkPathRemoveBtns?.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst disableAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst removeAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.remove());\r\n}\r\n\r\nconst updateButtonText = (button, text, svgAnchor = false) => {\r\n button.childNodes.forEach((node) => {\r\n if (node.nodeName === '#text' && node.textContent.trim() !== '') {\r\n node.textContent = text;\r\n }\r\n if (svgAnchor && node.nodeName === 'svg') {\r\n node.querySelector('use').setAttribute('xlink:href', svgAnchor);\r\n }\r\n });\r\n}\r\n\r\n// Function to render directories in the dialog\r\nconst renderDirectories = async (dirs, parentDir = null, listeners = {}) => {\r\n if (!dirs) return;\r\n if (typeof dirs === 'object') dirs = Object.values(dirs);\r\n if (!elements.dirContainer.classList.contains(\"loaded\")) elements.dirContainer.innerHTML = \"\";\r\n\r\n if (dirs.length === 0 && !parentDir) {\r\n const listItem = await renderTemplate(squeezeOptions.templates.directoryItemEmpty, { emptyText: __('No directories found!', 'squeeze') }, elements.dirContainer);\r\n return;\r\n }\r\n\r\n const selectedFolders = JSON.parse(elements.pathInput.value);\r\n let target;\r\n\r\n for (const dir of dirs) {\r\n const listItemClasses = [];\r\n\r\n if (dir.parent === '/') {\r\n listItemClasses.push(\"loaded\", \"opened\");\r\n }\r\n\r\n if (parentDir) {\r\n target = parentDir;\r\n } else if (dir.parent) {\r\n const parentElement = elements.dirContainer.querySelector(`[data-path=\"${dir.parent}\"]`);\r\n if (parentElement) {\r\n target = parentElement;\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n\r\n const listItem = await renderTemplate(\r\n squeezeOptions.templates.directoryItem,\r\n {\r\n parent: dir.parent,\r\n path: dir.path,\r\n label: dir.name,\r\n classes: listItemClasses.join(\" \"),\r\n isWritable: dir.is_writeable && !(Array.isArray(selectedFolders) && selectedFolders.includes(dir.path)),\r\n isChecked: dir.is_writeable && Array.isArray(selectedFolders) && selectedFolders.includes(dir.path),\r\n },\r\n target\r\n )\r\n\r\n listItem.querySelector(\"label\").addEventListener(\"click\", listeners.handleDirectoryClick);\r\n listItem.querySelector(\"input[type='checkbox']\")?.addEventListener(\"change\", listeners.handleDirectoryCheck);\r\n }\r\n\r\n elements.dirContainer.classList.add(\"loaded\");\r\n}\r\n\r\nconst handleRemovePathButton = (e) => {\r\n e.preventDefault();\r\n const item = e.target.closest(\".squeeze-path-list__item\");\r\n if (item) {\r\n item.remove();\r\n const currentPaths = Array.from(elements.pathList.querySelectorAll(\".squeeze-path-list__input\"))\r\n .map(input => input.value.trim())\r\n .filter(value => value !== '');\r\n elements.pathInput.value = JSON.stringify(currentPaths);\r\n }\r\n}\r\n\r\nconst populatePathInput = async () => {\r\n const path = elements.pathInput.value;\r\n if (!path) return;\r\n\r\n try {\r\n const selectedFolders = JSON.parse(path);\r\n const items = elements.pathList.querySelectorAll(\".squeeze-path-list__item\");\r\n\r\n items.forEach(item => item.remove());\r\n\r\n for (const folder of selectedFolders) {\r\n const item = await renderTemplate(squeezeOptions.templates.pathListItem, { folder: folder }, elements.pathList);\r\n const removeButton = item.querySelector(\".squeeze-path-list__remove\");\r\n removeButton.addEventListener(\"click\", handleRemovePathButton);\r\n\r\n }\r\n } catch (error) {\r\n alert(__('Error parsing path input!', 'squeeze'));\r\n console.error('Error parsing path input:', error);\r\n }\r\n}\r\n\r\nconst getHiddenProp = () => {\r\n var prefixes = ['webkit', 'moz', 'ms', 'o'];\r\n\r\n // if 'hidden' is natively supported just return it\r\n if ('hidden' in document) return 'hidden';\r\n\r\n // otherwise loop over all the known prefixes until we find one\r\n for (let i = 0; i < prefixes.length; i++) {\r\n if ((prefixes[i] + 'Hidden') in document)\r\n return prefixes[i] + 'Hidden';\r\n }\r\n\r\n // otherwise it's not supported\r\n return null;\r\n}\r\n\r\nconst isDocHidden = () => {\r\n const prop = getHiddenProp();\r\n if (!prop) return false;\r\n\r\n return document[prop];\r\n}\r\n\r\n/**\r\n * @see https://stackoverflow.com/a/20732091\r\n */\r\nconst humanFileSize = (size) => {\r\n let i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));\r\n return +((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];\r\n}\r\n\r\nconst base64SizeInBytes = (base64) => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64; \r\n\r\n // Calculate padding characters ('=' at the end of Base64)\r\n const padding = (base64String.match(/=+$/) || [\"\"])[0].length;\r\n\r\n // Compute byte size\r\n return (base64String.length * 3) / 4 - padding;\r\n}\r\n\r\nconst maybeCompressAttachment = (attachmentType, attachmentSubType, compressOptions = null) => {\r\n const isAutoCompress = compressOptions?.auto_compress ?? true;\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType);\r\n\r\n return isImage && isAutoCompress;\r\n};\r\n\r\nconst base64ToBlob = (base64, type = 'image/jpeg') => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64;\r\n\r\n // Decode Base64 string\r\n const byteCharacters = atob(base64String);\r\n const byteNumbers = new Array(byteCharacters.length);\r\n \r\n for (let i = 0; i < byteCharacters.length; i++) {\r\n byteNumbers[i] = byteCharacters.charCodeAt(i);\r\n }\r\n\r\n const byteArray = new Uint8Array(byteNumbers);\r\n return new Blob([byteArray], { type: type });\r\n}\r\n\r\nconst base64ToFile = (base64, fileName = 'image.jpg', type = 'image/jpeg') => {\r\n const blob = base64ToBlob(base64, type);\r\n return new File([blob], fileName, { type: type });\r\n}\r\n\r\nconst fileToBase64 = (file) => {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = () => resolve(reader.result);\r\n reader.onerror = (error) => reject(error);\r\n reader.readAsDataURL(file);\r\n });\r\n}\r\n\r\nfunction objectToFormData(obj, fd = null, parentKey = null) {\r\n const formData = fd || new FormData();\r\n\r\n for (const key in obj) {\r\n if (!obj.hasOwnProperty(key)) continue;\r\n const value = obj[key];\r\n\r\n // build the form key: either \"foo\", \"parent[foo]\" or \"parent[]\" for arrays\r\n const formKey = parentKey\r\n ? Array.isArray(obj)\r\n ? `${parentKey}[]`\r\n : `${parentKey}[${key}]`\r\n : key;\r\n\r\n // Files or Blobs go straight in\r\n if (value instanceof File || value instanceof Blob) {\r\n formData.append(formKey, value, value.name);\r\n }\r\n // Arrays: recurse so they become key[]=val0, key[]=val1…\r\n else if (Array.isArray(value)) {\r\n objectToFormData(value, formData, formKey);\r\n }\r\n // Plain objects: recurse so they become key[subkey]=subval\r\n else if (\r\n value !== null &&\r\n typeof value === 'object' &&\r\n !(value instanceof Date)\r\n ) {\r\n objectToFormData(value, formData, formKey);\r\n }\r\n // Dates: convert to ISO string (or format as you like)\r\n else if (value instanceof Date) {\r\n formData.append(formKey, value.toISOString());\r\n }\r\n // Everything else (number, string, boolean, null, undefined)\r\n else {\r\n // Explicitly convert undefined to empty string so PHP sees it\r\n const stringVal =\r\n value === undefined || value === null ? '' : String(value);\r\n formData.append(formKey, stringVal);\r\n }\r\n }\r\n\r\n return formData;\r\n}\r\n\r\n/**\r\n * Extend the attachment object with additional data from the file.\r\n * @param {object} attachment \r\n * @param {object} file \r\n * @returns {object} — the extended attachment object.\r\n */\r\nconst extendAttachment = async (attachment, file) => {\r\n if (typeof attachment !== 'object' || !attachment.attributes) {\r\n console.warn('Invalid attachment object:', attachment);\r\n return;\r\n }\r\n\r\n const attributes = attachment.attributes;\r\n\r\n if (file?.base64) {\r\n attributes.base64Compressed = file.base64; // Use the base64 data from the attachment\r\n }\r\n\r\n if (file?.base64Webp) {\r\n attributes.base64WebpCompressed = file.base64Webp; // Use the WebP base64 data from the attachment\r\n }\r\n\r\n if (file?.originalFile) {\r\n attributes.originalFile = file.originalFile; // Use the original file from the attachment to be able to create a backup\r\n }\r\n\r\n return attachment;\r\n}\r\n\r\nconst getFileFromUrl = async (url, filename, format) => {\r\n const response = await fetch(url);\r\n const blob = await response.blob();\r\n const mimeType = format ? `image/${format}` : blob.type;\r\n return new File([blob], filename, { type: mimeType });\r\n}\n\n//# sourceURL=webpack:///./assets/js/helpers.js?"); 40 40 41 41 /***/ }), … … 47 47 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 48 48 49 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SQUEEZE)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nclass SQUEEZE {\r\n\r\n constructor(squeeze) {\r\n this.options = JSON.parse(squeeze.options); // plugin options\r\n this.nonce = squeeze.nonce; // nonce\r\n this.ajaxUrl = squeeze.ajaxUrl; // ajax url\r\n this.timeout = parseInt(this.options.timeout) * 1000; // convert to milliseconds\r\n this.poolSize = navigator.hardwareConcurrency || 1; // number of threads\r\n }\r\n\r\n handleCompress = async ( attachment ) => {\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const name = attachmentData.name;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const sizes = attachmentData.sizes;\r\n const format = mime.split(\"/\")[1];\r\n const sourceType = format;\r\n const outputType = format;\r\n const skipFull = attachmentData.originalImageName === undefined ? true : false;\r\n const timeout = this.timeout;\r\n const isPreview = attachmentData?.isPreview ?? false;\r\n const file = attachmentData?.file ?? null;\r\n\r\n //console.log(attachmentData, 'attachmentData')\r\n\r\n const worker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(\"assets_js_worker_js\"), __webpack_require__.b), {type: undefined}); // worker url\r\n worker.postMessage({\r\n action: 'compress',\r\n format,\r\n url,\r\n name,\r\n sourceType,\r\n outputType,\r\n mime,\r\n sizes,\r\n skipFull,\r\n timeout,\r\n isPreview,\r\n file,\r\n options: this.options,\r\n //urlOriginal: urlOriginal,\r\n });\r\n\r\n return new Promise((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n worker.terminate();\r\n console.warn('Worker terminated');\r\n reject(__('Request timed out.', 'squeeze'));\r\n }, timeout);\r\n\r\n worker.onmessage = (event) => {\r\n clearTimeout(timeoutId);\r\n if (event.data.error) {\r\n reject(event.data.error);\r\n } else {\r\n resolve(event.data);\r\n }\r\n worker.terminate();\r\n };\r\n\r\n worker.onerror = (error) => {\r\n clearTimeout(timeoutId);\r\n reject(`Worker error: ${error.message}`);\r\n };\r\n });\r\n\r\n }\r\n\r\n handleUpload = async ({ attachment, base64, type = 'uncompressed', mediaIDs = [] }) => {\r\n\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const format = mime.split(\"/\")[1];\r\n const sizes = attachmentData.sizes;\r\n\r\n //console.log(attachmentData, 'attachmentData')\r\n\r\n const data = {\r\n action: 'squeeze_update_attachment',\r\n _ajax_nonce: this.nonce,\r\n filename: filename,\r\n type: 'image',\r\n format: format,\r\n base64: base64.base64,\r\n base64Sizes: base64.base64Sizes,\r\n base64Webp: base64.base64Webp,\r\n base64SizesWebp: base64.base64SizesWebp,\r\n attachmentID: attachmentID,\r\n url: url,\r\n process: type,\r\n }\r\n\r\n console.log(data, 'squeeze_update_attachment') \r\n\r\n try {\r\n const uploadResponse = await jQuery.ajax({\r\n url: this.ajaxUrl, // + '111',\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n //if (type === 'uncompressed' || type === 'all' || type === 'path') {\r\n //if (uploadResponse.success) {\r\n uploadResponse['mediaIDs'] = mediaIDs;\r\n //}\r\n\r\n uploadResponse['filename'] = filename;\r\n uploadResponse['url'] = url;\r\n uploadResponse['sizes'] = sizes;\r\n\r\n return uploadResponse;\r\n \r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n };\r\n }\r\n\r\n }\r\n\r\n handleBulkUpload = async (type = 'uncompressed', mediaIDs = []) => {\r\n let currentID;\r\n let attachment;\r\n\r\n switch (type) {\r\n case 'all':\r\n case 'uncompressed':\r\n currentID = mediaIDs[0];\r\n break;\r\n case 'path':\r\n currentID = mediaIDs[0]?.filename;\r\n break;\r\n default:\r\n currentID = 0;\r\n break;\r\n }\r\n\r\n if (type === 'path') {\r\n\r\n \r\n\r\n attachment = {\r\n attributes: {\r\n url: mediaIDs[0].url,\r\n mime: mediaIDs[0].mime,\r\n name: mediaIDs[0].name,\r\n filename: mediaIDs[0].filename,\r\n id: mediaIDs[0].id,\r\n sizes: mediaIDs[0]?.sizes,\r\n }\r\n }\r\n\r\n } else {\r\n\r\n const attachmentResponse = await this.getAttachment(currentID); \r\n if (attachmentResponse.success === false) {\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': attachmentResponse.data\r\n }\r\n }\r\n const attachmentData = attachmentResponse.data;\r\n attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n\r\n }\r\n\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n\r\n const mediaType = attachment.attributes.mime.split(\"/\")[0];\r\n const mediaSubType = attachment.attributes.mime.split(\"/\")[1];\r\n\r\n if (!this.maybeCompressAttachment(mediaType, mediaSubType)) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': __('Skipped', 'squeeze')\r\n }\r\n }\r\n\r\n try {\r\n const compressData = await this.handleCompress( attachment );\r\n const uploadData = await this.handleUpload({ attachment: attachment, base64: compressData, type: type, mediaIDs: mediaIDs })\r\n\r\n return uploadData;\r\n\r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n }\r\n }\r\n\r\n }\r\n\r\n maybeCompressAttachment = (attachmentType, attachmentSubType) => {\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType)\r\n\r\n if (isImage) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n \r\n\r\n handleRestore = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_restore_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n };\r\n\r\n const response = await jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n };\r\n\r\n // Get list of attachments by path\r\n getAttachmentsByPath = async (path) => {\r\n\r\n const data = {\r\n action: 'squeeze_get_attachment_by_path',\r\n path: path,\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getAttachment = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_get_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getNextAttachments = async (page = 1, type = 'uncompressed', lastId = 0) => {\r\n const data = {\r\n action: 'squeeze_get_next_attachments',\r\n _ajax_nonce: this.nonce,\r\n page: page,\r\n type: type,\r\n lastId: lastId,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getDirectories = async (parentDir = false) => {\r\n const data = {\r\n action: 'squeeze_get_directories',\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n if (parentDir) {\r\n data['parentDir'] = parentDir;\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n \r\n\r\n setOptions = async (options) => {\r\n const data = {\r\n action: 'squeeze_set_options',\r\n _ajax_nonce: this.nonce,\r\n options: options,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /*\r\n getSizesFromFile = (file) => {\r\n if (!file) return;\r\n\r\n // get list of thumbnails from file\r\n const sizes = {};\r\n \r\n const fd = new FormData();\r\n fd.append('action', 'squeeze_get_sizes_from_file');\r\n fd.append('_ajax_nonce', this.nonce);\r\n fd.append('file', file);\r\n\r\n jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: fd,\r\n processData: false,\r\n contentType: false,\r\n async: false, // synchronous request\r\n }).done((response) => {\r\n console.log(response, 'getSizesFromFile response');\r\n if (response.success) {\r\n Object.keys(response.data).forEach((size) => {\r\n sizes[size] = response.data[size];\r\n });\r\n } else {\r\n console.error('Error getting sizes from file:', response.data);\r\n }\r\n }).fail((error) => {\r\n console.error('AJAX error:', error);\r\n });\r\n\r\n return sizes;\r\n\r\n }\r\n */\r\n\r\n}\n\n//# sourceURL=webpack:///./assets/js/squeeze.js?"); 49 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SQUEEZE)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var browser_image_compression__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! browser-image-compression */ \"./node_modules/browser-image-compression/dist/browser-image-compression.mjs\");\n/* harmony import */ var _jsquash_webp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @jsquash/webp */ \"./node_modules/@jsquash/webp/encode.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nclass SQUEEZE {\r\n\r\n constructor(squeeze) {\r\n this.options = JSON.parse(squeeze.options); // plugin options\r\n this.nonce = squeeze.nonce; // nonce\r\n this.ajaxUrl = squeeze.ajaxUrl; // ajax url\r\n this.timeout = parseInt(this.options.timeout) * 1000; // convert to milliseconds\r\n this.poolSize = navigator.hardwareConcurrency || 1; // number of threads\r\n }\r\n\r\n handleCompress = async ( attachment, type = 'uncompressed' ) => {\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const name = attachmentData.name;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const sizes = attachmentData.sizes;\r\n const format = mime.split(\"/\")[1];\r\n const sourceType = format;\r\n const outputType = format;\r\n const skipFull = attachmentData?.skipFull ?? attachmentData.originalImageName === undefined ? true : false;\r\n const timeout = this.timeout;\r\n const isPreview = attachmentData?.isPreview ?? false;\r\n const file = attachmentData?.file ?? null; // the original file, it passed for the newly uploaded attachment to compress it\r\n\r\n // the original compressed image base64, it passed when the attachment was already compressed and we need to compress thumbs only\r\n // we pass it in order to prevent re-compressing the original image when we need to compress thumbs only\r\n const base64Compressed = attachmentData?.base64Compressed ?? null; \r\n const base64WebpCompressed = attachmentData?.base64WebpCompressed ?? null; // the original compressed webp image base64\r\n\r\n const worker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(\"assets_js_worker_js\"), __webpack_require__.b), {type: undefined}); // worker url\r\n const channel = new MessageChannel();\r\n worker.postMessage({\r\n action: 'compress',\r\n format,\r\n url,\r\n name,\r\n sourceType,\r\n outputType,\r\n mime,\r\n sizes,\r\n skipFull,\r\n timeout,\r\n isPreview,\r\n file,\r\n base64Compressed,\r\n base64WebpCompressed,\r\n type,\r\n options: this.options,\r\n //urlOriginal: urlOriginal,\r\n }, [channel.port2]);\r\n\r\n // Listen for compression requests from the worker via port1\r\n channel.port1.onmessage = async (ev) => {\r\n //console.log(\"Worker received compression request:\", ev.data);\r\n const { id, action, fileOrArrayBuffer, mime, options } = ev.data;\r\n if (action !== 'imageCompression') return;\r\n\r\n try {\r\n // Accept ArrayBuffer or Blob\r\n const blob = (fileOrArrayBuffer instanceof ArrayBuffer)\r\n ? new Blob([this.toUint8Array(fileOrArrayBuffer)], { type: mime })\r\n : fileOrArrayBuffer;\r\n\r\n const compressedBlob = await (0,browser_image_compression__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(blob, { useWebWorker: true, ...(options || {}) });\r\n\r\n // quick checks\r\n //console.log('compressedBlob.type, size:', compressedBlob.type, compressedBlob.size);\r\n // normalize final binary\r\n const compressedArrayBuffer = await compressedBlob.arrayBuffer();\r\n\r\n // Reply with the compressed ArrayBuffer (transfer to avoid copy)\r\n channel.port1.postMessage({ id, ok: true, arrayBuffer: compressedArrayBuffer }, [compressedArrayBuffer]);\r\n } catch (err) {\r\n channel.port1.postMessage({ id, ok: false, error: err.message || String(err) });\r\n }\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n worker.terminate();\r\n console.warn('Worker compress terminated', name, sourceType, outputType);\r\n reject(__('Request timed out.', 'squeeze'));\r\n }, timeout);\r\n\r\n worker.onmessage = (event) => {\r\n clearTimeout(timeoutId);\r\n if (event.data.error) {\r\n reject(event.data.error);\r\n } else {\r\n resolve(event.data);\r\n }\r\n worker.terminate();\r\n };\r\n\r\n worker.onerror = (error) => {\r\n clearTimeout(timeoutId);\r\n reject(`Worker error: ${error.message}`);\r\n };\r\n });\r\n\r\n }\r\n\r\n handleUpload = async ({ attachment, base64, type = 'uncompressed', mediaIDs = [] }) => {\r\n\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const format = base64?.isDirectWebp && type !== 'path' ? 'webp' : mime.split(\"/\")[1];\r\n const sizes = attachmentData.sizes;\r\n\r\n const isDirectWebp = base64?.isDirectWebp && mime !== 'image/webp';\r\n const isBackupOriginal = this.options?.backup_original ?? false; // check if backup original is enabled\r\n let originalFile = attachmentData?.originalFile ?? null; // the original file, used for creating backup\r\n \r\n // if originalFile is not provided, try to get it from the URL\r\n // used when the attachment needs to be converted to webp from jpg or png\r\n if (!originalFile && type !== 'path' && isBackupOriginal && isDirectWebp) {\r\n const file = await (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getFileFromUrl)(url, filename, mime.split(\"/\")[1])\r\n //console.log('conveting original file to webp', file);\r\n originalFile = await this.convertFileToWebp(file);\r\n }\r\n //console.log('handleUpload attachmentData', attachmentData)\r\n\r\n const data = {\r\n action: 'squeeze_update_attachment',\r\n _ajax_nonce: this.nonce,\r\n filename: filename,\r\n type: 'image',\r\n format: format,\r\n base64: base64.base64,\r\n base64Sizes: base64.base64Sizes,\r\n base64Webp: base64.base64Webp,\r\n base64SizesWebp: base64.base64SizesWebp,\r\n attachmentID: attachmentID,\r\n url: url,\r\n process: type,\r\n originalFile: originalFile,\r\n }\r\n\r\n const formData = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.objectToFormData)(data);\r\n\r\n //console.log('squeeze_update_attachment', JSON.stringify(data, null, 2));\r\n\r\n try {\r\n const uploadResponse = await jQuery.ajax({\r\n url: this.ajaxUrl, // + '111',\r\n type: 'POST',\r\n data: formData,\r\n processData: false, // very important!\r\n contentType: false, // very important!\r\n });\r\n\r\n //if (uploadResponse.success) {\r\n uploadResponse['mediaIDs'] = mediaIDs;\r\n //}\r\n\r\n if (!uploadResponse?.data?.url) {\r\n uploadResponse.url = url; // fallback to original URL if not provided\r\n }\r\n\r\n //console.log('uploadResponse', JSON.stringify(uploadResponse, null, 2));\r\n\r\n return uploadResponse;\r\n \r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n };\r\n }\r\n\r\n }\r\n\r\n handleBulkUpload = async (type = 'uncompressed', mediaIDs = []) => {\r\n let currentID;\r\n let attachment;\r\n\r\n switch (type) {\r\n case 'all':\r\n case 'uncompressed':\r\n currentID = mediaIDs[0];\r\n break;\r\n case 'path':\r\n currentID = mediaIDs[0]?.filename;\r\n break;\r\n default:\r\n currentID = 0;\r\n break;\r\n }\r\n\r\n if (type === 'path') {\r\n\r\n \r\n\r\n attachment = {\r\n attributes: {\r\n url: mediaIDs[0].url,\r\n mime: mediaIDs[0].mime,\r\n name: mediaIDs[0].name,\r\n filename: mediaIDs[0].filename,\r\n id: mediaIDs[0].id,\r\n sizes: mediaIDs[0]?.sizes,\r\n }\r\n }\r\n\r\n } else {\r\n\r\n const attachmentResponse = await this.getAttachment(currentID); \r\n if (attachmentResponse.success === false) {\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': attachmentResponse.data\r\n }\r\n }\r\n const attachmentData = attachmentResponse.data;\r\n attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n\r\n }\r\n\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n\r\n const mediaType = attachment.attributes.mime.split(\"/\")[0];\r\n const mediaSubType = attachment.attributes.mime.split(\"/\")[1];\r\n\r\n if (!(0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment)(mediaType, mediaSubType)) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': __('Skipped', 'squeeze')\r\n }\r\n }\r\n\r\n try {\r\n const compressData = await this.handleCompress( attachment, type );\r\n const uploadData = await this.handleUpload({ attachment: attachment, base64: compressData, type: type, mediaIDs: mediaIDs })\r\n\r\n return uploadData;\r\n\r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error?.message ?? error,\r\n 'success': false\r\n }\r\n }\r\n\r\n }\r\n\r\n \r\n\r\n handleRestore = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_restore_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n };\r\n\r\n const response = await jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n };\r\n\r\n // Get list of attachments by path\r\n getAttachmentsByPath = async (path) => {\r\n\r\n const data = {\r\n action: 'squeeze_get_attachment_by_path',\r\n path: path,\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getAttachment = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_get_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getNextAttachments = async (page = 1, type = 'uncompressed', lastId = 0) => {\r\n const data = {\r\n action: 'squeeze_get_next_attachments',\r\n _ajax_nonce: this.nonce,\r\n page: page,\r\n type: type,\r\n lastId: lastId,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getDirectories = async (parentDir = false) => {\r\n const data = {\r\n action: 'squeeze_get_directories',\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n if (parentDir) {\r\n data['parentDir'] = parentDir;\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n \r\n\r\n setOptions = async (options) => {\r\n const data = {\r\n action: 'squeeze_set_options',\r\n _ajax_nonce: this.nonce,\r\n options: options,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Compresses an image before upload.\r\n * If the compressSizes parameter is provided, it will compress the sizes specified along with the original image.\r\n * \r\n * @param {File} file - The file to be compressed\r\n * @param {object} compressSizes - Optional sizes for compression\r\n * @returns {Promise<object|boolean>} - Returns a Promise that resolves to the compressed file as a base64 object or false if the file is invalid\r\n */\r\n compressBeforeUpload = async (file, compressSizes = null) => {\r\n if (!(file instanceof Blob) && !(file instanceof File)) {\r\n console.error('Invalid file type:', file);\r\n return false; // Return false if the file is not a Blob or File\r\n }\r\n\r\n const attachment = {\r\n attributes: {\r\n url: null,\r\n mime: file.type,\r\n name: file.name,\r\n filename: file.name,\r\n id: 0,\r\n sizes: compressSizes,\r\n file: file,\r\n skipFull: false,\r\n }\r\n }\r\n\r\n try {\r\n const base64Obj = await this.handleCompress(attachment);\r\n\r\n return base64Obj; // Return the compressed file as base64Obj\r\n } catch (error) {\r\n console.error(error);\r\n return error; // Return the error for further handling\r\n }\r\n }\r\n\r\n isWebpEncodingSupported = async () => {\r\n try {\r\n const canvas = document.createElement('canvas');\r\n if (!canvas.toDataURL) return false;\r\n const data = canvas.toDataURL('image/webp');\r\n // WebP signature starts with \"data:image/webp\"\r\n return data.indexOf('data:image/webp') === 0;\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n\r\n handleConvertFileToWebp = async (args) => {\r\n const timeout = this.timeout;\r\n \r\n const { file, sourceType, name } = args;\r\n const fileBuffer = await file.arrayBuffer();\r\n const mime = sourceType === 'png' ? 'image/png' : 'image/jpeg';\r\n const inputBlob = new Blob([fileBuffer], { type: mime });\r\n // compression options you can tune\r\n const imageCompressionOptions = {\r\n useWebWorker: true,\r\n fileType: 'image/webp',\r\n };\r\n\r\n return new Promise(async (resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n console.warn('Worker convertToWebp terminated', name);\r\n reject(new Error(__('Request timed out.', 'squeeze')));\r\n }, timeout);\r\n\r\n try {\r\n\r\n const compressedBlob = await (0,browser_image_compression__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(inputBlob, imageCompressionOptions);\r\n\r\n // quick checks\r\n //console.log('compressedBlob.type, size:', compressedBlob.type, compressedBlob.size);\r\n // normalize final binary\r\n const webpArrayBuffer = await compressedBlob.arrayBuffer();\r\n\r\n const webpName = name.replace(/\\.\\w+$/, '.webp');\r\n const webpFile = new File([webpArrayBuffer], webpName, { type: 'image/webp', lastModified: Date.now() });\r\n\r\n clearTimeout(timeoutId);\r\n resolve({ webpFile }); // must return object with webpFile prop\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n console.error('Error during image processing:', error);\r\n reject(error);\r\n }\r\n });\r\n \r\n }\r\n\r\n // helper: normalize buffer-like inputs to Uint8Array\r\n toUint8Array = (bufferLike) => {\r\n if (bufferLike instanceof Uint8Array) return bufferLike;\r\n if (bufferLike instanceof ArrayBuffer) return new Uint8Array(bufferLike);\r\n if (ArrayBuffer.isView(bufferLike)) return new Uint8Array(bufferLike.buffer, bufferLike.byteOffset, bufferLike.byteLength);\r\n // Node Buffer (in some environments) has .buffer and .byteOffset\r\n if (bufferLike && typeof bufferLike === 'object' && bufferLike.buffer) {\r\n return new Uint8Array(bufferLike.buffer, bufferLike.byteOffset || 0, bufferLike.byteLength || bufferLike.length);\r\n }\r\n throw new Error('Unsupported buffer type: ' + Object.prototype.toString.call(bufferLike));\r\n }\r\n\r\n /**\r\n * Convert an image File to WebP.\r\n *\r\n * @param {File} inputFile — the original image File (e.g. JPEG, PNG).\r\n * @returns {Promise<File>} — a Promise that resolves to a WebP File.\r\n */\r\n convertFileToWebp = async (inputFile) => {\r\n // Ensure it’s an image\r\n if (!inputFile.type.startsWith('image/')) {\r\n throw new Error('Input must be an image File');\r\n }\r\n const args = {\r\n file: inputFile,\r\n sourceType: inputFile.type.split('/')[1], // e.g. 'jpeg', 'png'\r\n name: inputFile.name,\r\n }\r\n const webpSupported = await this.isWebpEncodingSupported();\r\n try {\r\n // Convert the image to WebP\r\n let webpData;\r\n if (webpSupported) {\r\n webpData = await this.handleConvertFileToWebp(args);\r\n } else {\r\n console.warn('WebP encoding not supported on this device. Using original format instead.');\r\n const webpName = args.name.replace(/\\.\\w+$/, '.webp');\r\n webpData = await this.convertToWebpWithJsquash(inputFile, webpName);\r\n }\r\n if (!webpData || !webpData.webpFile) {\r\n throw new Error('Failed to convert image to WebP');\r\n }\r\n\r\n return webpData.webpFile; // Return the WebP File\r\n\r\n } catch (error) {\r\n console.error('Error converting image to WebP:', error);\r\n throw error; // Re-throw the error for further handling\r\n }\r\n\r\n }\r\n\r\n /**\r\n * Convert an input (File | Blob | ArrayBuffer | Uint8Array) to a WebP File using @jsquash/webp.\r\n * @param {File|Blob|ArrayBuffer|Uint8Array} input\r\n * @param {string} outputName - desired filename for the .webp output\r\n * @param {{quality?: number, lossless?: boolean, method?: number}} [opts] - encoder options (quality 0-100)\r\n * @returns {Promise<File>} - WebP File\r\n */\r\n convertToWebpWithJsquash = async (input, outputName = 'out.webp', opts = { quality: 100 }) => {\r\n // Normalize input to Blob\r\n let blob;\r\n if (input instanceof Blob) {\r\n blob = input;\r\n } else if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) {\r\n blob = new Blob([input]);\r\n } else {\r\n throw new Error('Unsupported input type. Provide File, Blob, ArrayBuffer or TypedArray.');\r\n }\r\n\r\n // Load image into <img>\r\n const dataURL = await new Promise((resolve, reject) => {\r\n const fr = new FileReader();\r\n fr.onload = () => resolve(fr.result);\r\n fr.onerror = reject;\r\n fr.readAsDataURL(blob);\r\n });\r\n\r\n const img = await new Promise((resolve, reject) => {\r\n const i = new Image();\r\n i.onload = () => resolve(i);\r\n i.onerror = () => reject(new Error('Failed to load image for conversion'));\r\n i.src = dataURL;\r\n // avoid cross-origin taint if data-url is used\r\n });\r\n\r\n // Draw to canvas and extract ImageData\r\n const canvas = document.createElement('canvas');\r\n canvas.width = img.naturalWidth || img.width;\r\n canvas.height = img.naturalHeight || img.height;\r\n const ctx = canvas.getContext('2d');\r\n ctx.drawImage(img, 0, 0);\r\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n\r\n // encode -> returns ArrayBuffer (WASM libwebp)\r\n // opts example: { quality: 75, lossless: false, method: 4 }\r\n const webpArrayBuffer = await (0,_jsquash_webp__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(imageData, opts);\r\n\r\n // Validate a little (size)\r\n if (!webpArrayBuffer || webpArrayBuffer.byteLength < 20) {\r\n throw new Error('jsquash produced an invalid WebP buffer');\r\n }\r\n\r\n // Wrap into File\r\n const webpFile = new File([webpArrayBuffer], outputName.replace(/\\.\\w+$/, '.webp'), {\r\n type: 'image/webp',\r\n lastModified: Date.now(),\r\n });\r\n\r\n return {webpFile};\r\n }\r\n\r\n}\n\n//# sourceURL=webpack:///./assets/js/squeeze.js?"); 50 51 /***/ }), 52 53 /***/ "./node_modules/@jsquash/webp/encode.js": 54 /*!**********************************************!*\ 55 !*** ./node_modules/@jsquash/webp/encode.js ***! 56 \**********************************************/ 57 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 58 59 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ encode),\n/* harmony export */ \"init\": () => (/* binding */ init)\n/* harmony export */ });\n/* harmony import */ var _meta_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./meta.js */ \"./node_modules/@jsquash/webp/meta.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@jsquash/webp/utils.js\");\n/* harmony import */ var wasm_feature_detect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! wasm-feature-detect */ \"./node_modules/wasm-feature-detect/dist/esm/index.js\");\n/**\n * Copyright 2020 Google Inc. All Rights Reserved.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n\nlet emscriptenModule;\nasync function init(module, moduleOptionOverrides) {\n if (await (0,wasm_feature_detect__WEBPACK_IMPORTED_MODULE_0__.simd)()) {\n const webpEncoder = await __webpack_require__.e(/*! import() */ \"vendors-node_modules_jsquash_webp_codec_enc_webp_enc_simd_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./codec/enc/webp_enc_simd.js */ \"./node_modules/@jsquash/webp/codec/enc/webp_enc_simd.js\"));\n emscriptenModule = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.initEmscriptenModule)(webpEncoder.default, module, moduleOptionOverrides);\n return emscriptenModule;\n }\n const webpEncoder = await __webpack_require__.e(/*! import() */ \"vendors-node_modules_jsquash_webp_codec_enc_webp_enc_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./codec/enc/webp_enc.js */ \"./node_modules/@jsquash/webp/codec/enc/webp_enc.js\"));\n emscriptenModule = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.initEmscriptenModule)(webpEncoder.default, module, moduleOptionOverrides);\n return emscriptenModule;\n}\nasync function encode(data, options = {}) {\n if (!emscriptenModule)\n emscriptenModule = init();\n const _options = { ..._meta_js__WEBPACK_IMPORTED_MODULE_2__.defaultOptions, ...options };\n const module = await emscriptenModule;\n const result = module.encode(data.data, data.width, data.height, _options);\n if (!result)\n throw new Error('Encoding error.');\n return result.buffer;\n}\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/encode.js?"); 60 61 /***/ }), 62 63 /***/ "./node_modules/@jsquash/webp/meta.js": 64 /*!********************************************!*\ 65 !*** ./node_modules/@jsquash/webp/meta.js ***! 66 \********************************************/ 67 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 68 69 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"defaultOptions\": () => (/* binding */ defaultOptions),\n/* harmony export */ \"extension\": () => (/* binding */ extension),\n/* harmony export */ \"label\": () => (/* binding */ label),\n/* harmony export */ \"mimeType\": () => (/* binding */ mimeType)\n/* harmony export */ });\nconst label = 'WebP';\nconst mimeType = 'image/webp';\nconst extension = 'webp';\n// These come from struct WebPConfig in encode.h.\nconst defaultOptions = {\n quality: 75,\n target_size: 0,\n target_PSNR: 0,\n method: 4,\n sns_strength: 50,\n filter_strength: 60,\n filter_sharpness: 0,\n filter_type: 1,\n partitions: 0,\n segments: 4,\n pass: 1,\n show_compressed: 0,\n preprocessing: 0,\n autofilter: 0,\n partition_limit: 0,\n alpha_compression: 1,\n alpha_filtering: 1,\n alpha_quality: 100,\n lossless: 0,\n exact: 0,\n image_hint: 0,\n emulate_jpeg_size: 0,\n thread_level: 0,\n low_memory: 0,\n near_lossless: 100,\n use_delta_palette: 0,\n use_sharp_yuv: 0,\n};\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/meta.js?"); 70 71 /***/ }), 72 73 /***/ "./node_modules/@jsquash/webp/utils.js": 74 /*!*********************************************!*\ 75 !*** ./node_modules/@jsquash/webp/utils.js ***! 76 \*********************************************/ 77 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 78 79 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"initEmscriptenModule\": () => (/* binding */ initEmscriptenModule)\n/* harmony export */ });\n/**\n * Copyright 2020 Google Inc. All Rights Reserved.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module.\n */\nfunction initEmscriptenModule(moduleFactory, wasmModule, moduleOptionOverrides = {}) {\n let instantiateWasm;\n if (wasmModule) {\n instantiateWasm = (imports, callback) => {\n const instance = new WebAssembly.Instance(wasmModule, imports);\n callback(instance);\n return instance.exports;\n };\n }\n return moduleFactory({\n // Just to be safe, don't automatically invoke any wasm functions\n noInitialRun: true,\n instantiateWasm,\n ...moduleOptionOverrides,\n });\n}\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/utils.js?"); 80 81 /***/ }), 82 83 /***/ "./node_modules/browser-image-compression/dist/browser-image-compression.mjs": 84 /*!***********************************************************************************!*\ 85 !*** ./node_modules/browser-image-compression/dist/browser-image-compression.mjs ***! 86 \***********************************************************************************/ 87 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 88 89 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ imageCompression)\n/* harmony export */ });\n/**\n * Browser Image Compression\n * v2.0.2\n * by Donald <[email protected]>\n * https://github.com/Donaldcwl/browser-image-compression\n */\n\nfunction _mergeNamespaces(e,t){return t.forEach((function(t){t&&\"string\"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(r){if(\"default\"!==r&&!(r in e)){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}}))})),Object.freeze(e)}function copyExifWithoutOrientation(e,t){return new Promise((function(r,i){let o;return getApp1Segment(e).then((function(e){try{return o=e,r(new Blob([t.slice(0,2),o,t.slice(2)],{type:\"image/jpeg\"}))}catch(e){return i(e)}}),i)}))}const getApp1Segment=e=>new Promise(((t,r)=>{const i=new FileReader;i.addEventListener(\"load\",(({target:{result:e}})=>{const i=new DataView(e);let o=0;if(65496!==i.getUint16(o))return r(\"not a valid JPEG\");for(o+=2;;){const a=i.getUint16(o);if(65498===a)break;const s=i.getUint16(o+2);if(65505===a&&1165519206===i.getUint32(o+4)){const a=o+10;let f;switch(i.getUint16(a)){case 18761:f=!0;break;case 19789:f=!1;break;default:return r(\"TIFF header contains invalid endian\")}if(42!==i.getUint16(a+2,f))return r(\"TIFF header contains invalid version\");const l=i.getUint32(a+4,f),c=a+l+2+12*i.getUint16(a+l,f);for(let e=a+l+2;e<c;e+=12){if(274==i.getUint16(e,f)){if(3!==i.getUint16(e+2,f))return r(\"Orientation data type is invalid\");if(1!==i.getUint32(e+4,f))return r(\"Orientation data count is invalid\");i.setUint16(e+8,1,f);break}}return t(e.slice(o,o+2+s))}o+=2+s}return t(new Blob)})),i.readAsArrayBuffer(e)}));var e={},t={get exports(){return e},set exports(t){e=t}};!function(e){var r,i,UZIP={};t.exports=UZIP,UZIP.parse=function(e,t){for(var r=UZIP.bin.readUshort,i=UZIP.bin.readUint,o=0,a={},s=new Uint8Array(e),f=s.length-4;101010256!=i(s,f);)f--;o=f;o+=4;var l=r(s,o+=4);r(s,o+=2);var c=i(s,o+=2),u=i(s,o+=4);o+=4,o=u;for(var h=0;h<l;h++){i(s,o),o+=4,o+=4,o+=4,i(s,o+=4);c=i(s,o+=4);var d=i(s,o+=4),A=r(s,o+=4),g=r(s,o+2),p=r(s,o+4);o+=6;var m=i(s,o+=8);o+=4,o+=A+g+p,UZIP._readLocal(s,m,a,c,d,t)}return a},UZIP._readLocal=function(e,t,r,i,o,a){var s=UZIP.bin.readUshort,f=UZIP.bin.readUint;f(e,t),s(e,t+=4),s(e,t+=2);var l=s(e,t+=2);f(e,t+=2),f(e,t+=4),t+=4;var c=s(e,t+=8),u=s(e,t+=2);t+=2;var h=UZIP.bin.readUTF8(e,t,c);if(t+=c,t+=u,a)r[h]={size:o,csize:i};else{var d=new Uint8Array(e.buffer,t);if(0==l)r[h]=new Uint8Array(d.buffer.slice(t,t+i));else{if(8!=l)throw\"unknown compression method: \"+l;var A=new Uint8Array(o);UZIP.inflateRaw(d,A),r[h]=A}}},UZIP.inflateRaw=function(e,t){return UZIP.F.inflate(e,t)},UZIP.inflate=function(e,t){return e[0],e[1],UZIP.inflateRaw(new Uint8Array(e.buffer,e.byteOffset+2,e.length-6),t)},UZIP.deflate=function(e,t){null==t&&(t={level:6});var r=0,i=new Uint8Array(50+Math.floor(1.1*e.length));i[r]=120,i[r+1]=156,r+=2,r=UZIP.F.deflateRaw(e,i,r,t.level);var o=UZIP.adler(e,0,e.length);return i[r+0]=o>>>24&255,i[r+1]=o>>>16&255,i[r+2]=o>>>8&255,i[r+3]=o>>>0&255,new Uint8Array(i.buffer,0,r+4)},UZIP.deflateRaw=function(e,t){null==t&&(t={level:6});var r=new Uint8Array(50+Math.floor(1.1*e.length)),i=UZIP.F.deflateRaw(e,r,i,t.level);return new Uint8Array(r.buffer,0,i)},UZIP.encode=function(e,t){null==t&&(t=!1);var r=0,i=UZIP.bin.writeUint,o=UZIP.bin.writeUshort,a={};for(var s in e){var f=!UZIP._noNeed(s)&&!t,l=e[s],c=UZIP.crc.crc(l,0,l.length);a[s]={cpr:f,usize:l.length,crc:c,file:f?UZIP.deflateRaw(l):l}}for(var s in a)r+=a[s].file.length+30+46+2*UZIP.bin.sizeUTF8(s);r+=22;var u=new Uint8Array(r),h=0,d=[];for(var s in a){var A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,0)}var g=0,p=h;for(var s in a){A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,1,d[g++])}var m=h-p;return i(u,h,101010256),h+=4,o(u,h+=4,g),o(u,h+=2,g),i(u,h+=2,m),i(u,h+=4,p),h+=4,h+=2,u.buffer},UZIP._noNeed=function(e){var t=e.split(\".\").pop().toLowerCase();return-1!=\"png,jpg,jpeg,zip\".indexOf(t)},UZIP._writeHeader=function(e,t,r,i,o,a){var s=UZIP.bin.writeUint,f=UZIP.bin.writeUshort,l=i.file;return s(e,t,0==o?67324752:33639248),t+=4,1==o&&(t+=2),f(e,t,20),f(e,t+=2,0),f(e,t+=2,i.cpr?8:0),s(e,t+=2,0),s(e,t+=4,i.crc),s(e,t+=4,l.length),s(e,t+=4,i.usize),f(e,t+=4,UZIP.bin.sizeUTF8(r)),f(e,t+=2,0),t+=2,1==o&&(t+=2,t+=2,s(e,t+=6,a),t+=4),t+=UZIP.bin.writeUTF8(e,t,r),0==o&&(e.set(l,t),t+=l.length),t},UZIP.crc={table:function(){for(var e=new Uint32Array(256),t=0;t<256;t++){for(var r=t,i=0;i<8;i++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update:function(e,t,r,i){for(var o=0;o<i;o++)e=UZIP.crc.table[255&(e^t[r+o])]^e>>>8;return e},crc:function(e,t,r){return 4294967295^UZIP.crc.update(4294967295,e,t,r)}},UZIP.adler=function(e,t,r){for(var i=1,o=0,a=t,s=t+r;a<s;){for(var f=Math.min(a+5552,s);a<f;)o+=i+=e[a++];i%=65521,o%=65521}return o<<16|i},UZIP.bin={readUshort:function(e,t){return e[t]|e[t+1]<<8},writeUshort:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255},readUint:function(e,t){return 16777216*e[t+3]+(e[t+2]<<16|e[t+1]<<8|e[t])},writeUint:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255,e[t+2]=r>>16&255,e[t+3]=r>>24&255},readASCII:function(e,t,r){for(var i=\"\",o=0;o<r;o++)i+=String.fromCharCode(e[t+o]);return i},writeASCII:function(e,t,r){for(var i=0;i<r.length;i++)e[t+i]=r.charCodeAt(i)},pad:function(e){return e.length<2?\"0\"+e:e},readUTF8:function(e,t,r){for(var i,o=\"\",a=0;a<r;a++)o+=\"%\"+UZIP.bin.pad(e[t+a].toString(16));try{i=decodeURIComponent(o)}catch(i){return UZIP.bin.readASCII(e,t,r)}return i},writeUTF8:function(e,t,r){for(var i=r.length,o=0,a=0;a<i;a++){var s=r.charCodeAt(a);if(0==(4294967168&s))e[t+o]=s,o++;else if(0==(4294965248&s))e[t+o]=192|s>>6,e[t+o+1]=128|s>>0&63,o+=2;else if(0==(4294901760&s))e[t+o]=224|s>>12,e[t+o+1]=128|s>>6&63,e[t+o+2]=128|s>>0&63,o+=3;else{if(0!=(4292870144&s))throw\"e\";e[t+o]=240|s>>18,e[t+o+1]=128|s>>12&63,e[t+o+2]=128|s>>6&63,e[t+o+3]=128|s>>0&63,o+=4}}return o},sizeUTF8:function(e){for(var t=e.length,r=0,i=0;i<t;i++){var o=e.charCodeAt(i);if(0==(4294967168&o))r++;else if(0==(4294965248&o))r+=2;else if(0==(4294901760&o))r+=3;else{if(0!=(4292870144&o))throw\"e\";r+=4}}return r}},UZIP.F={},UZIP.F.deflateRaw=function(e,t,r,i){var o=[[0,0,0,0,0],[4,4,8,4,0],[4,5,16,8,0],[4,6,16,16,0],[4,10,16,32,0],[8,16,32,32,0],[8,16,128,128,0],[8,32,128,256,0],[32,128,258,1024,1],[32,258,258,4096,1]][i],a=UZIP.F.U,s=UZIP.F._goodIndex;UZIP.F._hash;var f=UZIP.F._putsE,l=0,c=r<<3,u=0,h=e.length;if(0==i){for(;l<h;){f(t,c,l+(_=Math.min(65535,h-l))==h?1:0),c=UZIP.F._copyExact(e,l,_,t,c+8),l+=_}return c>>>3}var d=a.lits,A=a.strt,g=a.prev,p=0,m=0,w=0,v=0,b=0,y=0;for(h>2&&(A[y=UZIP.F._hash(e,0)]=0),l=0;l<h;l++){if(b=y,l+1<h-2){y=UZIP.F._hash(e,l+1);var E=l+1&32767;g[E]=A[y],A[y]=E}if(u<=l){(p>14e3||m>26697)&&h-l>100&&(u<l&&(d[p]=l-u,p+=2,u=l),c=UZIP.F._writeBlock(l==h-1||u==h?1:0,d,p,v,e,w,l-w,t,c),p=m=v=0,w=l);var F=0;l<h-2&&(F=UZIP.F._bestMatch(e,l,g,b,Math.min(o[2],h-l),o[3]));var _=F>>>16,B=65535&F;if(0!=F){B=65535&F;var U=s(_=F>>>16,a.of0);a.lhst[257+U]++;var C=s(B,a.df0);a.dhst[C]++,v+=a.exb[U]+a.dxb[C],d[p]=_<<23|l-u,d[p+1]=B<<16|U<<8|C,p+=2,u=l+_}else a.lhst[e[l]]++;m++}}for(w==l&&0!=e.length||(u<l&&(d[p]=l-u,p+=2,u=l),c=UZIP.F._writeBlock(1,d,p,v,e,w,l-w,t,c),p=0,m=0,p=m=v=0,w=l);0!=(7&c);)c++;return c>>>3},UZIP.F._bestMatch=function(e,t,r,i,o,a){var s=32767&t,f=r[s],l=s-f+32768&32767;if(f==s||i!=UZIP.F._hash(e,t-l))return 0;for(var c=0,u=0,h=Math.min(32767,t);l<=h&&0!=--a&&f!=s;){if(0==c||e[t+c]==e[t+c-l]){var d=UZIP.F._howLong(e,t,l);if(d>c){if(u=l,(c=d)>=o)break;l+2<d&&(d=l+2);for(var A=0,g=0;g<d-2;g++){var p=t-l+g+32768&32767,m=p-r[p]+32768&32767;m>A&&(A=m,f=p)}}}l+=(s=f)-(f=r[s])+32768&32767}return c<<16|u},UZIP.F._howLong=function(e,t,r){if(e[t]!=e[t-r]||e[t+1]!=e[t+1-r]||e[t+2]!=e[t+2-r])return 0;var i=t,o=Math.min(e.length,t+258);for(t+=3;t<o&&e[t]==e[t-r];)t++;return t-i},UZIP.F._hash=function(e,t){return(e[t]<<8|e[t+1])+(e[t+2]<<4)&65535},UZIP.saved=0,UZIP.F._writeBlock=function(e,t,r,i,o,a,s,f,l){var c,u,h,d,A,g,p,m,w,v=UZIP.F.U,b=UZIP.F._putsF,y=UZIP.F._putsE;v.lhst[256]++,u=(c=UZIP.F.getTrees())[0],h=c[1],d=c[2],A=c[3],g=c[4],p=c[5],m=c[6],w=c[7];var E=32+(0==(l+3&7)?0:8-(l+3&7))+(s<<3),F=i+UZIP.F.contSize(v.fltree,v.lhst)+UZIP.F.contSize(v.fdtree,v.dhst),_=i+UZIP.F.contSize(v.ltree,v.lhst)+UZIP.F.contSize(v.dtree,v.dhst);_+=14+3*p+UZIP.F.contSize(v.itree,v.ihst)+(2*v.ihst[16]+3*v.ihst[17]+7*v.ihst[18]);for(var B=0;B<286;B++)v.lhst[B]=0;for(B=0;B<30;B++)v.dhst[B]=0;for(B=0;B<19;B++)v.ihst[B]=0;var U=E<F&&E<_?0:F<_?1:2;if(b(f,l,e),b(f,l+1,U),l+=3,0==U){for(;0!=(7&l);)l++;l=UZIP.F._copyExact(o,a,s,f,l)}else{var C,I;if(1==U&&(C=v.fltree,I=v.fdtree),2==U){UZIP.F.makeCodes(v.ltree,u),UZIP.F.revCodes(v.ltree,u),UZIP.F.makeCodes(v.dtree,h),UZIP.F.revCodes(v.dtree,h),UZIP.F.makeCodes(v.itree,d),UZIP.F.revCodes(v.itree,d),C=v.ltree,I=v.dtree,y(f,l,A-257),y(f,l+=5,g-1),y(f,l+=5,p-4),l+=4;for(var Q=0;Q<p;Q++)y(f,l+3*Q,v.itree[1+(v.ordr[Q]<<1)]);l+=3*p,l=UZIP.F._codeTiny(m,v.itree,f,l),l=UZIP.F._codeTiny(w,v.itree,f,l)}for(var M=a,x=0;x<r;x+=2){for(var S=t[x],R=S>>>23,T=M+(8388607&S);M<T;)l=UZIP.F._writeLit(o[M++],C,f,l);if(0!=R){var O=t[x+1],P=O>>16,H=O>>8&255,L=255&O;y(f,l=UZIP.F._writeLit(257+H,C,f,l),R-v.of0[H]),l+=v.exb[H],b(f,l=UZIP.F._writeLit(L,I,f,l),P-v.df0[L]),l+=v.dxb[L],M+=R}}l=UZIP.F._writeLit(256,C,f,l)}return l},UZIP.F._copyExact=function(e,t,r,i,o){var a=o>>>3;return i[a]=r,i[a+1]=r>>>8,i[a+2]=255-i[a],i[a+3]=255-i[a+1],a+=4,i.set(new Uint8Array(e.buffer,t,r),a),o+(r+4<<3)},UZIP.F.getTrees=function(){for(var e=UZIP.F.U,t=UZIP.F._hufTree(e.lhst,e.ltree,15),r=UZIP.F._hufTree(e.dhst,e.dtree,15),i=[],o=UZIP.F._lenCodes(e.ltree,i),a=[],s=UZIP.F._lenCodes(e.dtree,a),f=0;f<i.length;f+=2)e.ihst[i[f]]++;for(f=0;f<a.length;f+=2)e.ihst[a[f]]++;for(var l=UZIP.F._hufTree(e.ihst,e.itree,7),c=19;c>4&&0==e.itree[1+(e.ordr[c-1]<<1)];)c--;return[t,r,l,o,s,c,i,a]},UZIP.F.getSecond=function(e){for(var t=[],r=0;r<e.length;r+=2)t.push(e[r+1]);return t},UZIP.F.nonZero=function(e){for(var t=\"\",r=0;r<e.length;r+=2)0!=e[r+1]&&(t+=(r>>1)+\",\");return t},UZIP.F.contSize=function(e,t){for(var r=0,i=0;i<t.length;i++)r+=t[i]*e[1+(i<<1)];return r},UZIP.F._codeTiny=function(e,t,r,i){for(var o=0;o<e.length;o+=2){var a=e[o],s=e[o+1];i=UZIP.F._writeLit(a,t,r,i);var f=16==a?2:17==a?3:7;a>15&&(UZIP.F._putsE(r,i,s,f),i+=f)}return i},UZIP.F._lenCodes=function(e,t){for(var r=e.length;2!=r&&0==e[r-1];)r-=2;for(var i=0;i<r;i+=2){var o=e[i+1],a=i+3<r?e[i+3]:-1,s=i+5<r?e[i+5]:-1,f=0==i?-1:e[i-1];if(0==o&&a==o&&s==o){for(var l=i+5;l+2<r&&e[l+2]==o;)l+=2;(c=Math.min(l+1-i>>>1,138))<11?t.push(17,c-3):t.push(18,c-11),i+=2*c-2}else if(o==f&&a==o&&s==o){for(l=i+5;l+2<r&&e[l+2]==o;)l+=2;var c=Math.min(l+1-i>>>1,6);t.push(16,c-3),i+=2*c-2}else t.push(o,0)}return r>>>1},UZIP.F._hufTree=function(e,t,r){var i=[],o=e.length,a=t.length,s=0;for(s=0;s<a;s+=2)t[s]=0,t[s+1]=0;for(s=0;s<o;s++)0!=e[s]&&i.push({lit:s,f:e[s]});var f=i.length,l=i.slice(0);if(0==f)return 0;if(1==f){var c=i[0].lit;l=0==c?1:0;return t[1+(c<<1)]=1,t[1+(l<<1)]=1,1}i.sort((function(e,t){return e.f-t.f}));var u=i[0],h=i[1],d=0,A=1,g=2;for(i[0]={lit:-1,f:u.f+h.f,l:u,r:h,d:0};A!=f-1;)u=d!=A&&(g==f||i[d].f<i[g].f)?i[d++]:i[g++],h=d!=A&&(g==f||i[d].f<i[g].f)?i[d++]:i[g++],i[A++]={lit:-1,f:u.f+h.f,l:u,r:h};var p=UZIP.F.setDepth(i[A-1],0);for(p>r&&(UZIP.F.restrictDepth(l,r,p),p=r),s=0;s<f;s++)t[1+(l[s].lit<<1)]=l[s].d;return p},UZIP.F.setDepth=function(e,t){return-1!=e.lit?(e.d=t,t):Math.max(UZIP.F.setDepth(e.l,t+1),UZIP.F.setDepth(e.r,t+1))},UZIP.F.restrictDepth=function(e,t,r){var i=0,o=1<<r-t,a=0;for(e.sort((function(e,t){return t.d==e.d?e.f-t.f:t.d-e.d})),i=0;i<e.length&&e[i].d>t;i++){var s=e[i].d;e[i].d=t,a+=o-(1<<r-s)}for(a>>>=r-t;a>0;){(s=e[i].d)<t?(e[i].d++,a-=1<<t-s-1):i++}for(;i>=0;i--)e[i].d==t&&a<0&&(e[i].d--,a++);0!=a&&console.log(\"debt left\")},UZIP.F._goodIndex=function(e,t){var r=0;return t[16|r]<=e&&(r|=16),t[8|r]<=e&&(r|=8),t[4|r]<=e&&(r|=4),t[2|r]<=e&&(r|=2),t[1|r]<=e&&(r|=1),r},UZIP.F._writeLit=function(e,t,r,i){return UZIP.F._putsF(r,i,t[e<<1]),i+t[1+(e<<1)]},UZIP.F.inflate=function(e,t){var r=Uint8Array;if(3==e[0]&&0==e[1])return t||new r(0);var i=UZIP.F,o=i._bitsF,a=i._bitsE,s=i._decodeTiny,f=i.makeCodes,l=i.codes2map,c=i._get17,u=i.U,h=null==t;h&&(t=new r(e.length>>>2<<3));for(var d,A,g=0,p=0,m=0,w=0,v=0,b=0,y=0,E=0,F=0;0==g;)if(g=o(e,F,1),p=o(e,F+1,2),F+=3,0!=p){if(h&&(t=UZIP.F._check(t,E+(1<<17))),1==p&&(d=u.flmap,A=u.fdmap,b=511,y=31),2==p){m=a(e,F,5)+257,w=a(e,F+5,5)+1,v=a(e,F+10,4)+4,F+=14;for(var _=0;_<38;_+=2)u.itree[_]=0,u.itree[_+1]=0;var B=1;for(_=0;_<v;_++){var U=a(e,F+3*_,3);u.itree[1+(u.ordr[_]<<1)]=U,U>B&&(B=U)}F+=3*v,f(u.itree,B),l(u.itree,B,u.imap),d=u.lmap,A=u.dmap,F=s(u.imap,(1<<B)-1,m+w,e,F,u.ttree);var C=i._copyOut(u.ttree,0,m,u.ltree);b=(1<<C)-1;var I=i._copyOut(u.ttree,m,w,u.dtree);y=(1<<I)-1,f(u.ltree,C),l(u.ltree,C,d),f(u.dtree,I),l(u.dtree,I,A)}for(;;){var Q=d[c(e,F)&b];F+=15&Q;var M=Q>>>4;if(M>>>8==0)t[E++]=M;else{if(256==M)break;var x=E+M-254;if(M>264){var S=u.ldef[M-257];x=E+(S>>>3)+a(e,F,7&S),F+=7&S}var R=A[c(e,F)&y];F+=15&R;var T=R>>>4,O=u.ddef[T],P=(O>>>4)+o(e,F,15&O);for(F+=15&O,h&&(t=UZIP.F._check(t,E+(1<<17)));E<x;)t[E]=t[E++-P],t[E]=t[E++-P],t[E]=t[E++-P],t[E]=t[E++-P];E=x}}}else{0!=(7&F)&&(F+=8-(7&F));var H=4+(F>>>3),L=e[H-4]|e[H-3]<<8;h&&(t=UZIP.F._check(t,E+L)),t.set(new r(e.buffer,e.byteOffset+H,L),E),F=H+L<<3,E+=L}return t.length==E?t:t.slice(0,E)},UZIP.F._check=function(e,t){var r=e.length;if(t<=r)return e;var i=new Uint8Array(Math.max(r<<1,t));return i.set(e,0),i},UZIP.F._decodeTiny=function(e,t,r,i,o,a){for(var s=UZIP.F._bitsE,f=UZIP.F._get17,l=0;l<r;){var c=e[f(i,o)&t];o+=15&c;var u=c>>>4;if(u<=15)a[l]=u,l++;else{var h=0,d=0;16==u?(d=3+s(i,o,2),o+=2,h=a[l-1]):17==u?(d=3+s(i,o,3),o+=3):18==u&&(d=11+s(i,o,7),o+=7);for(var A=l+d;l<A;)a[l]=h,l++}}return o},UZIP.F._copyOut=function(e,t,r,i){for(var o=0,a=0,s=i.length>>>1;a<r;){var f=e[a+t];i[a<<1]=0,i[1+(a<<1)]=f,f>o&&(o=f),a++}for(;a<s;)i[a<<1]=0,i[1+(a<<1)]=0,a++;return o},UZIP.F.makeCodes=function(e,t){for(var r,i,o,a,s=UZIP.F.U,f=e.length,l=s.bl_count,c=0;c<=t;c++)l[c]=0;for(c=1;c<f;c+=2)l[e[c]]++;var u=s.next_code;for(r=0,l[0]=0,i=1;i<=t;i++)r=r+l[i-1]<<1,u[i]=r;for(o=0;o<f;o+=2)0!=(a=e[o+1])&&(e[o]=u[a],u[a]++)},UZIP.F.codes2map=function(e,t,r){for(var i=e.length,o=UZIP.F.U.rev15,a=0;a<i;a+=2)if(0!=e[a+1])for(var s=a>>1,f=e[a+1],l=s<<4|f,c=t-f,u=e[a]<<c,h=u+(1<<c);u!=h;){r[o[u]>>>15-t]=l,u++}},UZIP.F.revCodes=function(e,t){for(var r=UZIP.F.U.rev15,i=15-t,o=0;o<e.length;o+=2){var a=e[o]<<t-e[o+1];e[o]=r[a]>>>i}},UZIP.F._putsE=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},UZIP.F._putsF=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},UZIP.F._bitsE=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<<r)-1},UZIP.F._bitsF=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<<r)-1},UZIP.F._get17=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},UZIP.F._get25=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},UZIP.F.U=(r=Uint16Array,i=Uint32Array,{next_code:new r(16),bl_count:new r(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new r(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new i(32),flmap:new r(512),fltree:[],fdmap:new r(32),fdtree:[],lmap:new r(32768),ltree:[],ttree:[],dmap:new r(32768),dtree:[],imap:new r(512),itree:[],rev15:new r(32768),lhst:new i(286),dhst:new i(30),ihst:new i(19),lits:new i(15e3),strt:new r(65536),prev:new r(32768)}),function(){for(var e=UZIP.F.U,t=0;t<32768;t++){var r=t;r=(4278255360&(r=(4042322160&(r=(3435973836&(r=(2863311530&r)>>>1|(1431655765&r)<<1))>>>2|(858993459&r)<<2))>>>4|(252645135&r)<<4))>>>8|(16711935&r)<<8,e.rev15[t]=(r>>>16|r<<16)>>>17}function pushV(e,t,r){for(;0!=t--;)e.push(0,r)}for(t=0;t<32;t++)e.ldef[t]=e.of0[t]<<3|e.exb[t],e.ddef[t]=e.df0[t]<<4|e.dxb[t];pushV(e.fltree,144,8),pushV(e.fltree,112,9),pushV(e.fltree,24,7),pushV(e.fltree,8,8),UZIP.F.makeCodes(e.fltree,9),UZIP.F.codes2map(e.fltree,9,e.flmap),UZIP.F.revCodes(e.fltree,9),pushV(e.fdtree,32,5),UZIP.F.makeCodes(e.fdtree,5),UZIP.F.codes2map(e.fdtree,5,e.fdmap),UZIP.F.revCodes(e.fdtree,5),pushV(e.itree,19,0),pushV(e.ltree,286,0),pushV(e.dtree,30,0),pushV(e.ttree,320,0)}()}();var UZIP=_mergeNamespaces({__proto__:null,default:e},[e]);const UPNG=function(){var e={nextZero(e,t){for(;0!=e[t];)t++;return t},readUshort:(e,t)=>e[t]<<8|e[t+1],writeUshort(e,t,r){e[t]=r>>8&255,e[t+1]=255&r},readUint:(e,t)=>16777216*e[t]+(e[t+1]<<16|e[t+2]<<8|e[t+3]),writeUint(e,t,r){e[t]=r>>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=255&r},readASCII(e,t,r){let i=\"\";for(let o=0;o<r;o++)i+=String.fromCharCode(e[t+o]);return i},writeASCII(e,t,r){for(let i=0;i<r.length;i++)e[t+i]=r.charCodeAt(i)},readBytes(e,t,r){const i=[];for(let o=0;o<r;o++)i.push(e[t+o]);return i},pad:e=>e.length<2?`0${e}`:e,readUTF8(t,r,i){let o,a=\"\";for(let o=0;o<i;o++)a+=`%${e.pad(t[r+o].toString(16))}`;try{o=decodeURIComponent(a)}catch(o){return e.readASCII(t,r,i)}return o}};function decodeImage(t,r,i,o){const a=r*i,s=_getBPP(o),f=Math.ceil(r*s/8),l=new Uint8Array(4*a),c=new Uint32Array(l.buffer),{ctype:u}=o,{depth:h}=o,d=e.readUshort;if(6==u){const e=a<<2;if(8==h)for(var A=0;A<e;A+=4)l[A]=t[A],l[A+1]=t[A+1],l[A+2]=t[A+2],l[A+3]=t[A+3];if(16==h)for(A=0;A<e;A++)l[A]=t[A<<1]}else if(2==u){const e=o.tabs.tRNS;if(null==e){if(8==h)for(A=0;A<a;A++){var g=3*A;c[A]=255<<24|t[g+2]<<16|t[g+1]<<8|t[g]}if(16==h)for(A=0;A<a;A++){g=6*A;c[A]=255<<24|t[g+4]<<16|t[g+2]<<8|t[g]}}else{var p=e[0];const r=e[1],i=e[2];if(8==h)for(A=0;A<a;A++){var m=A<<2;g=3*A;c[A]=255<<24|t[g+2]<<16|t[g+1]<<8|t[g],t[g]==p&&t[g+1]==r&&t[g+2]==i&&(l[m+3]=0)}if(16==h)for(A=0;A<a;A++){m=A<<2,g=6*A;c[A]=255<<24|t[g+4]<<16|t[g+2]<<8|t[g],d(t,g)==p&&d(t,g+2)==r&&d(t,g+4)==i&&(l[m+3]=0)}}}else if(3==u){const e=o.tabs.PLTE,s=o.tabs.tRNS,c=s?s.length:0;if(1==h)for(var w=0;w<i;w++){var v=w*f,b=w*r;for(A=0;A<r;A++){m=b+A<<2;var y=3*(E=t[v+(A>>3)]>>7-((7&A)<<0)&1);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}}if(2==h)for(w=0;w<i;w++)for(v=w*f,b=w*r,A=0;A<r;A++){m=b+A<<2,y=3*(E=t[v+(A>>2)]>>6-((3&A)<<1)&3);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}if(4==h)for(w=0;w<i;w++)for(v=w*f,b=w*r,A=0;A<r;A++){m=b+A<<2,y=3*(E=t[v+(A>>1)]>>4-((1&A)<<2)&15);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}if(8==h)for(A=0;A<a;A++){var E;m=A<<2,y=3*(E=t[A]);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}}else if(4==u){if(8==h)for(A=0;A<a;A++){m=A<<2;var F=t[_=A<<1];l[m]=F,l[m+1]=F,l[m+2]=F,l[m+3]=t[_+1]}if(16==h)for(A=0;A<a;A++){var _;m=A<<2,F=t[_=A<<2];l[m]=F,l[m+1]=F,l[m+2]=F,l[m+3]=t[_+2]}}else if(0==u)for(p=o.tabs.tRNS?o.tabs.tRNS:-1,w=0;w<i;w++){const e=w*f,i=w*r;if(1==h)for(var B=0;B<r;B++){var U=(F=255*(t[e+(B>>>3)]>>>7-(7&B)&1))==255*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(2==h)for(B=0;B<r;B++){U=(F=85*(t[e+(B>>>2)]>>>6-((3&B)<<1)&3))==85*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(4==h)for(B=0;B<r;B++){U=(F=17*(t[e+(B>>>1)]>>>4-((1&B)<<2)&15))==17*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(8==h)for(B=0;B<r;B++){U=(F=t[e+B])==p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(16==h)for(B=0;B<r;B++){F=t[e+(B<<1)],U=d(t,e+(B<<1))==p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}}return l}function _decompress(e,r,i,o){const a=_getBPP(e),s=Math.ceil(i*a/8),f=new Uint8Array((s+1+e.interlace)*o);return r=e.tabs.CgBI?t(r,f):_inflate(r,f),0==e.interlace?r=_filterZero(r,e,0,i,o):1==e.interlace&&(r=function _readInterlace(e,t){const r=t.width,i=t.height,o=_getBPP(t),a=o>>3,s=Math.ceil(r*o/8),f=new Uint8Array(i*s);let l=0;const c=[0,0,4,0,2,0,1],u=[0,4,0,2,0,1,0],h=[8,8,8,4,4,2,2],d=[8,8,4,4,2,2,1];let A=0;for(;A<7;){const p=h[A],m=d[A];let w=0,v=0,b=c[A];for(;b<i;)b+=p,v++;let y=u[A];for(;y<r;)y+=m,w++;const E=Math.ceil(w*o/8);_filterZero(e,t,l,w,v);let F=0,_=c[A];for(;_<i;){let t=u[A],i=l+F*E<<3;for(;t<r;){var g;if(1==o)g=(g=e[i>>3])>>7-(7&i)&1,f[_*s+(t>>3)]|=g<<7-((7&t)<<0);if(2==o)g=(g=e[i>>3])>>6-(7&i)&3,f[_*s+(t>>2)]|=g<<6-((3&t)<<1);if(4==o)g=(g=e[i>>3])>>4-(7&i)&15,f[_*s+(t>>1)]|=g<<4-((1&t)<<2);if(o>=8){const r=_*s+t*a;for(let t=0;t<a;t++)f[r+t]=e[(i>>3)+t]}i+=o,t+=m}F++,_+=p}w*v!=0&&(l+=v*(1+E)),A+=1}return f}(r,e)),r}function _inflate(e,r){return t(new Uint8Array(e.buffer,2,e.length-6),r)}var t=function(){const e={H:{}};return e.H.N=function(t,r){const i=Uint8Array;let o,a,s=0,f=0,l=0,c=0,u=0,h=0,d=0,A=0,g=0;if(3==t[0]&&0==t[1])return r||new i(0);const p=e.H,m=p.b,w=p.e,v=p.R,b=p.n,y=p.A,E=p.Z,F=p.m,_=null==r;for(_&&(r=new i(t.length>>>2<<5));0==s;)if(s=m(t,g,1),f=m(t,g+1,2),g+=3,0!=f){if(_&&(r=e.H.W(r,A+(1<<17))),1==f&&(o=F.J,a=F.h,h=511,d=31),2==f){l=w(t,g,5)+257,c=w(t,g+5,5)+1,u=w(t,g+10,4)+4,g+=14;let e=1;for(var B=0;B<38;B+=2)F.Q[B]=0,F.Q[B+1]=0;for(B=0;B<u;B++){const r=w(t,g+3*B,3);F.Q[1+(F.X[B]<<1)]=r,r>e&&(e=r)}g+=3*u,b(F.Q,e),y(F.Q,e,F.u),o=F.w,a=F.d,g=v(F.u,(1<<e)-1,l+c,t,g,F.v);const r=p.V(F.v,0,l,F.C);h=(1<<r)-1;const i=p.V(F.v,l,c,F.D);d=(1<<i)-1,b(F.C,r),y(F.C,r,o),b(F.D,i),y(F.D,i,a)}for(;;){const e=o[E(t,g)&h];g+=15&e;const i=e>>>4;if(i>>>8==0)r[A++]=i;else{if(256==i)break;{let e=A+i-254;if(i>264){const r=F.q[i-257];e=A+(r>>>3)+w(t,g,7&r),g+=7&r}const o=a[E(t,g)&d];g+=15&o;const s=o>>>4,f=F.c[s],l=(f>>>4)+m(t,g,15&f);for(g+=15&f;A<e;)r[A]=r[A++-l],r[A]=r[A++-l],r[A]=r[A++-l],r[A]=r[A++-l];A=e}}}}else{0!=(7&g)&&(g+=8-(7&g));const o=4+(g>>>3),a=t[o-4]|t[o-3]<<8;_&&(r=e.H.W(r,A+a)),r.set(new i(t.buffer,t.byteOffset+o,a),A),g=o+a<<3,A+=a}return r.length==A?r:r.slice(0,A)},e.H.W=function(e,t){const r=e.length;if(t<=r)return e;const i=new Uint8Array(r<<1);return i.set(e,0),i},e.H.R=function(t,r,i,o,a,s){const f=e.H.e,l=e.H.Z;let c=0;for(;c<i;){const e=t[l(o,a)&r];a+=15&e;const i=e>>>4;if(i<=15)s[c]=i,c++;else{let e=0,t=0;16==i?(t=3+f(o,a,2),a+=2,e=s[c-1]):17==i?(t=3+f(o,a,3),a+=3):18==i&&(t=11+f(o,a,7),a+=7);const r=c+t;for(;c<r;)s[c]=e,c++}}return a},e.H.V=function(e,t,r,i){let o=0,a=0;const s=i.length>>>1;for(;a<r;){const r=e[a+t];i[a<<1]=0,i[1+(a<<1)]=r,r>o&&(o=r),a++}for(;a<s;)i[a<<1]=0,i[1+(a<<1)]=0,a++;return o},e.H.n=function(t,r){const i=e.H.m,o=t.length;let a,s,f;let l;const c=i.j;for(var u=0;u<=r;u++)c[u]=0;for(u=1;u<o;u+=2)c[t[u]]++;const h=i.K;for(a=0,c[0]=0,s=1;s<=r;s++)a=a+c[s-1]<<1,h[s]=a;for(f=0;f<o;f+=2)l=t[f+1],0!=l&&(t[f]=h[l],h[l]++)},e.H.A=function(t,r,i){const o=t.length,a=e.H.m.r;for(let e=0;e<o;e+=2)if(0!=t[e+1]){const o=e>>1,s=t[e+1],f=o<<4|s,l=r-s;let c=t[e]<<l;const u=c+(1<<l);for(;c!=u;){i[a[c]>>>15-r]=f,c++}}},e.H.l=function(t,r){const i=e.H.m.r,o=15-r;for(let e=0;e<t.length;e+=2){const a=t[e]<<r-t[e+1];t[e]=i[a]>>>o}},e.H.M=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},e.H.I=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},e.H.e=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<<r)-1},e.H.b=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<<r)-1},e.H.Z=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},e.H.i=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},e.H.m=function(){const e=Uint16Array,t=Uint32Array;return{K:new e(16),j:new e(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new e(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new t(32),J:new e(512),_:[],h:new e(32),$:[],w:new e(32768),C:[],v:[],d:new e(32768),D:[],u:new e(512),Q:[],r:new e(32768),s:new t(286),Y:new t(30),a:new t(19),t:new t(15e3),k:new e(65536),g:new e(32768)}}(),function(){const t=e.H.m;for(var r=0;r<32768;r++){let e=r;e=(2863311530&e)>>>1|(1431655765&e)<<1,e=(3435973836&e)>>>2|(858993459&e)<<2,e=(4042322160&e)>>>4|(252645135&e)<<4,e=(4278255360&e)>>>8|(16711935&e)<<8,t.r[r]=(e>>>16|e<<16)>>>17}function n(e,t,r){for(;0!=t--;)e.push(0,r)}for(r=0;r<32;r++)t.q[r]=t.S[r]<<3|t.T[r],t.c[r]=t.p[r]<<4|t.z[r];n(t._,144,8),n(t._,112,9),n(t._,24,7),n(t._,8,8),e.H.n(t._,9),e.H.A(t._,9,t.J),e.H.l(t._,9),n(t.$,32,5),e.H.n(t.$,5),e.H.A(t.$,5,t.h),e.H.l(t.$,5),n(t.Q,19,0),n(t.C,286,0),n(t.D,30,0),n(t.v,320,0)}(),e.H.N}();function _getBPP(e){return[1,null,3,1,2,null,4][e.ctype]*e.depth}function _filterZero(e,t,r,i,o){let a=_getBPP(t);const s=Math.ceil(i*a/8);let f,l;a=Math.ceil(a/8);let c=e[r],u=0;if(c>1&&(e[r]=[0,0,1][c-2]),3==c)for(u=a;u<s;u++)e[u+1]=e[u+1]+(e[u+1-a]>>>1)&255;for(let t=0;t<o;t++)if(f=r+t*s,l=f+t+1,c=e[l-1],u=0,0==c)for(;u<s;u++)e[f+u]=e[l+u];else if(1==c){for(;u<a;u++)e[f+u]=e[l+u];for(;u<s;u++)e[f+u]=e[l+u]+e[f+u-a]}else if(2==c)for(;u<s;u++)e[f+u]=e[l+u]+e[f+u-s];else if(3==c){for(;u<a;u++)e[f+u]=e[l+u]+(e[f+u-s]>>>1);for(;u<s;u++)e[f+u]=e[l+u]+(e[f+u-s]+e[f+u-a]>>>1)}else{for(;u<a;u++)e[f+u]=e[l+u]+_paeth(0,e[f+u-s],0);for(;u<s;u++)e[f+u]=e[l+u]+_paeth(e[f+u-a],e[f+u-s],e[f+u-a-s])}return e}function _paeth(e,t,r){const i=e+t-r,o=i-e,a=i-t,s=i-r;return o*o<=a*a&&o*o<=s*s?e:a*a<=s*s?t:r}function _IHDR(t,r,i){i.width=e.readUint(t,r),r+=4,i.height=e.readUint(t,r),r+=4,i.depth=t[r],r++,i.ctype=t[r],r++,i.compress=t[r],r++,i.filter=t[r],r++,i.interlace=t[r],r++}function _copyTile(e,t,r,i,o,a,s,f,l){const c=Math.min(t,o),u=Math.min(r,a);let h=0,d=0;for(let r=0;r<u;r++)for(let a=0;a<c;a++)if(s>=0&&f>=0?(h=r*t+a<<2,d=(f+r)*o+s+a<<2):(h=(-f+r)*t-s+a<<2,d=r*o+a<<2),0==l)i[d]=e[h],i[d+1]=e[h+1],i[d+2]=e[h+2],i[d+3]=e[h+3];else if(1==l){var A=e[h+3]*(1/255),g=e[h]*A,p=e[h+1]*A,m=e[h+2]*A,w=i[d+3]*(1/255),v=i[d]*w,b=i[d+1]*w,y=i[d+2]*w;const t=1-A,r=A+w*t,o=0==r?0:1/r;i[d+3]=255*r,i[d+0]=(g+v*t)*o,i[d+1]=(p+b*t)*o,i[d+2]=(m+y*t)*o}else if(2==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];A==w&&g==v&&p==b&&m==y?(i[d]=0,i[d+1]=0,i[d+2]=0,i[d+3]=0):(i[d]=g,i[d+1]=p,i[d+2]=m,i[d+3]=A)}else if(3==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];if(A==w&&g==v&&p==b&&m==y)continue;if(A<220&&w>20)return!1}return!0}return{decode:function decode(r){const i=new Uint8Array(r);let o=8;const a=e,s=a.readUshort,f=a.readUint,l={tabs:{},frames:[]},c=new Uint8Array(i.length);let u,h=0,d=0;const A=[137,80,78,71,13,10,26,10];for(var g=0;g<8;g++)if(i[g]!=A[g])throw\"The input is not a PNG file!\";for(;o<i.length;){const e=a.readUint(i,o);o+=4;const r=a.readASCII(i,o,4);if(o+=4,\"IHDR\"==r)_IHDR(i,o,l);else if(\"iCCP\"==r){for(var p=o;0!=i[p];)p++;a.readASCII(i,o,p-o),i[p+1];const s=i.slice(p+2,o+e);let f=null;try{f=_inflate(s)}catch(e){f=t(s)}l.tabs[r]=f}else if(\"CgBI\"==r)l.tabs[r]=i.slice(o,o+4);else if(\"IDAT\"==r){for(g=0;g<e;g++)c[h+g]=i[o+g];h+=e}else if(\"acTL\"==r)l.tabs[r]={num_frames:f(i,o),num_plays:f(i,o+4)},u=new Uint8Array(i.length);else if(\"fcTL\"==r){if(0!=d)(E=l.frames[l.frames.length-1]).data=_decompress(l,u.slice(0,d),E.rect.width,E.rect.height),d=0;const e={x:f(i,o+12),y:f(i,o+16),width:f(i,o+4),height:f(i,o+8)};let t=s(i,o+22);t=s(i,o+20)/(0==t?100:t);const r={rect:e,delay:Math.round(1e3*t),dispose:i[o+24],blend:i[o+25]};l.frames.push(r)}else if(\"fdAT\"==r){for(g=0;g<e-4;g++)u[d+g]=i[o+g+4];d+=e-4}else if(\"pHYs\"==r)l.tabs[r]=[a.readUint(i,o),a.readUint(i,o+4),i[o+8]];else if(\"cHRM\"==r){l.tabs[r]=[];for(g=0;g<8;g++)l.tabs[r].push(a.readUint(i,o+4*g))}else if(\"tEXt\"==r||\"zTXt\"==r){null==l.tabs[r]&&(l.tabs[r]={});var m=a.nextZero(i,o),w=a.readASCII(i,o,m-o),v=o+e-m-1;if(\"tEXt\"==r)y=a.readASCII(i,m+1,v);else{var b=_inflate(i.slice(m+2,m+2+v));y=a.readUTF8(b,0,b.length)}l.tabs[r][w]=y}else if(\"iTXt\"==r){null==l.tabs[r]&&(l.tabs[r]={});m=0,p=o;m=a.nextZero(i,p);w=a.readASCII(i,p,m-p);const t=i[p=m+1];var y;i[p+1],p+=2,m=a.nextZero(i,p),a.readASCII(i,p,m-p),p=m+1,m=a.nextZero(i,p),a.readUTF8(i,p,m-p);v=e-((p=m+1)-o);if(0==t)y=a.readUTF8(i,p,v);else{b=_inflate(i.slice(p,p+v));y=a.readUTF8(b,0,b.length)}l.tabs[r][w]=y}else if(\"PLTE\"==r)l.tabs[r]=a.readBytes(i,o,e);else if(\"hIST\"==r){const e=l.tabs.PLTE.length/3;l.tabs[r]=[];for(g=0;g<e;g++)l.tabs[r].push(s(i,o+2*g))}else if(\"tRNS\"==r)3==l.ctype?l.tabs[r]=a.readBytes(i,o,e):0==l.ctype?l.tabs[r]=s(i,o):2==l.ctype&&(l.tabs[r]=[s(i,o),s(i,o+2),s(i,o+4)]);else if(\"gAMA\"==r)l.tabs[r]=a.readUint(i,o)/1e5;else if(\"sRGB\"==r)l.tabs[r]=i[o];else if(\"bKGD\"==r)0==l.ctype||4==l.ctype?l.tabs[r]=[s(i,o)]:2==l.ctype||6==l.ctype?l.tabs[r]=[s(i,o),s(i,o+2),s(i,o+4)]:3==l.ctype&&(l.tabs[r]=i[o]);else if(\"IEND\"==r)break;o+=e,a.readUint(i,o),o+=4}var E;return 0!=d&&((E=l.frames[l.frames.length-1]).data=_decompress(l,u.slice(0,d),E.rect.width,E.rect.height)),l.data=_decompress(l,c,l.width,l.height),delete l.compress,delete l.interlace,delete l.filter,l},toRGBA8:function toRGBA8(e){const t=e.width,r=e.height;if(null==e.tabs.acTL)return[decodeImage(e.data,t,r,e).buffer];const i=[];null==e.frames[0].data&&(e.frames[0].data=e.data);const o=t*r*4,a=new Uint8Array(o),s=new Uint8Array(o),f=new Uint8Array(o);for(let c=0;c<e.frames.length;c++){const u=e.frames[c],h=u.rect.x,d=u.rect.y,A=u.rect.width,g=u.rect.height,p=decodeImage(u.data,A,g,e);if(0!=c)for(var l=0;l<o;l++)f[l]=a[l];if(0==u.blend?_copyTile(p,A,g,a,t,r,h,d,0):1==u.blend&&_copyTile(p,A,g,a,t,r,h,d,1),i.push(a.buffer.slice(0)),0==u.dispose);else if(1==u.dispose)_copyTile(s,A,g,a,t,r,h,d,0);else if(2==u.dispose)for(l=0;l<o;l++)a[l]=f[l]}return i},_paeth:_paeth,_copyTile:_copyTile,_bin:e}}();!function(){const{_copyTile:e}=UPNG,{_bin:t}=UPNG,r=UPNG._paeth;var i={table:function(){const e=new Uint32Array(256);for(let t=0;t<256;t++){let r=t;for(let e=0;e<8;e++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update(e,t,r,o){for(let a=0;a<o;a++)e=i.table[255&(e^t[r+a])]^e>>>8;return e},crc:(e,t,r)=>4294967295^i.update(4294967295,e,t,r)};function addErr(e,t,r,i){t[r]+=e[0]*i>>4,t[r+1]+=e[1]*i>>4,t[r+2]+=e[2]*i>>4,t[r+3]+=e[3]*i>>4}function N(e){return Math.max(0,Math.min(255,e))}function D(e,t){const r=e[0]-t[0],i=e[1]-t[1],o=e[2]-t[2],a=e[3]-t[3];return r*r+i*i+o*o+a*a}function dither(e,t,r,i,o,a,s){null==s&&(s=1);const f=i.length,l=[];for(var c=0;c<f;c++){const e=i[c];l.push([e>>>0&255,e>>>8&255,e>>>16&255,e>>>24&255])}for(c=0;c<f;c++){let e=4294967295;for(var u=0,h=0;h<f;h++){var d=D(l[c],l[h]);h!=c&&d<e&&(e=d,u=h)}}const A=new Uint32Array(o.buffer),g=new Int16Array(t*r*4),p=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5];for(c=0;c<p.length;c++)p[c]=255*((p[c]+.5)/16-.5);for(let o=0;o<r;o++)for(let w=0;w<t;w++){var m;c=4*(o*t+w);if(2!=s)m=[N(e[c]+g[c]),N(e[c+1]+g[c+1]),N(e[c+2]+g[c+2]),N(e[c+3]+g[c+3])];else{d=p[4*(3&o)+(3&w)];m=[N(e[c]+d),N(e[c+1]+d),N(e[c+2]+d),N(e[c+3]+d)]}u=0;let v=16777215;for(h=0;h<f;h++){const e=D(m,l[h]);e<v&&(v=e,u=h)}const b=l[u],y=[m[0]-b[0],m[1]-b[1],m[2]-b[2],m[3]-b[3]];1==s&&(w!=t-1&&addErr(y,g,c+4,7),o!=r-1&&(0!=w&&addErr(y,g,c+4*t-4,3),addErr(y,g,c+4*t,5),w!=t-1&&addErr(y,g,c+4*t+4,1))),a[c>>2]=u,A[c>>2]=i[u]}}function _main(e,r,o,a,s){null==s&&(s={});const{crc:f}=i,l=t.writeUint,c=t.writeUshort,u=t.writeASCII;let h=8;const d=e.frames.length>1;let A,g=!1,p=33+(d?20:0);if(null!=s.sRGB&&(p+=13),null!=s.pHYs&&(p+=21),null!=s.iCCP&&(A=pako.deflate(s.iCCP),p+=21+A.length+4),3==e.ctype){for(var m=e.plte.length,w=0;w<m;w++)e.plte[w]>>>24!=255&&(g=!0);p+=8+3*m+4+(g?8+1*m+4:0)}for(var v=0;v<e.frames.length;v++){d&&(p+=38),p+=(F=e.frames[v]).cimg.length+12,0!=v&&(p+=4)}p+=12;const b=new Uint8Array(p),y=[137,80,78,71,13,10,26,10];for(w=0;w<8;w++)b[w]=y[w];if(l(b,h,13),h+=4,u(b,h,\"IHDR\"),h+=4,l(b,h,r),h+=4,l(b,h,o),h+=4,b[h]=e.depth,h++,b[h]=e.ctype,h++,b[h]=0,h++,b[h]=0,h++,b[h]=0,h++,l(b,h,f(b,h-17,17)),h+=4,null!=s.sRGB&&(l(b,h,1),h+=4,u(b,h,\"sRGB\"),h+=4,b[h]=s.sRGB,h++,l(b,h,f(b,h-5,5)),h+=4),null!=s.iCCP){const e=13+A.length;l(b,h,e),h+=4,u(b,h,\"iCCP\"),h+=4,u(b,h,\"ICC profile\"),h+=11,h+=2,b.set(A,h),h+=A.length,l(b,h,f(b,h-(e+4),e+4)),h+=4}if(null!=s.pHYs&&(l(b,h,9),h+=4,u(b,h,\"pHYs\"),h+=4,l(b,h,s.pHYs[0]),h+=4,l(b,h,s.pHYs[1]),h+=4,b[h]=s.pHYs[2],h++,l(b,h,f(b,h-13,13)),h+=4),d&&(l(b,h,8),h+=4,u(b,h,\"acTL\"),h+=4,l(b,h,e.frames.length),h+=4,l(b,h,null!=s.loop?s.loop:0),h+=4,l(b,h,f(b,h-12,12)),h+=4),3==e.ctype){l(b,h,3*(m=e.plte.length)),h+=4,u(b,h,\"PLTE\"),h+=4;for(w=0;w<m;w++){const t=3*w,r=e.plte[w],i=255&r,o=r>>>8&255,a=r>>>16&255;b[h+t+0]=i,b[h+t+1]=o,b[h+t+2]=a}if(h+=3*m,l(b,h,f(b,h-3*m-4,3*m+4)),h+=4,g){l(b,h,m),h+=4,u(b,h,\"tRNS\"),h+=4;for(w=0;w<m;w++)b[h+w]=e.plte[w]>>>24&255;h+=m,l(b,h,f(b,h-m-4,m+4)),h+=4}}let E=0;for(v=0;v<e.frames.length;v++){var F=e.frames[v];d&&(l(b,h,26),h+=4,u(b,h,\"fcTL\"),h+=4,l(b,h,E++),h+=4,l(b,h,F.rect.width),h+=4,l(b,h,F.rect.height),h+=4,l(b,h,F.rect.x),h+=4,l(b,h,F.rect.y),h+=4,c(b,h,a[v]),h+=2,c(b,h,1e3),h+=2,b[h]=F.dispose,h++,b[h]=F.blend,h++,l(b,h,f(b,h-30,30)),h+=4);const t=F.cimg;l(b,h,(m=t.length)+(0==v?0:4)),h+=4;const r=h;u(b,h,0==v?\"IDAT\":\"fdAT\"),h+=4,0!=v&&(l(b,h,E++),h+=4),b.set(t,h),h+=m,l(b,h,f(b,r,h-r)),h+=4}return l(b,h,0),h+=4,u(b,h,\"IEND\"),h+=4,l(b,h,f(b,h-4,4)),h+=4,b.buffer}function compressPNG(e,t,r){for(let i=0;i<e.frames.length;i++){const o=e.frames[i];o.rect.width;const a=o.rect.height,s=new Uint8Array(a*o.bpl+a);o.cimg=_filterZero(o.img,a,o.bpp,o.bpl,s,t,r)}}function compress(t,r,i,o,a){const s=a[0],f=a[1],l=a[2],c=a[3],u=a[4],h=a[5];let d=6,A=8,g=255;for(var p=0;p<t.length;p++){const e=new Uint8Array(t[p]);for(var m=e.length,w=0;w<m;w+=4)g&=e[w+3]}const v=255!=g,b=function framize(t,r,i,o,a,s){const f=[];for(var l=0;l<t.length;l++){const h=new Uint8Array(t[l]),A=new Uint32Array(h.buffer);var c;let g=0,p=0,m=r,w=i,v=o?1:0;if(0!=l){const b=s||o||1==l||0!=f[l-2].dispose?1:2;let y=0,E=1e9;for(let e=0;e<b;e++){var u=new Uint8Array(t[l-1-e]);const o=new Uint32Array(t[l-1-e]);let s=r,f=i,c=-1,h=-1;for(let e=0;e<i;e++)for(let t=0;t<r;t++){A[d=e*r+t]!=o[d]&&(t<s&&(s=t),t>c&&(c=t),e<f&&(f=e),e>h&&(h=e))}-1==c&&(s=f=c=h=0),a&&(1==(1&s)&&s--,1==(1&f)&&f--);const v=(c-s+1)*(h-f+1);v<E&&(E=v,y=e,g=s,p=f,m=c-s+1,w=h-f+1)}u=new Uint8Array(t[l-1-y]);1==y&&(f[l-1].dispose=2),c=new Uint8Array(m*w*4),e(u,r,i,c,m,w,-g,-p,0),v=e(h,r,i,c,m,w,-g,-p,3)?1:0,1==v?_prepareDiff(h,r,i,c,{x:g,y:p,width:m,height:w}):e(h,r,i,c,m,w,-g,-p,0)}else c=h.slice(0);f.push({rect:{x:g,y:p,width:m,height:w},img:c,blend:v,dispose:0})}if(o)for(l=0;l<f.length;l++){if(1==(A=f[l]).blend)continue;const e=A.rect,o=f[l-1].rect,s=Math.min(e.x,o.x),c=Math.min(e.y,o.y),u={x:s,y:c,width:Math.max(e.x+e.width,o.x+o.width)-s,height:Math.max(e.y+e.height,o.y+o.height)-c};f[l-1].dispose=1,l-1!=0&&_updateFrame(t,r,i,f,l-1,u,a),_updateFrame(t,r,i,f,l,u,a)}let h=0;if(1!=t.length)for(var d=0;d<f.length;d++){var A;h+=(A=f[d]).rect.width*A.rect.height}return f}(t,r,i,s,f,l),y={},E=[],F=[];if(0!=o){const e=[];for(w=0;w<b.length;w++)e.push(b[w].img.buffer);const t=function concatRGBA(e){let t=0;for(var r=0;r<e.length;r++)t+=e[r].byteLength;const i=new Uint8Array(t);let o=0;for(r=0;r<e.length;r++){const t=new Uint8Array(e[r]),a=t.length;for(let e=0;e<a;e+=4){let r=t[e],a=t[e+1],s=t[e+2];const f=t[e+3];0==f&&(r=a=s=0),i[o+e]=r,i[o+e+1]=a,i[o+e+2]=s,i[o+e+3]=f}o+=a}return i.buffer}(e),r=quantize(t,o);for(w=0;w<r.plte.length;w++)E.push(r.plte[w].est.rgba);let i=0;for(w=0;w<b.length;w++){const e=(B=b[w]).img.length;var _=new Uint8Array(r.inds.buffer,i>>2,e>>2);F.push(_);const t=new Uint8Array(r.abuf,i,e);h&&dither(B.img,B.rect.width,B.rect.height,E,t,_),B.img.set(t),i+=e}}else for(p=0;p<b.length;p++){var B=b[p];const e=new Uint32Array(B.img.buffer);var U=B.rect.width;m=e.length,_=new Uint8Array(m);F.push(_);for(w=0;w<m;w++){const t=e[w];if(0!=w&&t==e[w-1])_[w]=_[w-1];else if(w>U&&t==e[w-U])_[w]=_[w-U];else{let e=y[t];if(null==e&&(y[t]=e=E.length,E.push(t),E.length>=300))break;_[w]=e}}}const C=E.length;C<=256&&0==u&&(A=C<=2?1:C<=4?2:C<=16?4:8,A=Math.max(A,c));for(p=0;p<b.length;p++){(B=b[p]).rect.x,B.rect.y;U=B.rect.width;const e=B.rect.height;let t=B.img;new Uint32Array(t.buffer);let r=4*U,i=4;if(C<=256&&0==u){r=Math.ceil(A*U/8);var I=new Uint8Array(r*e);const o=F[p];for(let t=0;t<e;t++){w=t*r;const e=t*U;if(8==A)for(var Q=0;Q<U;Q++)I[w+Q]=o[e+Q];else if(4==A)for(Q=0;Q<U;Q++)I[w+(Q>>1)]|=o[e+Q]<<4-4*(1&Q);else if(2==A)for(Q=0;Q<U;Q++)I[w+(Q>>2)]|=o[e+Q]<<6-2*(3&Q);else if(1==A)for(Q=0;Q<U;Q++)I[w+(Q>>3)]|=o[e+Q]<<7-1*(7&Q)}t=I,d=3,i=1}else if(0==v&&1==b.length){I=new Uint8Array(U*e*3);const o=U*e;for(w=0;w<o;w++){const e=3*w,r=4*w;I[e]=t[r],I[e+1]=t[r+1],I[e+2]=t[r+2]}t=I,d=2,i=3,r=3*U}B.img=t,B.bpl=r,B.bpp=i}return{ctype:d,depth:A,plte:E,frames:b}}function _updateFrame(t,r,i,o,a,s,f){const l=Uint8Array,c=Uint32Array,u=new l(t[a-1]),h=new c(t[a-1]),d=a+1<t.length?new l(t[a+1]):null,A=new l(t[a]),g=new c(A.buffer);let p=r,m=i,w=-1,v=-1;for(let e=0;e<s.height;e++)for(let t=0;t<s.width;t++){const i=s.x+t,f=s.y+e,l=f*r+i,c=g[l];0==c||0==o[a-1].dispose&&h[l]==c&&(null==d||0!=d[4*l+3])||(i<p&&(p=i),i>w&&(w=i),f<m&&(m=f),f>v&&(v=f))}-1==w&&(p=m=w=v=0),f&&(1==(1&p)&&p--,1==(1&m)&&m--),s={x:p,y:m,width:w-p+1,height:v-m+1};const b=o[a];b.rect=s,b.blend=1,b.img=new Uint8Array(s.width*s.height*4),0==o[a-1].dispose?(e(u,r,i,b.img,s.width,s.height,-s.x,-s.y,0),_prepareDiff(A,r,i,b.img,s)):e(A,r,i,b.img,s.width,s.height,-s.x,-s.y,0)}function _prepareDiff(t,r,i,o,a){e(t,r,i,o,a.width,a.height,-a.x,-a.y,2)}function _filterZero(e,t,r,i,o,a,s){const f=[];let l,c=[0,1,2,3,4];-1!=a?c=[a]:(t*i>5e5||1==r)&&(c=[0]),s&&(l={level:0});const u=UZIP;for(var h=0;h<c.length;h++){for(let a=0;a<t;a++)_filterLine(o,e,a,i,r,c[h]);f.push(u.deflate(o,l))}let d,A=1e9;for(h=0;h<f.length;h++)f[h].length<A&&(d=h,A=f[h].length);return f[d]}function _filterLine(e,t,i,o,a,s){const f=i*o;let l=f+i;if(e[l]=s,l++,0==s)if(o<500)for(var c=0;c<o;c++)e[l+c]=t[f+c];else e.set(new Uint8Array(t.buffer,f,o),l);else if(1==s){for(c=0;c<a;c++)e[l+c]=t[f+c];for(c=a;c<o;c++)e[l+c]=t[f+c]-t[f+c-a]+256&255}else if(0==i){for(c=0;c<a;c++)e[l+c]=t[f+c];if(2==s)for(c=a;c<o;c++)e[l+c]=t[f+c];if(3==s)for(c=a;c<o;c++)e[l+c]=t[f+c]-(t[f+c-a]>>1)+256&255;if(4==s)for(c=a;c<o;c++)e[l+c]=t[f+c]-r(t[f+c-a],0,0)+256&255}else{if(2==s)for(c=0;c<o;c++)e[l+c]=t[f+c]+256-t[f+c-o]&255;if(3==s){for(c=0;c<a;c++)e[l+c]=t[f+c]+256-(t[f+c-o]>>1)&255;for(c=a;c<o;c++)e[l+c]=t[f+c]+256-(t[f+c-o]+t[f+c-a]>>1)&255}if(4==s){for(c=0;c<a;c++)e[l+c]=t[f+c]+256-r(0,t[f+c-o],0)&255;for(c=a;c<o;c++)e[l+c]=t[f+c]+256-r(t[f+c-a],t[f+c-o],t[f+c-a-o])&255}}}function quantize(e,t){const r=new Uint8Array(e),i=r.slice(0),o=new Uint32Array(i.buffer),a=getKDtree(i,t),s=a[0],f=a[1],l=r.length,c=new Uint8Array(l>>2);let u;if(r.length<2e7)for(var h=0;h<l;h+=4){u=getNearest(s,d=r[h]*(1/255),A=r[h+1]*(1/255),g=r[h+2]*(1/255),p=r[h+3]*(1/255)),c[h>>2]=u.ind,o[h>>2]=u.est.rgba}else for(h=0;h<l;h+=4){var d=r[h]*(1/255),A=r[h+1]*(1/255),g=r[h+2]*(1/255),p=r[h+3]*(1/255);for(u=s;u.left;)u=planeDst(u.est,d,A,g,p)<=0?u.left:u.right;c[h>>2]=u.ind,o[h>>2]=u.est.rgba}return{abuf:i.buffer,inds:c,plte:f}}function getKDtree(e,t,r){null==r&&(r=1e-4);const i=new Uint32Array(e.buffer),o={i0:0,i1:e.length,bst:null,est:null,tdst:0,left:null,right:null};o.bst=stats(e,o.i0,o.i1),o.est=estats(o.bst);const a=[o];for(;a.length<t;){let t=0,o=0;for(var s=0;s<a.length;s++)a[s].est.L>t&&(t=a[s].est.L,o=s);if(t<r)break;const f=a[o],l=splitPixels(e,i,f.i0,f.i1,f.est.e,f.est.eMq255);if(f.i0>=l||f.i1<=l){f.est.L=0;continue}const c={i0:f.i0,i1:l,bst:null,est:null,tdst:0,left:null,right:null};c.bst=stats(e,c.i0,c.i1),c.est=estats(c.bst);const u={i0:l,i1:f.i1,bst:null,est:null,tdst:0,left:null,right:null};u.bst={R:[],m:[],N:f.bst.N-c.bst.N};for(s=0;s<16;s++)u.bst.R[s]=f.bst.R[s]-c.bst.R[s];for(s=0;s<4;s++)u.bst.m[s]=f.bst.m[s]-c.bst.m[s];u.est=estats(u.bst),f.left=c,f.right=u,a[o]=c,a.push(u)}a.sort(((e,t)=>t.bst.N-e.bst.N));for(s=0;s<a.length;s++)a[s].ind=s;return[o,a]}function getNearest(e,t,r,i,o){if(null==e.left)return e.tdst=function dist(e,t,r,i,o){const a=t-e[0],s=r-e[1],f=i-e[2],l=o-e[3];return a*a+s*s+f*f+l*l}(e.est.q,t,r,i,o),e;const a=planeDst(e.est,t,r,i,o);let s=e.left,f=e.right;a>0&&(s=e.right,f=e.left);const l=getNearest(s,t,r,i,o);if(l.tdst<=a*a)return l;const c=getNearest(f,t,r,i,o);return c.tdst<l.tdst?c:l}function planeDst(e,t,r,i,o){const{e:a}=e;return a[0]*t+a[1]*r+a[2]*i+a[3]*o-e.eMq}function splitPixels(e,t,r,i,o,a){for(i-=4;r<i;){for(;vecDot(e,r,o)<=a;)r+=4;for(;vecDot(e,i,o)>a;)i-=4;if(r>=i)break;const s=t[r>>2];t[r>>2]=t[i>>2],t[i>>2]=s,r+=4,i-=4}for(;vecDot(e,r,o)>a;)r-=4;return r+4}function vecDot(e,t,r){return e[t]*r[0]+e[t+1]*r[1]+e[t+2]*r[2]+e[t+3]*r[3]}function stats(e,t,r){const i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o=[0,0,0,0],a=r-t>>2;for(let a=t;a<r;a+=4){const t=e[a]*(1/255),r=e[a+1]*(1/255),s=e[a+2]*(1/255),f=e[a+3]*(1/255);o[0]+=t,o[1]+=r,o[2]+=s,o[3]+=f,i[0]+=t*t,i[1]+=t*r,i[2]+=t*s,i[3]+=t*f,i[5]+=r*r,i[6]+=r*s,i[7]+=r*f,i[10]+=s*s,i[11]+=s*f,i[15]+=f*f}return i[4]=i[1],i[8]=i[2],i[9]=i[6],i[12]=i[3],i[13]=i[7],i[14]=i[11],{R:i,m:o,N:a}}function estats(e){const{R:t}=e,{m:r}=e,{N:i}=e,a=r[0],s=r[1],f=r[2],l=r[3],c=0==i?0:1/i,u=[t[0]-a*a*c,t[1]-a*s*c,t[2]-a*f*c,t[3]-a*l*c,t[4]-s*a*c,t[5]-s*s*c,t[6]-s*f*c,t[7]-s*l*c,t[8]-f*a*c,t[9]-f*s*c,t[10]-f*f*c,t[11]-f*l*c,t[12]-l*a*c,t[13]-l*s*c,t[14]-l*f*c,t[15]-l*l*c],h=u,d=o;let A=[Math.random(),Math.random(),Math.random(),Math.random()],g=0,p=0;if(0!=i)for(let e=0;e<16&&(A=d.multVec(h,A),p=Math.sqrt(d.dot(A,A)),A=d.sml(1/p,A),!(0!=e&&Math.abs(p-g)<1e-9));e++)g=p;const m=[a*c,s*c,f*c,l*c];return{Cov:u,q:m,e:A,L:g,eMq255:d.dot(d.sml(255,m),A),eMq:d.dot(A,m),rgba:(Math.round(255*m[3])<<24|Math.round(255*m[2])<<16|Math.round(255*m[1])<<8|Math.round(255*m[0])<<0)>>>0}}var o={multVec:(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],e[4]*t[0]+e[5]*t[1]+e[6]*t[2]+e[7]*t[3],e[8]*t[0]+e[9]*t[1]+e[10]*t[2]+e[11]*t[3],e[12]*t[0]+e[13]*t[1]+e[14]*t[2]+e[15]*t[3]],dot:(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],sml:(e,t)=>[e*t[0],e*t[1],e*t[2],e*t[3]]};UPNG.encode=function encode(e,t,r,i,o,a,s){null==i&&(i=0),null==s&&(s=!1);const f=compress(e,t,r,i,[!1,!1,!1,0,s,!1]);return compressPNG(f,-1),_main(f,t,r,o,a)},UPNG.encodeLL=function encodeLL(e,t,r,i,o,a,s,f){const l={ctype:0+(1==i?0:2)+(0==o?0:4),depth:a,frames:[]},c=(i+o)*a,u=c*t;for(let i=0;i<e.length;i++)l.frames.push({rect:{x:0,y:0,width:t,height:r},img:new Uint8Array(e[i]),blend:0,dispose:1,bpp:Math.ceil(c/8),bpl:Math.ceil(u/8)});return compressPNG(l,0,!0),_main(l,t,r,s,f)},UPNG.encode.compress=compress,UPNG.encode.dither=dither,UPNG.quantize=quantize,UPNG.quantize.getKDtree=getKDtree,UPNG.quantize.getNearest=getNearest}();const r={toArrayBuffer(e,t){const i=e.width,o=e.height,a=i<<2,s=e.getContext(\"2d\").getImageData(0,0,i,o),f=new Uint32Array(s.data.buffer),l=(32*i+31)/32<<2,c=l*o,u=122+c,h=new ArrayBuffer(u),d=new DataView(h),A=1<<20;let g,p,m,w,v=A,b=0,y=0,E=0;function set16(e){d.setUint16(y,e,!0),y+=2}function set32(e){d.setUint32(y,e,!0),y+=4}function seek(e){y+=e}set16(19778),set32(u),seek(4),set32(122),set32(108),set32(i),set32(-o>>>0),set16(1),set16(32),set32(3),set32(c),set32(2835),set32(2835),seek(8),set32(16711680),set32(65280),set32(255),set32(4278190080),set32(1466527264),function convert(){for(;b<o&&v>0;){for(w=122+b*l,g=0;g<a;)v--,p=f[E++],m=p>>>24,d.setUint32(w+g,p<<8|m),g+=4;b++}E<f.length?(v=A,setTimeout(convert,r._dly)):t(h)}()},toBlob(e,t){this.toArrayBuffer(e,(e=>{t(new Blob([e],{type:\"image/bmp\"}))}))},_dly:9};var i={CHROME:\"CHROME\",FIREFOX:\"FIREFOX\",DESKTOP_SAFARI:\"DESKTOP_SAFARI\",IE:\"IE\",IOS:\"IOS\",ETC:\"ETC\"},o={[i.CHROME]:16384,[i.FIREFOX]:11180,[i.DESKTOP_SAFARI]:16384,[i.IE]:8192,[i.IOS]:4096,[i.ETC]:8192};const a=\"undefined\"!=typeof window,s=\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,f=a&&window.cordova&&window.cordova.require&&window.cordova.require(\"cordova/modulemapper\"),CustomFile=(a||s)&&(f&&f.getOriginalSymbol(window,\"File\")||\"undefined\"!=typeof File&&File),CustomFileReader=(a||s)&&(f&&f.getOriginalSymbol(window,\"FileReader\")||\"undefined\"!=typeof FileReader&&FileReader);function getFilefromDataUrl(e,t,r=Date.now()){return new Promise((i=>{const o=e.split(\",\"),a=o[0].match(/:(.*?);/)[1],s=globalThis.atob(o[1]);let f=s.length;const l=new Uint8Array(f);for(;f--;)l[f]=s.charCodeAt(f);const c=new Blob([l],{type:a});c.name=t,c.lastModified=r,i(c)}))}function getDataUrlFromFile(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=()=>t(i.result),i.onerror=e=>r(e),i.readAsDataURL(e)}))}function loadImage(e){return new Promise(((t,r)=>{const i=new Image;i.onload=()=>t(i),i.onerror=e=>r(e),i.src=e}))}function getBrowserName(){if(void 0!==getBrowserName.cachedResult)return getBrowserName.cachedResult;let e=i.ETC;const{userAgent:t}=navigator;return/Chrom(e|ium)/i.test(t)?e=i.CHROME:/iP(ad|od|hone)/i.test(t)&&/WebKit/i.test(t)?e=i.IOS:/Safari/i.test(t)?e=i.DESKTOP_SAFARI:/Firefox/i.test(t)?e=i.FIREFOX:(/MSIE/i.test(t)||!0==!!document.documentMode)&&(e=i.IE),getBrowserName.cachedResult=e,getBrowserName.cachedResult}function approximateBelowMaximumCanvasSizeOfBrowser(e,t){const r=getBrowserName(),i=o[r];let a=e,s=t,f=a*s;const l=a>s?s/a:a/s;for(;f>i*i;){const e=(i+a)/2,t=(i+s)/2;e<t?(s=t,a=t*l):(s=e*l,a=e),f=a*s}return{width:a,height:s}}function getNewCanvasAndCtx(e,t){let r,i;try{if(r=new OffscreenCanvas(e,t),i=r.getContext(\"2d\"),null===i)throw new Error(\"getContext of OffscreenCanvas returns null\")}catch(e){r=document.createElement(\"canvas\"),i=r.getContext(\"2d\")}return r.width=e,r.height=t,[r,i]}function drawImageInCanvas(e,t){const{width:r,height:i}=approximateBelowMaximumCanvasSizeOfBrowser(e.width,e.height),[o,a]=getNewCanvasAndCtx(r,i);return t&&/jpe?g/.test(t)&&(a.fillStyle=\"white\",a.fillRect(0,0,o.width,o.height)),a.drawImage(e,0,0,o.width,o.height),o}function isIOS(){return void 0!==isIOS.cachedResult||(isIOS.cachedResult=[\"iPad Simulator\",\"iPhone Simulator\",\"iPod Simulator\",\"iPad\",\"iPhone\",\"iPod\"].includes(navigator.platform)||navigator.userAgent.includes(\"Mac\")&&\"undefined\"!=typeof document&&\"ontouchend\"in document),isIOS.cachedResult}function drawFileInCanvas(e,t={}){return new Promise((function(r,o){let a,s;var $Try_2_Post=function(){try{return s=drawImageInCanvas(a,t.fileType||e.type),r([a,s])}catch(e){return o(e)}},$Try_2_Catch=function(t){try{0;var $Try_3_Catch=function(e){try{throw e}catch(e){return o(e)}};try{let t;return getDataUrlFromFile(e).then((function(e){try{return t=e,loadImage(t).then((function(e){try{return a=e,function(){try{return $Try_2_Post()}catch(e){return o(e)}}()}catch(e){return $Try_3_Catch(e)}}),$Try_3_Catch)}catch(e){return $Try_3_Catch(e)}}),$Try_3_Catch)}catch(e){$Try_3_Catch(e)}}catch(e){return o(e)}};try{if(isIOS()||[i.DESKTOP_SAFARI,i.MOBILE_SAFARI].includes(getBrowserName()))throw new Error(\"Skip createImageBitmap on IOS and Safari\");return createImageBitmap(e).then((function(e){try{return a=e,$Try_2_Post()}catch(e){return $Try_2_Catch()}}),$Try_2_Catch)}catch(e){$Try_2_Catch()}}))}function canvasToFile(e,t,i,o,a=1){return new Promise((function(s,f){let l;if(\"image/png\"===t){let c,u,h;return c=e.getContext(\"2d\"),({data:u}=c.getImageData(0,0,e.width,e.height)),h=UPNG.encode([u.buffer],e.width,e.height,4096*a),l=new Blob([h],{type:t}),l.name=i,l.lastModified=o,$If_4.call(this)}{if(\"image/bmp\"===t)return new Promise((t=>r.toBlob(e,t))).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_5.call(this)}catch(e){return f(e)}}.bind(this),f);{if(\"function\"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return e.convertToBlob({type:t,quality:a}).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f);{let d;return d=e.toDataURL(t,a),getFilefromDataUrl(d,i,o).then(function(e){try{return l=e,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f)}function $If_6(){return $If_5.call(this)}}function $If_5(){return $If_4.call(this)}}function $If_4(){return s(l)}}))}function cleanupCanvasMemory(e){e.width=0,e.height=0}function isAutoOrientationInBrowser(){return new Promise((function(e,t){let r,i,o,a,s;return void 0!==isAutoOrientationInBrowser.cachedResult?e(isAutoOrientationInBrowser.cachedResult):(r=\"data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==\",getFilefromDataUrl(\"data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==\",\"test.jpg\",Date.now()).then((function(r){try{return i=r,drawFileInCanvas(i).then((function(r){try{return o=r[1],canvasToFile(o,i.type,i.name,i.lastModified).then((function(r){try{return a=r,cleanupCanvasMemory(o),drawFileInCanvas(a).then((function(r){try{return s=r[0],isAutoOrientationInBrowser.cachedResult=1===s.width&&2===s.height,e(isAutoOrientationInBrowser.cachedResult)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t))}))}function getExifOrientation(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=e=>{const r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return t(-2);const i=r.byteLength;let o=2;for(;o<i;){if(r.getUint16(o+2,!1)<=8)return t(-1);const e=r.getUint16(o,!1);if(o+=2,65505==e){if(1165519206!=r.getUint32(o+=2,!1))return t(-1);const e=18761==r.getUint16(o+=6,!1);o+=r.getUint32(o+4,e);const i=r.getUint16(o,e);o+=2;for(let a=0;a<i;a++)if(274==r.getUint16(o+12*a,e))return t(r.getUint16(o+12*a+8,e))}else{if(65280!=(65280&e))break;o+=r.getUint16(o,!1)}}return t(-1)},i.onerror=e=>r(e),i.readAsArrayBuffer(e)}))}function handleMaxWidthOrHeight(e,t){const{width:r}=e,{height:i}=e,{maxWidthOrHeight:o}=t;let a,s=e;return isFinite(o)&&(r>o||i>o)&&([s,a]=getNewCanvasAndCtx(r,i),r>i?(s.width=o,s.height=i/r*o):(s.width=r/i*o,s.height=o),a.drawImage(e,0,0,s.width,s.height),cleanupCanvasMemory(e)),s}function followExifOrientation(e,t){const{width:r}=e,{height:i}=e,[o,a]=getNewCanvasAndCtx(r,i);switch(t>4&&t<9?(o.width=i,o.height=r):(o.width=r,o.height=i),t){case 2:a.transform(-1,0,0,1,r,0);break;case 3:a.transform(-1,0,0,-1,r,i);break;case 4:a.transform(1,0,0,-1,0,i);break;case 5:a.transform(0,1,1,0,0,0);break;case 6:a.transform(0,1,-1,0,i,0);break;case 7:a.transform(0,-1,-1,0,i,r);break;case 8:a.transform(0,-1,1,0,0,r)}return a.drawImage(e,0,0,r,i),cleanupCanvasMemory(e),o}function compress(e,t,r=0){return new Promise((function(i,o){let a,s,f,l,c,u,h,d,A,g,p,m,w,v,b,y,E,F,_,B;function incProgress(e=5){if(t.signal&&t.signal.aborted)throw t.signal.reason;a+=e,t.onProgress(Math.min(a,100))}function setProgress(e){if(t.signal&&t.signal.aborted)throw t.signal.reason;a=Math.min(Math.max(e,a),100),t.onProgress(a)}return a=r,s=t.maxIteration||10,f=1024*t.maxSizeMB*1024,incProgress(),drawFileInCanvas(e,t).then(function(r){try{return[,l]=r,incProgress(),c=handleMaxWidthOrHeight(l,t),incProgress(),new Promise((function(r,i){var o;if(!(o=t.exifOrientation))return getExifOrientation(e).then(function(e){try{return o=e,$If_2.call(this)}catch(e){return i(e)}}.bind(this),i);function $If_2(){return r(o)}return $If_2.call(this)})).then(function(r){try{return u=r,incProgress(),isAutoOrientationInBrowser().then(function(r){try{return h=r?c:followExifOrientation(c,u),incProgress(),d=t.initialQuality||1,A=t.fileType||e.type,canvasToFile(h,A,e.name,e.lastModified,d).then(function(r){try{{if(g=r,incProgress(),p=g.size>f,m=g.size>e.size,!p&&!m)return setProgress(100),i(g);var a;function $Loop_3(){if(s--&&(b>f||b>w)){let t,r;return t=B?.95*_.width:_.width,r=B?.95*_.height:_.height,[E,F]=getNewCanvasAndCtx(t,r),F.drawImage(_,0,0,t,r),d*=\"image/png\"===A?.85:.95,canvasToFile(E,A,e.name,e.lastModified,d).then((function(e){try{return y=e,cleanupCanvasMemory(_),_=E,b=y.size,setProgress(Math.min(99,Math.floor((v-b)/(v-f)*100))),$Loop_3}catch(e){return o(e)}}),o)}return[1]}return w=e.size,v=g.size,b=v,_=h,B=!t.alwaysKeepResolution&&p,(a=function(e){for(;e;){if(e.then)return void e.then(a,o);try{if(e.pop){if(e.length)return e.pop()?$Loop_3_exit.call(this):e;e=$Loop_3}else e=e.call(this)}catch(e){return o(e)}}}.bind(this))($Loop_3);function $Loop_3_exit(){return cleanupCanvasMemory(_),cleanupCanvasMemory(E),cleanupCanvasMemory(c),cleanupCanvasMemory(h),cleanupCanvasMemory(l),setProgress(100),i(y)}}}catch(u){return o(u)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}))}const l=\"\\nlet scriptImported = false\\nself.addEventListener('message', async (e) => {\\n const { file, id, imageCompressionLibUrl, options } = e.data\\n options.onProgress = (progress) => self.postMessage({ progress, id })\\n try {\\n if (!scriptImported) {\\n // console.log('[worker] importScripts', imageCompressionLibUrl)\\n self.importScripts(imageCompressionLibUrl)\\n scriptImported = true\\n }\\n // console.log('[worker] self', self)\\n const compressedFile = await imageCompression(file, options)\\n self.postMessage({ file: compressedFile, id })\\n } catch (e) {\\n // console.error('[worker] error', e)\\n self.postMessage({ error: e.message + '\\\\n' + e.stack, id })\\n }\\n})\\n\";let c;function compressOnWebWorker(e,t){return new Promise(((r,i)=>{c||(c=function createWorkerScriptURL(e){const t=[];return\"function\"==typeof e?t.push(`(${e})()`):t.push(e),URL.createObjectURL(new Blob(t))}(l));const o=new Worker(c);o.addEventListener(\"message\",(function handler(e){if(t.signal&&t.signal.aborted)o.terminate();else if(void 0===e.data.progress){if(e.data.error)return i(new Error(e.data.error)),void o.terminate();r(e.data.file),o.terminate()}else t.onProgress(e.data.progress)})),o.addEventListener(\"error\",i),t.signal&&t.signal.addEventListener(\"abort\",(()=>{i(t.signal.reason),o.terminate()})),o.postMessage({file:e,imageCompressionLibUrl:t.libURL,options:{...t,onProgress:void 0,signal:void 0}})}))}function imageCompression(e,t){return new Promise((function(r,i){let o,a,s,f,l,c;if(o={...t},s=0,({onProgress:f}=o),o.maxSizeMB=o.maxSizeMB||Number.POSITIVE_INFINITY,l=\"boolean\"!=typeof o.useWebWorker||o.useWebWorker,delete o.useWebWorker,o.onProgress=e=>{s=e,\"function\"==typeof f&&f(s)},!(e instanceof Blob||e instanceof CustomFile))return i(new Error(\"The file given is not an instance of Blob or File\"));if(!/^image/.test(e.type))return i(new Error(\"The file given is not an image\"));if(c=\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!l||\"function\"!=typeof Worker||c)return compress(e,o).then(function(e){try{return a=e,$If_4.call(this)}catch(e){return i(e)}}.bind(this),i);var u=function(){try{return $If_4.call(this)}catch(e){return i(e)}}.bind(this),$Try_1_Catch=function(t){try{return compress(e,o).then((function(e){try{return a=e,u()}catch(e){return i(e)}}),i)}catch(e){return i(e)}};try{return o.libURL=o.libURL||\"https://cdn.jsdelivr.net/npm/[email protected]/dist/browser-image-compression.js\",compressOnWebWorker(e,o).then((function(e){try{return a=e,u()}catch(e){return $Try_1_Catch()}}),$Try_1_Catch)}catch(e){$Try_1_Catch()}function $If_4(){try{a.name=e.name,a.lastModified=e.lastModified}catch(e){}try{o.preserveExif&&\"image/jpeg\"===e.type&&(!o.fileType||o.fileType&&o.fileType===e.type)&&(a=copyExifWithoutOrientation(e,a))}catch(e){}return r(a)}}))}imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation,imageCompression.cleanupCanvasMemory=cleanupCanvasMemory,imageCompression.isAutoOrientationInBrowser=isAutoOrientationInBrowser,imageCompression.approximateBelowMaximumCanvasSizeOfBrowser=approximateBelowMaximumCanvasSizeOfBrowser,imageCompression.copyExifWithoutOrientation=copyExifWithoutOrientation,imageCompression.getBrowserName=getBrowserName,imageCompression.version=\"2.0.2\";\n//# sourceMappingURL=browser-image-compression.mjs.map\n\n\n//# sourceURL=webpack:///./node_modules/browser-image-compression/dist/browser-image-compression.mjs?"); 90 91 /***/ }), 92 93 /***/ "./node_modules/wasm-feature-detect/dist/esm/index.js": 94 /*!************************************************************!*\ 95 !*** ./node_modules/wasm-feature-detect/dist/esm/index.js ***! 96 \************************************************************/ 97 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 98 99 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"bigInt\": () => (/* binding */ bigInt),\n/* harmony export */ \"bulkMemory\": () => (/* binding */ bulkMemory),\n/* harmony export */ \"exceptions\": () => (/* binding */ exceptions),\n/* harmony export */ \"extendedConst\": () => (/* binding */ extendedConst),\n/* harmony export */ \"gc\": () => (/* binding */ gc),\n/* harmony export */ \"memory64\": () => (/* binding */ memory64),\n/* harmony export */ \"multiValue\": () => (/* binding */ multiValue),\n/* harmony export */ \"mutableGlobals\": () => (/* binding */ mutableGlobals),\n/* harmony export */ \"referenceTypes\": () => (/* binding */ referenceTypes),\n/* harmony export */ \"relaxedSimd\": () => (/* binding */ relaxedSimd),\n/* harmony export */ \"saturatedFloatToInt\": () => (/* binding */ saturatedFloatToInt),\n/* harmony export */ \"signExtensions\": () => (/* binding */ signExtensions),\n/* harmony export */ \"simd\": () => (/* binding */ simd),\n/* harmony export */ \"streamingCompilation\": () => (/* binding */ streamingCompilation),\n/* harmony export */ \"tailCall\": () => (/* binding */ tailCall),\n/* harmony export */ \"threads\": () => (/* binding */ threads)\n/* harmony export */ });\nconst bigInt=()=>(async e=>{try{return(await WebAssembly.instantiate(e)).instance.exports.b(BigInt(0))===BigInt(0)}catch(e){return!1}})(new Uint8Array([0,97,115,109,1,0,0,0,1,6,1,96,1,126,1,126,3,2,1,0,7,5,1,1,98,0,0,10,6,1,4,0,32,0,11])),bulkMemory=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,3,1,0,1,10,14,1,12,0,65,0,65,0,65,0,252,10,0,0,11])),exceptions=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,6,64,25,11,11])),extendedConst=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,5,3,1,0,1,11,9,1,0,65,1,65,2,106,11,0])),gc=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,10,2,95,1,125,0,96,0,1,107,0,3,2,1,1,10,12,1,10,0,67,0,0,0,0,251,7,0,11])),memory64=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,5,3,1,4,1])),multiValue=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,6,1,96,0,2,127,127,3,2,1,0,10,8,1,6,0,65,0,65,0,11])),mutableGlobals=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,2,8,1,1,97,1,98,3,127,1,6,6,1,127,1,65,0,11,7,5,1,1,97,3,1])),referenceTypes=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,7,1,5,0,208,112,26,11])),relaxedSimd=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,15,1,13,0,65,1,253,15,65,2,253,15,253,128,2,11])),saturatedFloatToInt=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,12,1,10,0,67,0,0,0,0,252,0,26,11])),signExtensions=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,65,0,192,26,11])),simd=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11])),streamingCompilation=()=>(async()=>\"compileStreaming\"in WebAssembly)(),tailCall=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,6,1,4,0,18,0,11])),threads=()=>(async e=>{try{return\"undefined\"!=typeof MessageChannel&&(new MessageChannel).port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(e)}catch(e){return!1}})(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]));\n\n\n//# sourceURL=webpack:///./node_modules/wasm-feature-detect/dist/esm/index.js?"); 50 100 51 101 /***/ }) … … 93 143 /******/ })(); 94 144 /******/ 145 /******/ /* webpack/runtime/ensure chunk */ 146 /******/ (() => { 147 /******/ __webpack_require__.f = {}; 148 /******/ // This file contains only the entry chunk. 149 /******/ // The chunk loading function for additional chunks 150 /******/ __webpack_require__.e = (chunkId) => { 151 /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { 152 /******/ __webpack_require__.f[key](chunkId, promises); 153 /******/ return promises; 154 /******/ }, [])); 155 /******/ }; 156 /******/ })(); 157 /******/ 95 158 /******/ /* webpack/runtime/get javascript chunk filename */ 96 159 /******/ (() => { … … 117 180 /******/ (() => { 118 181 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 182 /******/ })(); 183 /******/ 184 /******/ /* webpack/runtime/load script */ 185 /******/ (() => { 186 /******/ var inProgress = {}; 187 /******/ // data-webpack is not used as build has no uniqueName 188 /******/ // loadScript function to load a script via script tag 189 /******/ __webpack_require__.l = (url, done, key, chunkId) => { 190 /******/ if(inProgress[url]) { inProgress[url].push(done); return; } 191 /******/ var script, needAttach; 192 /******/ if(key !== undefined) { 193 /******/ var scripts = document.getElementsByTagName("script"); 194 /******/ for(var i = 0; i < scripts.length; i++) { 195 /******/ var s = scripts[i]; 196 /******/ if(s.getAttribute("src") == url) { script = s; break; } 197 /******/ } 198 /******/ } 199 /******/ if(!script) { 200 /******/ needAttach = true; 201 /******/ script = document.createElement('script'); 202 /******/ 203 /******/ script.charset = 'utf-8'; 204 /******/ script.timeout = 120; 205 /******/ if (__webpack_require__.nc) { 206 /******/ script.setAttribute("nonce", __webpack_require__.nc); 207 /******/ } 208 /******/ 209 /******/ script.src = url; 210 /******/ } 211 /******/ inProgress[url] = [done]; 212 /******/ var onScriptComplete = (prev, event) => { 213 /******/ // avoid mem leaks in IE. 214 /******/ script.onerror = script.onload = null; 215 /******/ clearTimeout(timeout); 216 /******/ var doneFns = inProgress[url]; 217 /******/ delete inProgress[url]; 218 /******/ script.parentNode && script.parentNode.removeChild(script); 219 /******/ doneFns && doneFns.forEach((fn) => (fn(event))); 220 /******/ if(prev) return prev(event); 221 /******/ } 222 /******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); 223 /******/ script.onerror = onScriptComplete.bind(null, script.onerror); 224 /******/ script.onload = onScriptComplete.bind(null, script.onload); 225 /******/ needAttach && document.head.appendChild(script); 226 /******/ }; 119 227 /******/ })(); 120 228 /******/ … … 161 269 /******/ }; 162 270 /******/ 163 /******/ // no chunk on demand loading 271 /******/ __webpack_require__.f.j = (chunkId, promises) => { 272 /******/ // JSONP chunk loading for javascript 273 /******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined; 274 /******/ if(installedChunkData !== 0) { // 0 means "already installed". 275 /******/ 276 /******/ // a Promise means "currently loading". 277 /******/ if(installedChunkData) { 278 /******/ promises.push(installedChunkData[2]); 279 /******/ } else { 280 /******/ if(true) { // all chunks have JS 281 /******/ // setup Promise in chunk cache 282 /******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject])); 283 /******/ promises.push(installedChunkData[2] = promise); 284 /******/ 285 /******/ // start chunk loading 286 /******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId); 287 /******/ // create error before stack unwound to get useful stacktrace later 288 /******/ var error = new Error(); 289 /******/ var loadingEnded = (event) => { 290 /******/ if(__webpack_require__.o(installedChunks, chunkId)) { 291 /******/ installedChunkData = installedChunks[chunkId]; 292 /******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined; 293 /******/ if(installedChunkData) { 294 /******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); 295 /******/ var realSrc = event && event.target && event.target.src; 296 /******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'; 297 /******/ error.name = 'ChunkLoadError'; 298 /******/ error.type = errorType; 299 /******/ error.request = realSrc; 300 /******/ installedChunkData[1](error); 301 /******/ } 302 /******/ } 303 /******/ }; 304 /******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId); 305 /******/ } else installedChunks[chunkId] = 0; 306 /******/ } 307 /******/ } 308 /******/ }; 164 309 /******/ 165 310 /******/ // no prefetching … … 173 318 /******/ // no on chunks loaded 174 319 /******/ 175 /******/ // no jsonp function 320 /******/ // install a JSONP callback for chunk loading 321 /******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { 322 /******/ var [chunkIds, moreModules, runtime] = data; 323 /******/ // add "moreModules" to the modules object, 324 /******/ // then flag all "chunkIds" as loaded and fire callback 325 /******/ var moduleId, chunkId, i = 0; 326 /******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { 327 /******/ for(moduleId in moreModules) { 328 /******/ if(__webpack_require__.o(moreModules, moduleId)) { 329 /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; 330 /******/ } 331 /******/ } 332 /******/ if(runtime) var result = runtime(__webpack_require__); 333 /******/ } 334 /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); 335 /******/ for(;i < chunkIds.length; i++) { 336 /******/ chunkId = chunkIds[i]; 337 /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { 338 /******/ installedChunks[chunkId][0](); 339 /******/ } 340 /******/ installedChunks[chunkId] = 0; 341 /******/ } 342 /******/ 343 /******/ } 344 /******/ 345 /******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || []; 346 /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); 347 /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); 176 348 /******/ })(); 177 349 /******/ -
squeeze/trunk/assets/js/script.bundle.js
r3311866 r3345284 17 17 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 18 18 19 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"handleBulkButtonClick\": () => (/* binding */ handleBulkButtonClick),\n/* harmony export */ \"handleBulkFromPage\": () => (/* binding */ handleBulkFromPage),\n/* harmony export */ \"handleBulkToggle\": () => (/* binding */ handleBulkToggle),\n/* harmony export */ \"handleButtonsClick\": () => (/* binding */ handleButtonsClick),\n/* harmony export */ \"handleClosePathDialog\": () => (/* binding */ handleClosePathDialog),\n/* harmony export */ \"handle DirectoryCheck\": () => (/* binding */ handleDirectoryCheck),\n/* harmony export */ \"handleDirectoryClick\": () => (/* binding */ handleDirectoryClick),\n/* harmony export */ \"handleFetchImagesFromPage\": () => (/* binding */ handleFetchImagesFromPage),\n/* harmony export */ \"handleMultiFileFormUpload\": () => (/* binding */ handleMultiFileFormUpload),\n/* harmony export */ \"handleOnLeave\": () => (/* binding */ handleOnLeave),\n/* harmony export */ \"handleRecursiveUpload\": () => (/* binding */ handleRecursiveUpload),\n/* harmony export */ \"handleRestoreBtnClick\": () => (/* binding */ handleRestoreBtnClick),\n/* harmony export */ \"handleSingleBtnClick\": () => (/* binding */ handleSingleBtnClick)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](squeezeOptions);\r\n\r\nconst updateUI = (initId, response) => {\r\n const statusEl = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.postsFilterForm?.querySelector(`#post-${initId} .column-squeeze .squeeze_status`);\r\n if (statusEl) statusEl.innerHTML = response.data;\r\n\r\n const gridItem = document.querySelector(`.media-frame.mode-grid .attachment[data-id=\"${initId}\"]`);\r\n if (gridItem) {\r\n const centered = gridItem.querySelector('.centered');\r\n const progress = gridItem.querySelector('.media-progress-bar');\r\n if (centered) centered.style.display = 'block';\r\n if (progress) progress.remove();\r\n gridItem.classList.remove('uploading');\r\n }\r\n};\r\n\r\nconst getTotalPages = (path) => {\r\n const selectors = {\r\n uncompressed: \"input[name='squeeze_bulk_uncompressed_pages']\",\r\n all: \"input[name='squeeze_bulk_total_pages']\"\r\n };\r\n const sel = selectors[path];\r\n const val = sel && document.querySelector(sel)?.value;\r\n return Number(val) || 1;\r\n};\r\n\r\nconst checkPaused = (data, page) => {\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused) return false;\r\n handleBulkPause(data, page);\r\n return true;\r\n};\r\n\r\nconst logAndThumbnail = async (filename, response, wrapper) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(response.data, {\r\n mediaLogWrapper: wrapper,\r\n iconId: response.success ? 'check-mark-circle-icon' : 'ban-sign-icon'\r\n });\r\n\r\n const titleEl = wrapper.querySelector('h3');\r\n if (titleEl && response.filename) {\r\n titleEl.textContent = `${__('Media', 'squeeze')} ${filename} (${response.filename}):`;\r\n }\r\n\r\n const thumbUrl = response.sizes?.thumbnail?.url || response.url;\r\n if (thumbUrl) {\r\n const thumb = document.createElement('div');\r\n thumb.classList.add('media-log-thumbnail');\r\n thumb.innerHTML = `<img src=\"${thumbUrl}\" alt=\"${filename}\"/>`;\r\n wrapper.appendChild(thumb);\r\n }\r\n};\r\n\r\nconst handleDirectoryCheck = (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.savePathBtn.disabled = !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.dirContainer.querySelector(\"input[type='checkbox']:checked\");\r\n};\r\n\r\nconst handleClosePathDialog = (event) => {\r\n if (!event.target.contains(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog)) return;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog.close();\r\n};\r\n\r\nconst handleBulkToggle = (event, process, mediaIDs, page = 1) => {\r\n const isPaused = event.target.dataset.running === 'true';\r\n\r\n event.target.dataset.running = isPaused ? 'false' : 'true';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, isPaused ? __('Resume bulk squeezing', 'squeeze') : __('Pause bulk squeezing', 'squeeze'), isPaused ? '#play-button-round-icon' : '#pause-button-icon');\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused = isPaused;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process = process;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = mediaIDs;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = page;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target = event.target;\r\n\r\n console.log('handleBulkToggle', _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData);\r\n\r\n return isPaused;\r\n};\r\n\r\n// Handle single compress button click\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleSingleBtnClick = async (event, Squeeze) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n const squeezeStatus = event.target.closest(\"td\").querySelector(\".squeeze_status\");\r\n\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async (data) => {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const response = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n //squeezeStatus.innerHTML = response?.data?.message ?? response;\r\n squeezeStatus.innerHTML = response?.data ?? response;\r\n\r\n if (event.target.closest(\"td.field\")) {\r\n const table = event.target.closest(\"td\")?.querySelector(\".squeeze_status .squeeze-comparison-table\");\r\n if (table) {\r\n const td = document.createElement(\"td\");\r\n td.classList.add(\"field\");\r\n td.style.width = \"100%\";\r\n td.appendChild(table);\r\n event.target.closest(\"tr\").appendChild(td);\r\n }\r\n }\r\n // TBD: add file size label to the attachment info\r\n /*\r\n if (event.target.closest('.attachment-info')) {\r\n const fileSizeLabel = event.target.closest('.attachment-info').querySelector('.file-size');\r\n if (fileSizeLabel) {\r\n const fileSize = response?.data?.sizes?.scaled?.compressed_size ?? response?.data?.sizes?.original?.compressed_size ?? null;\r\n if (fileSize) {\r\n const humanFileSize = SqueezeHelpers.humanFileSize(fileSize, true);\r\n fileSizeLabel.innerHTML = fileSizeLabel.innerHTML.replace(/(<\\/strong>\\s*)(.*)/, `$1${humanFileSize}`);\r\n }\r\n }\r\n }\r\n */\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error;\r\n } finally {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.removeAllButtons(event.target.closest(\"td\")?.querySelectorAll(`button`));\r\n window.onbeforeunload = null;\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error;\r\n event.target.remove();\r\n }\r\n};\r\n\r\nconst handleRestoreBtnClick = async (event) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n\r\n event.target.disabled = true;\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Restore in process...', 'squeeze');\r\n\r\n try {\r\n const response = await Squeeze.handleRestore(attachmentID);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = response.data;\r\n } catch (error) {\r\n console.error(error);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = error;\r\n } finally {\r\n event.target.closest('td').querySelector(`[name='squeeze_compress_again']`).disabled = false;\r\n event.target.remove();\r\n window.onbeforeunload = null;\r\n }\r\n};\r\n\r\nconst handleBulkButtonClick = async (event, process, mediaIDs, currentPage) => {\r\n if (mediaIDs.length === 0) return;\r\n\r\n const totalPages = getTotalPages(process);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableBulkButtons();\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process === process) {\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs/*.length > 0*/) {\r\n mediaIDs = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs;\r\n }\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page) {\r\n currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page;\r\n }\r\n }\r\n\r\n const isPaused = handleBulkToggle(event, process, mediaIDs, currentPage);\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await handleRecursiveUpload(process, mediaIDs, currentPage, true);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0 && finalResponse.page >= totalPages) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n};\r\n\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleButtonsClick = async (event, Squeeze) => {\r\n const singleBtnName = 'squeeze_compress_single';\r\n const compressAgainBtnName = 'squeeze_compress_again';\r\n const restoreBtnName = 'squeeze_restore';\r\n\r\n if (event.target.getAttribute(\"name\") === singleBtnName || event.target.getAttribute(\"name\") === compressAgainBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Squeezing...', 'squeeze');\r\n window.onbeforeunload = handleOnLeave;\r\n handleSingleBtnClick(event, Squeeze);\r\n }\r\n\r\n if (event.target.getAttribute(\"name\") === restoreBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n window.onbeforeunload = handleOnLeave;\r\n handleRestoreBtnClick(event);\r\n }\r\n};\r\n\r\nconst handleDirectoryClick = async (event) => {\r\n if (event.target !== event.currentTarget) return;\r\n\r\n const currentDir = event.target.closest(\".directory-item\");\r\n const currentPath = currentDir.dataset.path;\r\n const parentPath = currentDir.dataset.parent;\r\n\r\n if (parentPath === '/' || currentDir.classList.contains(\"loading\")) return;\r\n\r\n if (currentDir.classList.contains(\"loaded\")) {\r\n currentDir.classList.toggle(\"opened\");\r\n return;\r\n }\r\n\r\n currentDir.classList.add(\"loading\");\r\n\r\n const subDirs = await Squeeze.getDirectories(currentPath);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.renderDirectories(subDirs, currentDir, {\r\n handleDirectoryClick,\r\n handleDirectoryCheck\r\n });\r\n\r\n currentDir.classList.remove(\"loading\");\r\n currentDir.classList.add(\"loaded\", \"opened\");\r\n}\r\n\r\n/**\r\n * Hadnle warning on page leave\r\n*/\r\nconst handleOnLeave = () => {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const page = urlParams.get('page');\r\n const isUploadPage = window.location.href.includes('upload.php');\r\n const isMediaNewPage = window.location.href.includes('media-new.php');\r\n const isAttachmentPage = window.location.href.includes('post.php') && urlParams.get('action') === 'edit';\r\n\r\n if (page === 'squeeze-bulk' || isMediaNewPage || isAttachmentPage) {\r\n return __('Are you sure you want to leave this page? The squeezing process will be terminated!', 'squeeze');\r\n }\r\n if (isUploadPage) {\r\n return __('Are you sure you want to leave this page? The settings will not be saved!', 'squeeze');\r\n }\r\n};\r\n\r\nconst handleBulkPause = (data, currentPage) => {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(__('Bulk squeezing has been paused!', 'squeeze'), { isPause: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = data;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = currentPage;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target.disabled = false;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target, __('Resume bulk squeezing', 'squeeze'), '#play-button-round-icon');\r\n};\r\n\r\nconst handleUpdateChart = (uncompressedImagesCount) => {\r\n const chartValue = document.querySelector(\".squeeze-bulk-media-stats-chart-value > text\");\r\n const chartBar = document.querySelector(\".squeeze-bulk-media-stats-chart\");\r\n const squeezedImages = document.querySelector(\".squeeze-bulk-media-stats-item-value\");\r\n\r\n if (!chartValue || !chartBar) return;\r\n\r\n const imagesLeft = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages - uncompressedImagesCount;\r\n const percentage = parseFloat((imagesLeft / _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages) * 100).toFixed(2);\r\n const dasharray = percentage * 560 / 100;\r\n chartValue.textContent = `${percentage}%`;\r\n chartBar.style.setProperty('--squeeze-dasharray', dasharray);\r\n\r\n if (squeezedImages) {\r\n squeezedImages.textContent = `${imagesLeft} / ${_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages}`;\r\n }\r\n};\r\n\r\nconst handleRecursiveUpload = async (path, data, currentPage, isUpdateChart = false) => {\r\n\r\n if (!Array.isArray(data)) return { success: false, data: 'No data provided!', mediaIDs: [] }; // when bulk directory path has no images\r\n \r\n const totalPages = getTotalPages(path);\r\n\r\n if (data.length === 0) {\r\n currentPage += 1;\r\n if (currentPage > totalPages || !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId) return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n }\r\n }\r\n\r\n const initData = [...data]; // initial data\r\n\r\n const filename = data[0]?.filename ? data[0].filename : `ID #${data[0]}`;\r\n const mediaLogWrapper = await _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${__('Start squeezing...', 'squeeze')}`, { title: filename, isStart: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId = data[0] || 0; // update lastId to the last processed ID\r\n\r\n try {\r\n const response = await Squeeze.handleBulkUpload(path, data);\r\n\r\n await logAndThumbnail(filename, response, mediaLogWrapper);\r\n\r\n if (isUpdateChart && path !== 'all') {\r\n let uncompressedImagesCount = 0;\r\n if (path === 'uncompressed') {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages - 1 || 0;\r\n uncompressedImagesCount = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages;\r\n } else if (path === 'path') {\r\n uncompressedImagesCount = response.mediaIDs.length;\r\n }\r\n handleUpdateChart(uncompressedImagesCount);\r\n }\r\n\r\n if (checkPaused(data, currentPage)) {\r\n return { success: false, data: 'Process has been paused!', mediaIDs: data, page: currentPage };\r\n }\r\n\r\n updateUI(initData[0], response);\r\n\r\n if (response.mediaIDs.length > 0) {\r\n return handleRecursiveUpload(path, response.mediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { ...response, page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${error}`, { mediaLogWrapper, iconId: 'ban-sign-icon' });\r\n\r\n if (data.length > 0) {\r\n return handleRecursiveUpload(path, data, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { success: false, data: error, mediaIDs: [], page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n\r\nconst handleMultiFileFormUpload = (compressOptions) => {\r\n if (typeof wpUploaderInit === 'undefined' || typeof plupload === 'undefined' || typeof uploader === 'undefined') return;\r\n\r\n const SqueezeUploader = uploader;\r\n\r\n SqueezeUploader.bind('FilesAdded', function (up, files) { });\r\n\r\n SqueezeUploader.bind('FileUploaded', function (up, file, response) {\r\n const fileMime = file.type;\r\n const fileType = fileMime.split('/')[0];\r\n const fileSubType = fileMime.split('/')[1];\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) return;\r\n\r\n const fileID = file.id;\r\n const attachmentID = response.response;\r\n const mediaItem = document.getElementById(`media-item-${fileID}`);\r\n\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n /**\r\n * Wait for media item to load( 'async-upload.php' )\r\n * Ping every 1 second until the media item is loaded\r\n * @returns Promise\r\n */\r\n const waitForItemLoad = () => {\r\n return new Promise((resolve) => {\r\n let interval = setInterval(() => {\r\n if (mediaItem.querySelector('.media-item-wrapper')) {\r\n mediaItem.querySelector('.media-item-wrapper').innerHTML += `\r\n <div class=\"progress\">\r\n <div class=\"percent\">${__('Squeezing...', 'squeeze')}</div>\r\n <div class=\"bar\" style=\"width: 200px;\"></div>\r\n </div>\r\n `;\r\n clearInterval(interval);\r\n resolve();\r\n }\r\n }, 1000);\r\n });\r\n };\r\n\r\n waitForItemLoad().then(() => {\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async function (data) {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n window.onbeforeunload = null;\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${uploadData.data}</div>`;\r\n mediaItem.querySelector('.progress')?.remove();\r\n } else {\r\n alert(uploadData?.data ?? uploadData);\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n });\r\n\r\n SqueezeUploader.bind('UploadComplete', function (up, files) { });\r\n};\n\n//# sourceURL=webpack:///./assets/js/handlers.js?");19 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"handleBulkButtonClick\": () => (/* binding */ handleBulkButtonClick),\n/* harmony export */ \"handleBulkFromPage\": () => (/* binding */ handleBulkFromPage),\n/* harmony export */ \"handleBulkToggle\": () => (/* binding */ handleBulkToggle),\n/* harmony export */ \"handleButtonsClick\": () => (/* binding */ handleButtonsClick),\n/* harmony export */ \"handleClosePathDialog\": () => (/* binding */ handleClosePathDialog),\n/* harmony export */ \"handleCompressBeforeUpload\": () => (/* binding */ handleCompressBeforeUpload),\n/* harmony export */ \"handleDirectoryCheck\": () => (/* binding */ handleDirectoryCheck),\n/* harmony export */ \"handleDirectoryClick\": () => (/* binding */ handleDirectoryClick),\n/* harmony export */ \"handleFetchImagesFromPage\": () => (/* binding */ handleFetchImagesFromPage),\n/* harmony export */ \"handleMultiFileFormUpload\": () => (/* binding */ handleMultiFileFormUpload),\n/* harmony export */ \"handleOnLeave\": () => (/* binding */ handleOnLeave),\n/* harmony export */ \"handleRecursiveUpload\": () => (/* binding */ handleRecursiveUpload),\n/* harmony export */ \"handleRestoreBtnClick\": () => (/* binding */ handleRestoreBtnClick),\n/* harmony export */ \"handleSingleBtnClick\": () => (/* binding */ handleSingleBtnClick)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](squeezeOptions);\r\n\r\nconst updateUI = (initId, response) => {\r\n const statusEl = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.postsFilterForm?.querySelector(`#post-${initId} .column-squeeze .squeeze_status`);\r\n if (statusEl) statusEl.innerHTML = response?.data?.message ?? response?.data ?? response;\r\n\r\n const gridItem = document.querySelector(`.media-frame.mode-grid .attachment[data-id=\"${initId}\"]`);\r\n if (gridItem) {\r\n const centered = gridItem.querySelector('.centered');\r\n const progress = gridItem.querySelector('.media-progress-bar');\r\n if (centered) centered.style.display = 'block';\r\n if (progress) progress.remove();\r\n gridItem.classList.remove('uploading');\r\n }\r\n};\r\n\r\nconst getTotalPages = (path) => {\r\n const selectors = {\r\n uncompressed: \"input[name='squeeze_bulk_uncompressed_pages']\",\r\n all: \"input[name='squeeze_bulk_total_pages']\"\r\n };\r\n const sel = selectors[path];\r\n const val = sel && document.querySelector(sel)?.value;\r\n return Number(val) || 1;\r\n};\r\n\r\nconst checkPaused = (data, page) => {\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused) return false;\r\n handleBulkPause(data, page);\r\n return true;\r\n};\r\n\r\nconst logAndThumbnail = async (filename, response, wrapper) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(response?.data?.message ?? response?.data, {\r\n mediaLogWrapper: wrapper,\r\n iconId: response.success ? 'check-mark-circle-icon' : 'ban-sign-icon'\r\n });\r\n\r\n const titleEl = wrapper?.querySelector('h3');\r\n if (titleEl && response?.data?.filename) {\r\n titleEl.textContent = `${__('Media', 'squeeze')} ${filename} (${response.data.filename}):`;\r\n }\r\n\r\n const thumbUrl = response?.data?.sizes?.thumbnail?.url || response?.data?.url || response?.url;\r\n if (thumbUrl) {\r\n const thumb = document.createElement('div');\r\n thumb.classList.add('media-log-thumbnail');\r\n thumb.innerHTML = `<img src=\"${thumbUrl}\" alt=\"${filename}\"/>`;\r\n wrapper?.appendChild(thumb);\r\n }\r\n};\r\n\r\nconst handleDirectoryCheck = (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.savePathBtn.disabled = !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.dirContainer.querySelector(\"input[type='checkbox']:checked\");\r\n};\r\n\r\nconst handleClosePathDialog = (event) => {\r\n if (!event.target.contains(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog)) return;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.elements.pathDialog.close();\r\n};\r\n\r\nconst handleBulkToggle = (event, process, mediaIDs, page = 1) => {\r\n const isPaused = event.target.dataset.running === 'true';\r\n\r\n event.target.dataset.running = isPaused ? 'false' : 'true';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, isPaused ? __('Resume bulk squeezing', 'squeeze') : __('Pause bulk squeezing', 'squeeze'), isPaused ? '#play-button-round-icon' : '#pause-button-icon');\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.isPaused = isPaused;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process = process;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = mediaIDs;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = page;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target = event.target;\r\n\r\n //console.log('handleBulkToggle', cachedMediaData);\r\n\r\n return isPaused;\r\n};\r\n\r\n// Handle single compress button click\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleSingleBtnClick = async (event, Squeeze) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n const squeezeStatus = event.target.closest(\"td\").querySelector(\".squeeze_status\");\r\n\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async (data) => {\r\n const attachment = { attributes: data };\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const response = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n squeezeStatus.innerHTML = response?.data?.message ?? response?.data ?? response;\r\n\r\n if (event.target.closest(\"td.field\")) {\r\n const table = event.target.closest(\"td\")?.querySelector(\".squeeze_status .squeeze-comparison-table\");\r\n if (table) {\r\n const td = document.createElement(\"td\");\r\n td.classList.add(\"field\");\r\n td.style.width = \"100%\";\r\n td.appendChild(table);\r\n event.target.closest(\"tr\").appendChild(td);\r\n }\r\n }\r\n // TBD: add file size label to the attachment info\r\n /*\r\n if (event.target.closest('.attachment-info')) {\r\n const fileSizeLabel = event.target.closest('.attachment-info').querySelector('.file-size');\r\n if (fileSizeLabel) {\r\n const fileSize = response?.data?.sizes?.scaled?.compressed_size ?? response?.data?.sizes?.original?.compressed_size ?? null;\r\n if (fileSize) {\r\n const humanFileSize = SqueezeHelpers.humanFileSize(fileSize, true);\r\n fileSizeLabel.innerHTML = fileSizeLabel.innerHTML.replace(/(<\\/strong>\\s*)(.*)/, `$1${humanFileSize}`);\r\n }\r\n }\r\n }\r\n */\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error?.message ?? error;\r\n } finally {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.removeAllButtons(event.target.closest(\"td\")?.querySelectorAll(`button`));\r\n window.onbeforeunload = null;\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n squeezeStatus.innerHTML = error?.message ?? error;\r\n event.target.remove();\r\n }\r\n};\r\n\r\nconst handleRestoreBtnClick = async (event) => {\r\n const attachmentID = event.target.dataset.attachment;\r\n\r\n event.target.disabled = true;\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Restore in process...', 'squeeze');\r\n\r\n try {\r\n const response = await Squeeze.handleRestore(attachmentID);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = response?.data ?? response;\r\n } catch (error) {\r\n console.error(error);\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = error?.message ?? JSON.stringify(error, null, 2);\r\n } finally {\r\n event.target.closest('td').querySelector(`[name='squeeze_compress_again']`).disabled = false;\r\n event.target.remove();\r\n window.onbeforeunload = null;\r\n }\r\n};\r\n\r\nconst handleBulkButtonClick = async (event, process, mediaIDs, currentPage) => {\r\n if (mediaIDs.length === 0) return;\r\n\r\n const totalPages = getTotalPages(process);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableBulkButtons();\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.process === process) {\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs/*.length > 0*/) {\r\n mediaIDs = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs;\r\n }\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page) {\r\n currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page;\r\n }\r\n }\r\n\r\n const isPaused = handleBulkToggle(event, process, mediaIDs, currentPage);\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await handleRecursiveUpload(process, mediaIDs, currentPage, true);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0 && finalResponse.page >= totalPages) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n};\r\n\r\n// manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\nconst handleButtonsClick = async (event, Squeeze) => {\r\n const singleBtnName = 'squeeze_compress_single';\r\n const compressAgainBtnName = 'squeeze_compress_again';\r\n const restoreBtnName = 'squeeze_restore';\r\n\r\n if (event.target.getAttribute(\"name\") === singleBtnName || event.target.getAttribute(\"name\") === compressAgainBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n event.target.closest(\"td\").querySelector(\".squeeze_status\").innerHTML = '⏳ ' + __('Squeezing...', 'squeeze');\r\n window.onbeforeunload = handleOnLeave;\r\n handleSingleBtnClick(event, Squeeze);\r\n }\r\n\r\n if (event.target.getAttribute(\"name\") === restoreBtnName) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.disableAllButtons(event.target.closest(\"td\").querySelectorAll(`button`));\r\n window.onbeforeunload = handleOnLeave;\r\n handleRestoreBtnClick(event);\r\n }\r\n};\r\n\r\nconst handleDirectoryClick = async (event) => {\r\n if (event.target !== event.currentTarget) return;\r\n\r\n const currentDir = event.target.closest(\".directory-item\");\r\n const currentPath = currentDir.dataset.path;\r\n const parentPath = currentDir.dataset.parent;\r\n\r\n if (parentPath === '/' || currentDir.classList.contains(\"loading\")) return;\r\n\r\n if (currentDir.classList.contains(\"loaded\")) {\r\n currentDir.classList.toggle(\"opened\");\r\n return;\r\n }\r\n\r\n currentDir.classList.add(\"loading\");\r\n\r\n const subDirs = await Squeeze.getDirectories(currentPath);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.renderDirectories(subDirs, currentDir, {\r\n handleDirectoryClick,\r\n handleDirectoryCheck\r\n });\r\n\r\n currentDir.classList.remove(\"loading\");\r\n currentDir.classList.add(\"loaded\", \"opened\");\r\n}\r\n\r\n/**\r\n * Hadnle warning on page leave\r\n*/\r\nconst handleOnLeave = () => {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const page = urlParams.get('page');\r\n const isUploadPage = window.location.href.includes('upload.php');\r\n const isMediaNewPage = window.location.href.includes('media-new.php');\r\n const isAttachmentPage = window.location.href.includes('post.php') && urlParams.get('action') === 'edit';\r\n\r\n if (page === 'squeeze-bulk' || isMediaNewPage || isAttachmentPage) {\r\n return __('Are you sure you want to leave this page? The squeezing process will be terminated!', 'squeeze');\r\n }\r\n if (isUploadPage) {\r\n return __('Are you sure you want to leave this page? The settings will not be saved!', 'squeeze');\r\n }\r\n};\r\n\r\nconst handleBulkPause = (data, currentPage) => {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(__('Bulk squeezing has been paused!', 'squeeze'), { isPause: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.mediaIDs = data;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.page = currentPage;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target.disabled = false;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.updateButtonText(_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.target, __('Resume bulk squeezing', 'squeeze'), '#play-button-round-icon');\r\n};\r\n\r\nconst handleUpdateChart = (uncompressedImagesCount) => {\r\n const chartValue = document.querySelector(\".squeeze-bulk-media-stats-chart-value > text\");\r\n const chartBar = document.querySelector(\".squeeze-bulk-media-stats-chart\");\r\n const squeezedImages = document.querySelector(\".squeeze-bulk-media-stats-item-value\");\r\n\r\n if (!chartValue || !chartBar) return;\r\n\r\n const imagesLeft = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages - uncompressedImagesCount;\r\n const percentage = parseFloat((imagesLeft / _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages) * 100).toFixed(2);\r\n const dasharray = percentage * 560 / 100;\r\n chartValue.textContent = `${percentage}%`;\r\n chartBar.style.setProperty('--squeeze-dasharray', dasharray);\r\n\r\n if (squeezedImages) {\r\n squeezedImages.textContent = `${imagesLeft} / ${_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.totalImages}`;\r\n }\r\n};\r\n\r\nconst handleRecursiveUpload = async (path, data, currentPage, isUpdateChart = false) => {\r\n\r\n if (!Array.isArray(data)) return { success: false, data: 'No data provided!', mediaIDs: [] }; // when bulk directory path has no images\r\n\r\n const totalPages = getTotalPages(path);\r\n\r\n if (data.length === 0) {\r\n currentPage += 1;\r\n if (currentPage > totalPages || !_helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId) return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n return { success: true, data: __('No more images found!', 'squeeze'), mediaIDs: [], page: currentPage };\r\n }\r\n }\r\n\r\n const initData = [...data]; // initial data\r\n\r\n const filename = data[0]?.filename ? data[0].filename : `ID #${data[0]}`;\r\n const mediaLogWrapper = await _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${__('Start squeezing...', 'squeeze')}`, { title: filename, isStart: true });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.lastId = data[0] || 0; // update lastId to the last processed ID\r\n\r\n try {\r\n const response = await Squeeze.handleBulkUpload(path, data);\r\n\r\n //console.log('handleRecursiveUpload response', response);\r\n\r\n await logAndThumbnail(filename, response, mediaLogWrapper);\r\n\r\n if (isUpdateChart && path !== 'all') {\r\n let uncompressedImagesCount = 0;\r\n if (path === 'uncompressed') {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages - 1 || 0;\r\n uncompressedImagesCount = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.cachedMediaData.uncompressedImages;\r\n } else if (path === 'path') {\r\n uncompressedImagesCount = response.mediaIDs.length;\r\n }\r\n handleUpdateChart(uncompressedImagesCount);\r\n }\r\n\r\n if (checkPaused(data, currentPage)) {\r\n return { success: false, data: 'Process has been paused!', mediaIDs: data, page: currentPage };\r\n }\r\n\r\n updateUI(initData[0], response);\r\n\r\n if (response.mediaIDs.length > 0) {\r\n return handleRecursiveUpload(path, response.mediaIDs, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { ...response, page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n\r\n return response;\r\n\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.logMessage(`${error}`, { mediaLogWrapper, iconId: 'ban-sign-icon' });\r\n\r\n if (data.length > 0) {\r\n return handleRecursiveUpload(path, data, currentPage, isUpdateChart);\r\n } else {\r\n currentPage += 1;\r\n if (currentPage > totalPages) return { success: false, data: error, mediaIDs: [], page: currentPage };\r\n\r\n const lastId = initData[initData.length - 1];\r\n const maybeGetNextMediaIDs = await Squeeze.getNextAttachments(currentPage, path, lastId);\r\n if (maybeGetNextMediaIDs.success && maybeGetNextMediaIDs.data.length > 0) {\r\n const nextMediaIDs = maybeGetNextMediaIDs.data;\r\n return handleRecursiveUpload(path, nextMediaIDs, currentPage, isUpdateChart);\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n\r\n/**\r\n * Handles the compression of image before upload using Squeeze.\r\n * It compresses only the original image, not the thumbnails.\r\n * \r\n * @param {object} up - The plupload instance\r\n * @param {object} pluploadFile - The file to be compressed\r\n * @param {object} compressOptions - The compression options object\r\n * @returns {boolean} - Returns false to prevent further processing of the file\r\n */\r\nconst handleCompressBeforeUpload = async (up, pluploadFile, compressOptions) => {\r\n if (typeof Squeeze === 'undefined') return;\r\n if (typeof Squeeze.compressBeforeUpload !== 'function') {\r\n console.warn('Squeeze.compressBeforeUpload is not a function');\r\n return;\r\n }\r\n \r\n if (pluploadFile?._isSqueezed || pluploadFile?._isExcluded || pluploadFile?._isFailed) {\r\n //console.warn('File is already compressed:', pluploadFile);\r\n return; // Skip files that are already compressed\r\n }\r\n // Check if the file is an image based on its MIME type\r\n if (!pluploadFile.type.startsWith('image/')) {\r\n //console.warn('File is not an image:', pluploadFile.name);\r\n return; // Skip non-image files\r\n }\r\n\r\n const file = pluploadFile.getNative() || pluploadFile.getSource();\r\n\r\n const type = file?.type?.split('/')[0] ?? '';\r\n const subtype = file?.type?.split('/')[1] ?? '';\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(type, subtype, compressOptions)) {\r\n //console.warn('Skipping compression for:', pluploadFile.name);\r\n return; // Skip compression for this file\r\n }\r\n\r\n //console.time('BeforeUpload')\r\n\r\n up.stop();\r\n window.onbeforeunload = handleOnLeave;\r\n \r\n \r\n\r\n try {\r\n let originalFile = file;\r\n const base64Obj = await Squeeze.compressBeforeUpload(file);\r\n if (!base64Obj || !base64Obj.base64) {\r\n console.warn('Compression skipped or failed for:', file.name);\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isFailed = true; // Mark the file as failed\r\n //window.onbeforeunload = null;\r\n setTimeout(() => up.start(), 0);\r\n return; // Skip further processing if compression failed or was skipped\r\n }\r\n \r\n const isDirectWebp = compressOptions?.direct_webp && file.type !== 'image/webp';\r\n const isBackupOriginal = compressOptions?.backup_original;\r\n\r\n if (isBackupOriginal) {\r\n // If backup original is enabled, convert the original file to WebP if it's not already\r\n if (isDirectWebp) {\r\n originalFile = await Squeeze.convertFileToWebp(file);\r\n } else {\r\n originalFile = file; // Keep the original file as is\r\n }\r\n pluploadFile.originalFile = originalFile; // Store the original file in the pluploadFile object\r\n }\r\n\r\n const compressedFile = _helpers_js__WEBPACK_IMPORTED_MODULE_0__.base64ToFile(base64Obj.base64, file.name, file.type);\r\n const newSource = new mOxie.File(null, compressedFile);\r\n\r\n if (!newSource) {\r\n console.error('Failed to create new mOxie.File from base64 data');\r\n return; // Exit if newSource is not created\r\n }\r\n\r\n //console.log('Compressed file created:', newSource);\r\n\r\n // Override the file's getSource method to return the new compressed source\r\n pluploadFile.getSource = function () {\r\n return newSource;\r\n };\r\n\r\n // Reset status back to QUEUED\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isSqueezed = true; // Mark the file as compressed\r\n pluploadFile.base64 = base64Obj.base64; // Store the base64 data of the compressed image in the attachment\r\n pluploadFile.base64Webp = base64Obj?.base64Webp; // Store the WebP base64 data of the compressed image in the attachment\r\n \r\n // In the next tick, restart the queue\r\n setTimeout(() => up.start(), 0);\r\n\r\n //window.onbeforeunload = null;\r\n\r\n } catch (error) {\r\n console.error('Error during compression before upload:', error);\r\n pluploadFile.status = plupload.QUEUED;\r\n pluploadFile.loaded = 0;\r\n pluploadFile._isFailed = true; // Mark the file as failed\r\n setTimeout(() => up.start(), 0);\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nconst handleMultiFileFormUpload = (compressOptions) => {\r\n if (typeof wpUploaderInit === 'undefined' || typeof plupload === 'undefined' || typeof uploader === 'undefined') return;\r\n\r\n const SqueezeUploader = uploader;\r\n\r\n SqueezeUploader.bind('BeforeUpload', async function (up, pluploadFile) {\r\n handleCompressBeforeUpload(up, pluploadFile, compressOptions)\r\n });\r\n\r\n SqueezeUploader.bind('FileUploaded', function (up, file, response) {\r\n //console.log('FileUploaded', file, response);\r\n const fileMime = file.type;\r\n const fileType = fileMime.split('/')[0];\r\n const fileSubType = fileMime.split('/')[1];\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment(fileType, fileSubType, compressOptions)) return;\r\n\r\n /**\r\n * Wait for media item to load( 'async-upload.php' )\r\n * Ping every 1 second until the media item is loaded\r\n * @returns Promise\r\n */\r\n const waitForItemLoad = (addProgressBar = true) => {\r\n return new Promise((resolve) => {\r\n let interval = setInterval(() => {\r\n if (mediaItem.querySelector('.media-item-wrapper')) {\r\n if (addProgressBar) {\r\n mediaItem.querySelector('.media-item-wrapper').innerHTML += `\r\n <div class=\"progress\">\r\n <div class=\"percent\">${__('Squeezing...', 'squeeze')}</div>\r\n <div class=\"bar\" style=\"width: 200px;\"></div>\r\n </div>\r\n `;\r\n }\r\n clearInterval(interval);\r\n resolve();\r\n }\r\n }, 1000);\r\n });\r\n };\r\n\r\n const fileID = file.id;\r\n const attachmentID = response.response;\r\n const mediaItem = document.getElementById(`media-item-${fileID}`);\r\n\r\n if (file?._isExcluded) {\r\n console.warn('File is excluded from compression:', file.name);\r\n waitForItemLoad(false).then(() => {\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${__('File is excluded from compression:', 'squeeze')} ${file.name}</div>`;\r\n });\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n if (file?._isFailed) {\r\n console.warn('File compression failed:', file.name);\r\n waitForItemLoad(false).then(() => {\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${__('File compression failed:', 'squeeze')} ${file.name}</div>`;\r\n });\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n window.onbeforeunload = handleOnLeave;\r\n\r\n waitForItemLoad().then(() => {\r\n try {\r\n wp.media.attachment(attachmentID).fetch().then(async function (data) {\r\n //console.log('Fetched attachment data:', data);\r\n const attachment = { attributes: data };\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_0__.extendAttachment(attachment, file);\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n window.onbeforeunload = null;\r\n mediaItem.innerHTML += `<div class=\"squeeze_status\">${uploadData?.data?.message}</div>`;\r\n mediaItem.querySelector('.progress')?.remove();\r\n } else {\r\n mediaItem.innerHTML += uploadData?.data?.message ?? uploadData?.data ?? uploadData;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n } catch (error) {\r\n console.error(error);\r\n mediaItem.innerHTML += error;\r\n window.onbeforeunload = null;\r\n mediaItem.querySelector('.progress')?.remove();\r\n }\r\n });\r\n });\r\n}\r\n\r\n\n\n//# sourceURL=webpack:///./assets/js/handlers.js?"); 20 20 21 21 /***/ }), … … 27 27 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 28 28 29 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64SizeInBytes\": () => (/* binding */ base64SizeInBytes),\n/* harmony export */ \"base64ToBlob\": () => (/* binding */ base64ToBlob),\n/* harmony export */ \" cachedMediaData\": () => (/* binding */ cachedMediaData),\n/* harmony export */ \"disableAllButtons\": () => (/* binding */ disableAllButtons),\n/* harmony export */ \"disableBulkButtons\": () => (/* binding */ disableBulkButtons),\n/* harmony export */ \"elements\": () => (/* binding */ elements),\n/* harmony export */ \"humanFileSize\": () => (/* binding */ humanFileSize),\n/* harmony export */ \"isDocHidden\": () => (/* binding */ isDocHidden),\n/* harmony export */ \"logMessage\": () => (/* binding */ logMessage),\n/* harmony export */ \"maybeCompressAttachment\": () => (/* binding */ maybeCompressAttachment),\n/* harmony export */ \"populatePathInput\": () => (/* binding */ populatePathInput),\n/* harmony export */ \"removeAllButtons\": () => (/* binding */ removeAllButtons),\n/* harmony export */ \"renderDirectories\": () => (/* binding */ renderDirectories),\n/* harmony export */ \"renderTemplate\": () => (/* binding */ renderTemplate),\n/* harmony export */ \"restoreBulkButtons\": () => (/* binding */ restoreBulkButtons),\n/* harmony export */ \"updateButtonText\": () => (/* binding */ updateButtonText)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\n// move static helper functions here\r\nconst elements = {\r\n bulkBtn: document.querySelector(\"[name='squeeze_bulk']\"),\r\n bulkAgainBtn: document.querySelector(\"[name='squeeze_bulk_again']\"),\r\n bulkPathBtn: document.querySelector(\"[name='squeeze_bulk_path_button']\"),\r\n selectPathBtn: document.querySelector(\"[name='squeeze_select_path_button']\"),\r\n savePathBtn: document.querySelector(\"[name='squeeze_save_path_button']\"),\r\n pathDialog: document.getElementById(\"squeeze-path-dialog\"),\r\n closePathDialogBtn: document.querySelector(\"[name='squeeze_close_path_dialog_button']\"),\r\n pathInput: document.querySelector(\"[name='squeeze_bulk_path']\"),\r\n pathList: document.querySelector(\".squeeze-path-list\"),\r\n postsFilterForm: document.querySelector(\"#posts-filter\"),\r\n dirContainer: document.getElementById(\"squeeze-bulk-directory-list\"),\r\n bulkLogInput: document.querySelector(\"#squeeze-log-data\"),\r\n pauseBulkBtn: document.querySelector(\"[name='squeeze_pause_page_bulk']\")\r\n}\r\n\r\nconst cachedMediaData = {\r\n isPaused: false,\r\n page: 1,\r\n process: '',\r\n mediaIDs: [],\r\n lastId: 0,\r\n totalImages: document.querySelector(\"[name='squeeze_bulk_total_images']\")?.value || 0,\r\n uncompressedImages: document.querySelector(\"[name='squeeze_bulk_uncompressed_images']\")?.value || 0,\r\n target: null\r\n}\r\n\r\nconst loadTemplate = async (templatePath, data) => {\r\n const response = await fetch(templatePath);\r\n let template = await response.text();\r\n\r\n // Process sub-templates\r\n const subTemplateRegex = /\\{\\{\\>\\s*(.*?)\\s*\\}\\}/g;\r\n let match;\r\n while ((match = subTemplateRegex.exec(template)) !== null) {\r\n const subTemplatePath = `${squeezeOptions.templateBase}/${match[1].trim()}.html`;\r\n const subTemplate = await loadTemplate(subTemplatePath, data);\r\n template = template.replace(match[0], subTemplate);\r\n }\r\n\r\n // Function to safely evaluate conditions (supports boolean variables, expressions, AND/OR)\r\n const evaluateCondition = (condition, data) => {\r\n try {\r\n // Convert standalone boolean variables (e.g., webp_lossless) to data['webp_lossless']\r\n condition = condition.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match) =>\r\n match in data ? `data['${match}']` : match\r\n );\r\n\r\n return new Function(\"data\", `with(data) { return ${condition}; }`)(data);\r\n } catch (e) {\r\n console.error(\"Error evaluating condition:\", condition, e);\r\n return false;\r\n }\r\n };\r\n\r\n // Recursive function to process nested if-else conditions\r\n const processIfStatements = (template) => {\r\n return template.replace(/\\{\\{#if ([\\s\\S]*?)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g, (match, condition, content) => {\r\n condition = condition.trim();\r\n const conditionResult = evaluateCondition(condition, data);\r\n\r\n // Extract and split the if-else blocks\r\n const elseMatch = content.match(/\\{\\{#else\\}\\}([\\s\\S]*)/);\r\n const trueBlock = elseMatch ? content.replace(/\\{\\{#else\\}\\}([\\s\\S]*)/, \"\") : content;\r\n const falseBlock = elseMatch ? elseMatch[1] : \"\";\r\n\r\n // Process nested if statements recursively\r\n return processIfStatements(conditionResult ? trueBlock : falseBlock);\r\n });\r\n };\r\n\r\n // Apply recursive processing of if conditions\r\n template = processIfStatements(template);\r\n\r\n // Replace variables\r\n return template.replace(/\\{\\{(.*?)\\}\\}/g, (match, key) => data[key.trim()] || '');\r\n}\r\n\r\nconst renderTemplate = async (templatePath, data, target = null) => {\r\n const renderedHTML = await loadTemplate(templatePath, data);\r\n\r\n // Create a temporary container to parse HTML\r\n const tempContainer = document.createElement(\"template\");\r\n tempContainer.innerHTML = renderedHTML.trim();\r\n\r\n if (!target) {\r\n return tempContainer.content.firstChild;\r\n }\r\n\r\n target.appendChild(tempContainer.content.firstChild);\r\n\r\n // Return the last element of the rendered template\r\n return target.lastElementChild;\r\n}\r\n\r\nconst logMessage = async (msg, options = {}) => {\r\n const { mediaLogWrapper = null, isStart = false, isPause = false } = options;\r\n let { title = '', iconId = 'check-mark-circle-icon' } = options;\r\n\r\n if (!elements.bulkLogInput) return;\r\n\r\n if (isStart || isPause) {\r\n iconId = isPause ? 'pause-button-icon' : 'image-file-icon';\r\n title = isPause ? __('Bulk squeezing has been paused!', 'squeeze') : `${__('Media', 'squeeze')} ${title}:`;\r\n return await renderTemplate(squeezeOptions.templates.logWrapper, { title: title, msg: msg, iconId: iconId, isStart: isStart, isPause: isPause }, elements.bulkLogInput);\r\n } else {\r\n if (mediaLogWrapper) {\r\n const process = mediaLogWrapper.querySelector(\".media-log-process\");\r\n const step = await renderTemplate(squeezeOptions.templates.logStep, { msg: msg, iconId: iconId }, process);\r\n\r\n if (msg.includes('squeeze-comparison-table')) {\r\n const comparisonTable = step.querySelector('.squeeze-comparison-table');\r\n const toggleBtn = await renderTemplate(squeezeOptions.templates.logDetailsButton, { buttonText: __('Show details', 'squeeze') }, mediaLogWrapper);\r\n\r\n toggleBtn.addEventListener(\"click\", () => {\r\n comparisonTable.classList.toggle(\"show\");\r\n toggleBtn.textContent = comparisonTable.classList.contains(\"show\") ? __('Hide details', 'squeeze') : __('Show details', 'squeeze');\r\n });\r\n step.closest(\".media-log-wrapper\").appendChild(comparisonTable);\r\n step.closest(\".media-log-wrapper\").appendChild(toggleBtn);\r\n }\r\n } else {\r\n elements.bulkLogInput.innerHTML += msg + `<br>`;\r\n }\r\n }\r\n}\r\n\r\nconst restoreBulkButtons = () => {\r\n elements.bulkBtn.disabled = false;\r\n elements.bulkAgainBtn.disabled = false;\r\n elements.bulkPathBtn.disabled = false;\r\n elements.selectPathBtn.disabled = false;\r\n updateButtonText(elements.bulkBtn, __('Run Bulk Squeeze', 'squeeze'), '#play-button-round-icon');\r\n updateButtonText(elements.bulkAgainBtn, __('Repeat Bulk Squeeze', 'squeeze'), '#combine-left-right-outline-icon');\r\n updateButtonText(elements.bulkPathBtn, __('Run Directory Squeeze', 'squeeze'), '#play-button-round-icon');\r\n elements.bulkBtn.dataset.running = 'false';\r\n elements.bulkAgainBtn.dataset.running = 'false';\r\n elements.bulkPathBtn.dataset.running = 'false';\r\n\r\n cachedMediaData.process = '';\r\n cachedMediaData.mediaIDs = [];\r\n cachedMediaData.page = 1;\r\n}\r\n\r\nconst disableBulkButtons = () => {\r\n elements.bulkBtn.disabled = true;\r\n elements.bulkAgainBtn.disabled = true;\r\n elements.bulkPathBtn.disabled = true;\r\n elements.selectPathBtn.disabled = true;\r\n}\r\n\r\nconst disableAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst removeAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.remove());\r\n}\r\n\r\nconst updateButtonText = (button, text, svgAnchor = false) => {\r\n button.childNodes.forEach((node) => {\r\n if (node.nodeName === '#text' && node.textContent.trim() !== '') {\r\n node.textContent = text;\r\n }\r\n if (svgAnchor && node.nodeName === 'svg') {\r\n node.querySelector('use').setAttribute('xlink:href', svgAnchor);\r\n }\r\n });\r\n}\r\n\r\n// Function to render directories in the dialog\r\nconst renderDirectories = async (dirs, parentDir = null, listeners = {}) => {\r\n if (!dirs) return;\r\n if (typeof dirs === 'object') dirs = Object.values(dirs);\r\n if (!elements.dirContainer.classList.contains(\"loaded\")) elements.dirContainer.innerHTML = \"\";\r\n\r\n if (dirs.length === 0 && !parentDir) {\r\n const listItem = await renderTemplate(squeezeOptions.templates.directoryItemEmpty, { emptyText: __('No directories found!', 'squeeze') }, elements.dirContainer);\r\n return;\r\n }\r\n\r\n const selectedFolders = JSON.parse(elements.pathInput.value);\r\n let target;\r\n\r\n for (const dir of dirs) {\r\n const listItemClasses = [];\r\n\r\n if (dir.parent === '/') {\r\n listItemClasses.push(\"loaded\", \"opened\");\r\n }\r\n\r\n if (parentDir) {\r\n target = parentDir;\r\n } else if (dir.parent) {\r\n const parentElement = elements.dirContainer.querySelector(`[data-path=\"${dir.parent}\"]`);\r\n if (parentElement) {\r\n target = parentElement;\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n\r\n const listItem = await renderTemplate(\r\n squeezeOptions.templates.directoryItem,\r\n {\r\n parent: dir.parent,\r\n path: dir.path,\r\n label: dir.name,\r\n classes: listItemClasses.join(\" \"),\r\n isWritable: dir.is_writeable && !(Array.isArray(selectedFolders) && selectedFolders.includes(dir.path)),\r\n isChecked: dir.is_writeable && Array.isArray(selectedFolders) && selectedFolders.includes(dir.path),\r\n },\r\n target\r\n )\r\n\r\n listItem.querySelector(\"label\").addEventListener(\"click\", listeners.handleDirectoryClick);\r\n listItem.querySelector(\"input[type='checkbox']\")?.addEventListener(\"change\", listeners.handleDirectoryCheck);\r\n }\r\n\r\n elements.dirContainer.classList.add(\"loaded\");\r\n}\r\n\r\nconst populatePathInput = async () => {\r\n const path = elements.pathInput.value;\r\n if (!path) return;\r\n\r\n try {\r\n const selectedFolders = JSON.parse(path);\r\n const inputs = elements.pathList.querySelectorAll(\".squeeze-path-list__item\");\r\n\r\n inputs.forEach(input => input.remove());\r\n\r\n for (const folder of selectedFolders) {\r\n const input = await renderTemplate(squeezeOptions.templates.pathListItem, { folder: folder }, elements.pathList);\r\n }\r\n } catch (error) {\r\n alert(__('Error parsing path input!', 'squeeze'));\r\n console.error('Error parsing path input:', error);\r\n }\r\n}\r\n\r\nconst getHiddenProp = () => {\r\n var prefixes = ['webkit', 'moz', 'ms', 'o'];\r\n\r\n // if 'hidden' is natively supported just return it\r\n if ('hidden' in document) return 'hidden';\r\n\r\n // otherwise loop over all the known prefixes until we find one\r\n for (let i = 0; i < prefixes.length; i++) {\r\n if ((prefixes[i] + 'Hidden') in document)\r\n return prefixes[i] + 'Hidden';\r\n }\r\n\r\n // otherwise it's not supported\r\n return null;\r\n}\r\n\r\nconst isDocHidden = () => {\r\n const prop = getHiddenProp();\r\n if (!prop) return false;\r\n\r\n return document[prop];\r\n}\r\n\r\n/**\r\n * @see https://stackoverflow.com/a/20732091\r\n */\r\nconst humanFileSize = (size) => {\r\n let i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));\r\n return +((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];\r\n}\r\n\r\nconst base64SizeInBytes = (base64) => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64; \r\n\r\n // Calculate padding characters ('=' at the end of Base64)\r\n const padding = (base64String.match(/=+$/) || [\"\"])[0].length;\r\n\r\n // Compute byte size\r\n return (base64String.length * 3) / 4 - padding;\r\n}\r\n\r\nconst maybeCompressAttachment = (attachmentType, attachmentSubType, compressOptions) => {\r\n const isAutoCompress = compressOptions.auto_compress;\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType);\r\n\r\n return isImage && isAutoCompress;\r\n};\r\n\r\nconst base64ToBlob = (base64, type = 'image/jpeg') => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64;\r\n\r\n // Decode Base64 string\r\n const byteCharacters = atob(base64String);\r\n const byteNumbers = new Array(byteCharacters.length);\r\n \r\n for (let i = 0; i < byteCharacters.length; i++) {\r\n byteNumbers[i] = byteCharacters.charCodeAt(i);\r\n }\r\n\r\n const byteArray = new Uint8Array(byteNumbers);\r\n return new Blob([byteArray], { type: type });\r\n}\n\n//# sourceURL=webpack:///./assets/js/helpers.js?");29 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"base64SizeInBytes\": () => (/* binding */ base64SizeInBytes),\n/* harmony export */ \"base64ToBlob\": () => (/* binding */ base64ToBlob),\n/* harmony export */ \"base64ToFile\": () => (/* binding */ base64ToFile),\n/* harmony export */ \"cachedMediaData\": () => (/* binding */ cachedMediaData),\n/* harmony export */ \"disableAllButtons\": () => (/* binding */ disableAllButtons),\n/* harmony export */ \"disableBulkButtons\": () => (/* binding */ disableBulkButtons),\n/* harmony export */ \"elements\": () => (/* binding */ elements),\n/* harmony export */ \"extendAttachment\": () => (/* binding */ extendAttachment),\n/* harmony export */ \"fileToBase64\": () => (/* binding */ fileToBase64),\n/* harmony export */ \"getFileFromUrl\": () => (/* binding */ getFileFromUrl),\n/* harmony export */ \"handleRemovePathButton\": () => (/* binding */ handleRemovePathButton),\n/* harmony export */ \"humanFileSize\": () => (/* binding */ humanFileSize),\n/* harmony export */ \"isDocHidden\": () => (/* binding */ isDocHidden),\n/* harmony export */ \"logMessage\": () => (/* binding */ logMessage),\n/* harmony export */ \"maybeCompressAttachment\": () => (/* binding */ maybeCompressAttachment),\n/* harmony export */ \"objectToFormData\": () => (/* binding */ objectToFormData),\n/* harmony export */ \"populatePathInput\": () => (/* binding */ populatePathInput),\n/* harmony export */ \"removeAllButtons\": () => (/* binding */ removeAllButtons),\n/* harmony export */ \"renderDirectories\": () => (/* binding */ renderDirectories),\n/* harmony export */ \"renderTemplate\": () => (/* binding */ renderTemplate),\n/* harmony export */ \"restoreBulkButtons\": () => (/* binding */ restoreBulkButtons),\n/* harmony export */ \"updateButtonText\": () => (/* binding */ updateButtonText)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\n// move static helper functions here\r\nconst elements = {\r\n bulkBtn: document.querySelector(\"[name='squeeze_bulk']\"),\r\n bulkAgainBtn: document.querySelector(\"[name='squeeze_bulk_again']\"),\r\n bulkPathBtn: document.querySelector(\"[name='squeeze_bulk_path_button']\"),\r\n bulkPathRemoveBtns: document.querySelectorAll(\".squeeze-path-list__remove\"),\r\n selectPathBtn: document.querySelector(\"[name='squeeze_select_path_button']\"),\r\n savePathBtn: document.querySelector(\"[name='squeeze_save_path_button']\"),\r\n pathDialog: document.getElementById(\"squeeze-path-dialog\"),\r\n closePathDialogBtn: document.querySelector(\"[name='squeeze_close_path_dialog_button']\"),\r\n pathInput: document.querySelector(\"[name='squeeze_bulk_path']\"),\r\n pathList: document.querySelector(\".squeeze-path-list\"),\r\n postsFilterForm: document.querySelector(\"#posts-filter\"),\r\n dirContainer: document.getElementById(\"squeeze-bulk-directory-list\"),\r\n bulkLogInput: document.querySelector(\"#squeeze-log-data\"),\r\n pauseBulkBtn: document.querySelector(\"[name='squeeze_pause_page_bulk']\")\r\n}\r\n\r\nconst cachedMediaData = {\r\n isPaused: false,\r\n page: 1,\r\n process: '',\r\n mediaIDs: [],\r\n lastId: 0,\r\n totalImages: document.querySelector(\"[name='squeeze_bulk_total_images']\")?.value || 0,\r\n uncompressedImages: document.querySelector(\"[name='squeeze_bulk_uncompressed_images']\")?.value || 0,\r\n target: null\r\n}\r\n\r\nconst loadTemplate = async (templatePath, data) => {\r\n const response = await fetch(templatePath);\r\n let template = await response.text();\r\n\r\n // Process sub-templates\r\n const subTemplateRegex = /\\{\\{\\>\\s*(.*?)\\s*\\}\\}/g;\r\n let match;\r\n while ((match = subTemplateRegex.exec(template)) !== null) {\r\n const subTemplatePath = `${squeezeOptions.templateBase}/${match[1].trim()}.html`;\r\n const subTemplate = await loadTemplate(subTemplatePath, data);\r\n template = template.replace(match[0], subTemplate);\r\n }\r\n\r\n // Function to safely evaluate conditions (supports boolean variables, expressions, AND/OR)\r\n const evaluateCondition = (condition, data) => {\r\n try {\r\n // Convert standalone boolean variables (e.g., webp_lossless) to data['webp_lossless']\r\n condition = condition.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match) =>\r\n match in data ? `data['${match}']` : match\r\n );\r\n\r\n return new Function(\"data\", `with(data) { return ${condition}; }`)(data);\r\n } catch (e) {\r\n console.error(\"Error evaluating condition:\", condition, e);\r\n return false;\r\n }\r\n };\r\n\r\n // Recursive function to process nested if-else conditions\r\n const processIfStatements = (template) => {\r\n return template.replace(/\\{\\{#if ([\\s\\S]*?)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g, (match, condition, content) => {\r\n condition = condition.trim();\r\n const conditionResult = evaluateCondition(condition, data);\r\n\r\n // Extract and split the if-else blocks\r\n const elseMatch = content.match(/\\{\\{#else\\}\\}([\\s\\S]*)/);\r\n const trueBlock = elseMatch ? content.replace(/\\{\\{#else\\}\\}([\\s\\S]*)/, \"\") : content;\r\n const falseBlock = elseMatch ? elseMatch[1] : \"\";\r\n\r\n // Process nested if statements recursively\r\n return processIfStatements(conditionResult ? trueBlock : falseBlock);\r\n });\r\n };\r\n\r\n // Apply recursive processing of if conditions\r\n template = processIfStatements(template);\r\n\r\n // Replace variables\r\n return template.replace(/\\{\\{(.*?)\\}\\}/g, (match, key) => data[key.trim()] || '');\r\n}\r\n\r\nconst renderTemplate = async (templatePath, data, target = null) => {\r\n const renderedHTML = await loadTemplate(templatePath, data);\r\n\r\n // Create a temporary container to parse HTML\r\n const tempContainer = document.createElement(\"template\");\r\n tempContainer.innerHTML = renderedHTML.trim();\r\n\r\n if (!target) {\r\n return tempContainer.content.firstChild;\r\n }\r\n\r\n target.appendChild(tempContainer.content.firstChild);\r\n\r\n // Return the last element of the rendered template\r\n return target.lastElementChild;\r\n}\r\n\r\nconst logMessage = async (msg, options = {}) => {\r\n const { mediaLogWrapper = null, isStart = false, isPause = false } = options;\r\n let { title = '', iconId = 'check-mark-circle-icon' } = options;\r\n\r\n if (!elements.bulkLogInput) return;\r\n\r\n if (isStart || isPause) {\r\n iconId = isPause ? 'pause-button-icon' : 'image-file-icon';\r\n title = isPause ? __('Bulk squeezing has been paused!', 'squeeze') : `${__('Media', 'squeeze')} ${title}:`;\r\n return await renderTemplate(squeezeOptions.templates.logWrapper, { title: title, msg: msg, iconId: iconId, isStart: isStart, isPause: isPause }, elements.bulkLogInput);\r\n } else {\r\n if (mediaLogWrapper) {\r\n const process = mediaLogWrapper.querySelector(\".media-log-process\");\r\n const step = await renderTemplate(squeezeOptions.templates.logStep, { msg: msg, iconId: iconId }, process);\r\n\r\n if (msg && msg.includes('squeeze-comparison-table')) {\r\n const comparisonTable = step.querySelector('.squeeze-comparison-table');\r\n const toggleBtn = await renderTemplate(squeezeOptions.templates.logDetailsButton, { buttonText: __('Show details', 'squeeze') }, mediaLogWrapper);\r\n\r\n toggleBtn.addEventListener(\"click\", () => {\r\n comparisonTable.classList.toggle(\"show\");\r\n toggleBtn.textContent = comparisonTable.classList.contains(\"show\") ? __('Hide details', 'squeeze') : __('Show details', 'squeeze');\r\n });\r\n step.closest(\".media-log-wrapper\").appendChild(comparisonTable);\r\n step.closest(\".media-log-wrapper\").appendChild(toggleBtn);\r\n }\r\n } else {\r\n elements.bulkLogInput.innerHTML += msg + `<br>`;\r\n }\r\n }\r\n}\r\n\r\nconst restoreBulkButtons = () => {\r\n elements.bulkBtn.disabled = false;\r\n elements.bulkAgainBtn.disabled = false;\r\n elements.bulkPathBtn.disabled = false;\r\n elements.selectPathBtn.disabled = false;\r\n updateButtonText(elements.bulkBtn, __('Run Bulk Squeeze', 'squeeze'), '#play-button-round-icon');\r\n updateButtonText(elements.bulkAgainBtn, __('Repeat Bulk Squeeze', 'squeeze'), '#combine-left-right-outline-icon');\r\n updateButtonText(elements.bulkPathBtn, __('Run Directory Squeeze', 'squeeze'), '#play-button-round-icon');\r\n elements.bulkBtn.dataset.running = 'false';\r\n elements.bulkAgainBtn.dataset.running = 'false';\r\n elements.bulkPathBtn.dataset.running = 'false';\r\n elements.bulkPathRemoveBtns?.forEach((btn) => {\r\n btn.disabled = false;\r\n });\r\n\r\n cachedMediaData.process = '';\r\n cachedMediaData.mediaIDs = [];\r\n cachedMediaData.page = 1;\r\n}\r\n\r\nconst disableBulkButtons = () => {\r\n elements.bulkBtn.disabled = true;\r\n elements.bulkAgainBtn.disabled = true;\r\n elements.bulkPathBtn.disabled = true;\r\n elements.selectPathBtn.disabled = true;\r\n elements.bulkPathRemoveBtns?.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst disableAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.disabled = true);\r\n}\r\n\r\nconst removeAllButtons = (buttons) => {\r\n if (!buttons) return;\r\n buttons.forEach((btn) => btn.remove());\r\n}\r\n\r\nconst updateButtonText = (button, text, svgAnchor = false) => {\r\n button.childNodes.forEach((node) => {\r\n if (node.nodeName === '#text' && node.textContent.trim() !== '') {\r\n node.textContent = text;\r\n }\r\n if (svgAnchor && node.nodeName === 'svg') {\r\n node.querySelector('use').setAttribute('xlink:href', svgAnchor);\r\n }\r\n });\r\n}\r\n\r\n// Function to render directories in the dialog\r\nconst renderDirectories = async (dirs, parentDir = null, listeners = {}) => {\r\n if (!dirs) return;\r\n if (typeof dirs === 'object') dirs = Object.values(dirs);\r\n if (!elements.dirContainer.classList.contains(\"loaded\")) elements.dirContainer.innerHTML = \"\";\r\n\r\n if (dirs.length === 0 && !parentDir) {\r\n const listItem = await renderTemplate(squeezeOptions.templates.directoryItemEmpty, { emptyText: __('No directories found!', 'squeeze') }, elements.dirContainer);\r\n return;\r\n }\r\n\r\n const selectedFolders = JSON.parse(elements.pathInput.value);\r\n let target;\r\n\r\n for (const dir of dirs) {\r\n const listItemClasses = [];\r\n\r\n if (dir.parent === '/') {\r\n listItemClasses.push(\"loaded\", \"opened\");\r\n }\r\n\r\n if (parentDir) {\r\n target = parentDir;\r\n } else if (dir.parent) {\r\n const parentElement = elements.dirContainer.querySelector(`[data-path=\"${dir.parent}\"]`);\r\n if (parentElement) {\r\n target = parentElement;\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n } else {\r\n target = elements.dirContainer;\r\n }\r\n\r\n const listItem = await renderTemplate(\r\n squeezeOptions.templates.directoryItem,\r\n {\r\n parent: dir.parent,\r\n path: dir.path,\r\n label: dir.name,\r\n classes: listItemClasses.join(\" \"),\r\n isWritable: dir.is_writeable && !(Array.isArray(selectedFolders) && selectedFolders.includes(dir.path)),\r\n isChecked: dir.is_writeable && Array.isArray(selectedFolders) && selectedFolders.includes(dir.path),\r\n },\r\n target\r\n )\r\n\r\n listItem.querySelector(\"label\").addEventListener(\"click\", listeners.handleDirectoryClick);\r\n listItem.querySelector(\"input[type='checkbox']\")?.addEventListener(\"change\", listeners.handleDirectoryCheck);\r\n }\r\n\r\n elements.dirContainer.classList.add(\"loaded\");\r\n}\r\n\r\nconst handleRemovePathButton = (e) => {\r\n e.preventDefault();\r\n const item = e.target.closest(\".squeeze-path-list__item\");\r\n if (item) {\r\n item.remove();\r\n const currentPaths = Array.from(elements.pathList.querySelectorAll(\".squeeze-path-list__input\"))\r\n .map(input => input.value.trim())\r\n .filter(value => value !== '');\r\n elements.pathInput.value = JSON.stringify(currentPaths);\r\n }\r\n}\r\n\r\nconst populatePathInput = async () => {\r\n const path = elements.pathInput.value;\r\n if (!path) return;\r\n\r\n try {\r\n const selectedFolders = JSON.parse(path);\r\n const items = elements.pathList.querySelectorAll(\".squeeze-path-list__item\");\r\n\r\n items.forEach(item => item.remove());\r\n\r\n for (const folder of selectedFolders) {\r\n const item = await renderTemplate(squeezeOptions.templates.pathListItem, { folder: folder }, elements.pathList);\r\n const removeButton = item.querySelector(\".squeeze-path-list__remove\");\r\n removeButton.addEventListener(\"click\", handleRemovePathButton);\r\n\r\n }\r\n } catch (error) {\r\n alert(__('Error parsing path input!', 'squeeze'));\r\n console.error('Error parsing path input:', error);\r\n }\r\n}\r\n\r\nconst getHiddenProp = () => {\r\n var prefixes = ['webkit', 'moz', 'ms', 'o'];\r\n\r\n // if 'hidden' is natively supported just return it\r\n if ('hidden' in document) return 'hidden';\r\n\r\n // otherwise loop over all the known prefixes until we find one\r\n for (let i = 0; i < prefixes.length; i++) {\r\n if ((prefixes[i] + 'Hidden') in document)\r\n return prefixes[i] + 'Hidden';\r\n }\r\n\r\n // otherwise it's not supported\r\n return null;\r\n}\r\n\r\nconst isDocHidden = () => {\r\n const prop = getHiddenProp();\r\n if (!prop) return false;\r\n\r\n return document[prop];\r\n}\r\n\r\n/**\r\n * @see https://stackoverflow.com/a/20732091\r\n */\r\nconst humanFileSize = (size) => {\r\n let i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));\r\n return +((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];\r\n}\r\n\r\nconst base64SizeInBytes = (base64) => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64; \r\n\r\n // Calculate padding characters ('=' at the end of Base64)\r\n const padding = (base64String.match(/=+$/) || [\"\"])[0].length;\r\n\r\n // Compute byte size\r\n return (base64String.length * 3) / 4 - padding;\r\n}\r\n\r\nconst maybeCompressAttachment = (attachmentType, attachmentSubType, compressOptions = null) => {\r\n const isAutoCompress = compressOptions?.auto_compress ?? true;\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType);\r\n\r\n return isImage && isAutoCompress;\r\n};\r\n\r\nconst base64ToBlob = (base64, type = 'image/jpeg') => {\r\n // Remove data URL prefix if present\r\n const base64String = base64.split(',')[1] || base64;\r\n\r\n // Decode Base64 string\r\n const byteCharacters = atob(base64String);\r\n const byteNumbers = new Array(byteCharacters.length);\r\n \r\n for (let i = 0; i < byteCharacters.length; i++) {\r\n byteNumbers[i] = byteCharacters.charCodeAt(i);\r\n }\r\n\r\n const byteArray = new Uint8Array(byteNumbers);\r\n return new Blob([byteArray], { type: type });\r\n}\r\n\r\nconst base64ToFile = (base64, fileName = 'image.jpg', type = 'image/jpeg') => {\r\n const blob = base64ToBlob(base64, type);\r\n return new File([blob], fileName, { type: type });\r\n}\r\n\r\nconst fileToBase64 = (file) => {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = () => resolve(reader.result);\r\n reader.onerror = (error) => reject(error);\r\n reader.readAsDataURL(file);\r\n });\r\n}\r\n\r\nfunction objectToFormData(obj, fd = null, parentKey = null) {\r\n const formData = fd || new FormData();\r\n\r\n for (const key in obj) {\r\n if (!obj.hasOwnProperty(key)) continue;\r\n const value = obj[key];\r\n\r\n // build the form key: either \"foo\", \"parent[foo]\" or \"parent[]\" for arrays\r\n const formKey = parentKey\r\n ? Array.isArray(obj)\r\n ? `${parentKey}[]`\r\n : `${parentKey}[${key}]`\r\n : key;\r\n\r\n // Files or Blobs go straight in\r\n if (value instanceof File || value instanceof Blob) {\r\n formData.append(formKey, value, value.name);\r\n }\r\n // Arrays: recurse so they become key[]=val0, key[]=val1…\r\n else if (Array.isArray(value)) {\r\n objectToFormData(value, formData, formKey);\r\n }\r\n // Plain objects: recurse so they become key[subkey]=subval\r\n else if (\r\n value !== null &&\r\n typeof value === 'object' &&\r\n !(value instanceof Date)\r\n ) {\r\n objectToFormData(value, formData, formKey);\r\n }\r\n // Dates: convert to ISO string (or format as you like)\r\n else if (value instanceof Date) {\r\n formData.append(formKey, value.toISOString());\r\n }\r\n // Everything else (number, string, boolean, null, undefined)\r\n else {\r\n // Explicitly convert undefined to empty string so PHP sees it\r\n const stringVal =\r\n value === undefined || value === null ? '' : String(value);\r\n formData.append(formKey, stringVal);\r\n }\r\n }\r\n\r\n return formData;\r\n}\r\n\r\n/**\r\n * Extend the attachment object with additional data from the file.\r\n * @param {object} attachment \r\n * @param {object} file \r\n * @returns {object} — the extended attachment object.\r\n */\r\nconst extendAttachment = async (attachment, file) => {\r\n if (typeof attachment !== 'object' || !attachment.attributes) {\r\n console.warn('Invalid attachment object:', attachment);\r\n return;\r\n }\r\n\r\n const attributes = attachment.attributes;\r\n\r\n if (file?.base64) {\r\n attributes.base64Compressed = file.base64; // Use the base64 data from the attachment\r\n }\r\n\r\n if (file?.base64Webp) {\r\n attributes.base64WebpCompressed = file.base64Webp; // Use the WebP base64 data from the attachment\r\n }\r\n\r\n if (file?.originalFile) {\r\n attributes.originalFile = file.originalFile; // Use the original file from the attachment to be able to create a backup\r\n }\r\n\r\n return attachment;\r\n}\r\n\r\nconst getFileFromUrl = async (url, filename, format) => {\r\n const response = await fetch(url);\r\n const blob = await response.blob();\r\n const mimeType = format ? `image/${format}` : blob.type;\r\n return new File([blob], filename, { type: mimeType });\r\n}\n\n//# sourceURL=webpack:///./assets/js/helpers.js?"); 30 30 31 31 /***/ }), … … 37 37 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 38 38 39 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _handlers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./handlers.js */ \"./assets/js/handlers.js\");\n\r\n\r\n\r\n\r\n\r\n\"use strict\";\r\n\r\nconst { sprintf, __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](squeezeOptions);\r\nconst compressOptions = JSON.parse(squeezeOptions.options);\r\n \r\ndocument.addEventListener(\"click\", (event) => {\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleButtonsClick(event, Squeeze); // manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.bulkBtn?.addEventListener(\"click\", async (event) => {\r\n let uncompressedIDs = squeezeBulk.unCompressedImages ? squeezeBulk.unCompressedImages.split(\",\") : [];\r\n let currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.page ?? 1;\r\n\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleBulkButtonClick(event, 'uncompressed', uncompressedIDs, currentPage);\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.bulkAgainBtn?.addEventListener(\"click\", async (event) => {\r\n let allIDs = squeezeBulk.allImages ? squeezeBulk.allImages.split(\",\") : [];\r\n let currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.page ?? 1;\r\n\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleBulkButtonClick(event, 'all', allIDs, currentPage);\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.bulkPathBtn?.addEventListener(\"click\", async (event) => {\r\n const path = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathInput?.value ?? '';\r\n let bulkPathData;\r\n\r\n if (!path) {\r\n alert(__('Please enter a valid path!', 'squeeze'));\r\n return;\r\n }\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.disableBulkButtons();\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.process === 'path' && _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.mediaIDs.length > 0) {\r\n bulkPathData = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.mediaIDs;\r\n } else {\r\n const pathData = await Squeeze.getAttachmentsByPath(path);\r\n\r\n if (pathData.success) {\r\n bulkPathData = pathData.data;\r\n } else {\r\n console.error(pathData.data);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n }\r\n }\r\n\r\n const isPaused = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleBulkToggle(event, 'path', bulkPathData);\r\n\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleRecursiveUpload('path', bulkPathData, 1);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n})\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.selectPathBtn?.addEventListener(\"click\", async (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathDialog.showModal();\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.contains(\"loading\")) return;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.contains(\"loaded\")) {\r\n const selectedFolders = JSON.parse(_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathInput.value);\r\n\r\n if (Array.isArray(selectedFolders)) {\r\n selectedFolders.forEach((folder) => {\r\n const checkbox = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.querySelector(`input[value=\"${folder}\"]`);\r\n if (checkbox) {\r\n checkbox.checked = true;\r\n }\r\n });\r\n }\r\n\r\n return;\r\n\r\n } else {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.add(\"loading\");\r\n const folders = await Squeeze.getDirectories();\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.renderDirectories(folders, null, {\r\n handleDirectoryClick: _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleDirectoryClick,\r\n handleDirectoryCheck: _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleDirectoryCheck\r\n });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.remove(\"loading\");\r\n }\r\n\r\n\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.savePathBtn?.addEventListener(\"click\", () => {\r\n const checkboxes = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.querySelectorAll(\"input[type='checkbox']\");\r\n const selectedFolders = Array.from(checkboxes)\r\n .filter(checkbox => checkbox.checked)\r\n .map(checkbox => checkbox.value);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathInput.value = JSON.stringify(selectedFolders);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.populatePathInput();\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathDialog.close();\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.closePathDialogBtn?.addEventListener(\"click\", () => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathDialog.close();\r\n});\r\n\r\ndocument.addEventListener('click', _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleClosePathDialog);\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm?.addEventListener(\"submit\", async (event) => {\r\n const dataAction = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.dataset.action;\r\n const action = event.target.querySelector(\"select[name='action']\").value;\r\n const submitButtons = event.target.querySelectorAll(\"input[name='bulk_action']\");\r\n\r\n if (action === 'squeeze_bulk_compress' && dataAction !== 'squeeze_bulk_compressed') {\r\n event.preventDefault();\r\n const mediaList = document.querySelectorAll(\"input[name='media[]']:checked\");\r\n const uncompressedIDs = Array.from(mediaList).map((el) => el.value);\r\n\r\n if (uncompressedIDs.length === 0) return;\r\n\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n\r\n uncompressedIDs.forEach((id) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.querySelectorAll(`#post-${id} .column-squeeze button`).forEach((btn) => {\r\n btn.disabled = true;\r\n });\r\n const squeezeStatusElement = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.querySelector(`#post-${id} .column-squeeze .squeeze_status`);\r\n if (squeezeStatusElement) {\r\n squeezeStatusElement.innerText = '⏳ ' + __('Squeezing...', 'squeeze');\r\n }\r\n });\r\n\r\n submitButtons.forEach((btn) => {\r\n btn.disabled = true;\r\n btn.value = __('Squeezing...', 'squeeze');\r\n });\r\n\r\n try {\r\n const finalResponse = await _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleRecursiveUpload('uncompressed', uncompressedIDs, 1);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0) {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.dataset.action = 'squeeze_bulk_compressed';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.submit();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n }\r\n});\r\n\r\n// https://wordpress.stackexchange.com/a/131295/186146 - override wp.Uploader.prototype.success\r\njQuery.extend(wp?.Uploader?.prototype, {\r\n success: async (attachment) => {\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.maybeCompressAttachment(attachment.attributes.type, attachment.attributes.subtype, compressOptions)) {\r\n\r\n // set 'uploading' param to true, to pause the uploading process\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n attachment.set('uploading', true);\r\n attachment.set('percent', 0);\r\n attachment.set('status', 'Squeezing'); // Set status to 'Squeezing' to indicate compression is in progress\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n attachment.set('percent', 75); // Set percent to 75% to indicate compression is done\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n const compat = attachment.get('compat');\r\n const tempDiv = document.createElement('div');\r\n let compatItem = compat.item;\r\n\r\n tempDiv.innerHTML = compatItem;\r\n tempDiv.querySelector('.compat-field-squeeze_is_compressed .field').innerHTML = uploadData.data;\r\n compat.item = tempDiv.innerHTML;\r\n\r\n attachment.set('compat', compat);\r\n attachment.set('uploading', false);\r\n window.onbeforeunload = null;\r\n } else {\r\n attachment.set('uploading', false);\r\n window.onbeforeunload = null;\r\n alert(uploadData.data);\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n attachment.set('uploading', false);\r\n window.onbeforeunload = null;\r\n }\r\n }\r\n },\r\n});\r\n\r\ndocument.onreadystatechange = function () {\r\n if (document.readyState === \"complete\") { // equivalent to jQuery $(document).ready()\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleMultiFileFormUpload(compressOptions);\r\n }\r\n}\r\n\r\n/**\r\n * Create the toggle preview checkbox\r\n * @param {Integer} attachmentId \r\n * @param {Boolean} isPlaceholder\r\n * @returns HTMLElement\r\n */\r\nconst createTogglePreview = (attachmentId, isPlaceholder = false) => {\r\n\r\n // Create the toggle\r\n const toggleWrap = document.createElement('span');\r\n const toggleInput = document.createElement('input');\r\n const toggleLabel = document.createElement('label');\r\n\r\n toggleInput.type = 'checkbox';\r\n toggleInput.className = 'squeeze-ios8-switch';\r\n toggleInput.id = 'squeeze-ios8-switch-' + attachmentId;\r\n toggleLabel.textContent = __('Squeeze Preview', 'squeeze');\r\n toggleLabel.htmlFor = toggleInput.id;\r\n toggleWrap.style.marginInlineStart = '1em';\r\n\r\n if (isPlaceholder) {\r\n toggleInput.disabled = true;\r\n toggleLabel.innerHTML += ' ' + sprintf(__('(<a href=\"%s\" target=\"_blank\">premium only</a>)','squeeze'), squeezeOptions.upgradeUrl);\r\n }\r\n\r\n toggleWrap.appendChild(toggleInput);\r\n toggleWrap.appendChild(toggleLabel);\r\n\r\n return toggleWrap;\r\n}\r\n\r\n\n\n//# sourceURL=webpack:///./assets/js/script.js?");39 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _squeeze_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./squeeze.js */ \"./assets/js/squeeze.js\");\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var _handlers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./handlers.js */ \"./assets/js/handlers.js\");\n\r\n\r\n\r\n\r\n\r\n\"use strict\";\r\n\r\nconst { sprintf, __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nconst Squeeze = new _squeeze_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](squeezeOptions);\r\nconst compressOptions = JSON.parse(squeezeOptions.options);\r\nconst originalUploaderInit = wp?.Uploader?.prototype?.init;\r\n\r\ndocument.addEventListener(\"click\", (event) => {\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleButtonsClick(event, Squeeze); // manually pass Squeeze, because of the dynamic options update in the Preview Mode\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.bulkBtn?.addEventListener(\"click\", async (event) => {\r\n let uncompressedIDs = squeezeBulk.unCompressedImages ? squeezeBulk.unCompressedImages.split(\",\") : [];\r\n let currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.page ?? 1;\r\n\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleBulkButtonClick(event, 'uncompressed', uncompressedIDs, currentPage);\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.bulkAgainBtn?.addEventListener(\"click\", async (event) => {\r\n let allIDs = squeezeBulk.allImages ? squeezeBulk.allImages.split(\",\") : [];\r\n let currentPage = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.page ?? 1;\r\n\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleBulkButtonClick(event, 'all', allIDs, currentPage);\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.bulkPathBtn?.addEventListener(\"click\", async (event) => {\r\n const path = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathInput?.value ?? '';\r\n let bulkPathData;\r\n\r\n if (path.replace(/\\[\\]/g, '').split(',').length === 0 || !path.replace(/\\[\\]/g, '').split(',')[0] || !path) {\r\n alert(__('Please enter a valid path!', 'squeeze'));\r\n return;\r\n }\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.disableBulkButtons();\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.process === 'path' && _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.mediaIDs.length > 0) {\r\n bulkPathData = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.cachedMediaData.mediaIDs;\r\n } else {\r\n const pathData = await Squeeze.getAttachmentsByPath(path);\r\n\r\n if (pathData.success) {\r\n bulkPathData = pathData.data;\r\n } else {\r\n console.error(pathData.data);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n }\r\n }\r\n\r\n const isPaused = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleBulkToggle(event, 'path', bulkPathData);\r\n\r\n if (isPaused) {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.updateButtonText(event.target, __('Pausing...', 'squeeze'), '#pause-button-icon');\r\n return;\r\n } else {\r\n event.target.disabled = false;\r\n }\r\n\r\n try {\r\n const finalResponse = await _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleRecursiveUpload('path', bulkPathData, 1);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0) {\r\n alert(__('All images have been processed!', 'squeeze'));\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.restoreBulkButtons();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.restoreBulkButtons();\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n})\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.bulkPathRemoveBtns?.forEach((btn) => {\r\n btn.addEventListener(\"click\", _helpers_js__WEBPACK_IMPORTED_MODULE_1__.handleRemovePathButton);\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.selectPathBtn?.addEventListener(\"click\", async (event) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathDialog.showModal();\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.contains(\"loading\")) return;\r\n\r\n if (_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.contains(\"loaded\")) {\r\n const selectedFolders = JSON.parse(_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathInput.value);\r\n\r\n if (Array.isArray(selectedFolders)) {\r\n selectedFolders.forEach((folder) => {\r\n const checkbox = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.querySelector(`input[value=\"${folder}\"]`);\r\n if (checkbox) {\r\n checkbox.checked = true;\r\n }\r\n });\r\n }\r\n\r\n return;\r\n\r\n } else {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.add(\"loading\");\r\n const folders = await Squeeze.getDirectories();\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.renderDirectories(folders, null, {\r\n handleDirectoryClick: _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleDirectoryClick,\r\n handleDirectoryCheck: _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleDirectoryCheck\r\n });\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.classList.remove(\"loading\");\r\n }\r\n\r\n\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.savePathBtn?.addEventListener(\"click\", () => {\r\n const checkboxes = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.dirContainer.querySelectorAll(\"input[type='checkbox']\");\r\n const selectedFolders = Array.from(checkboxes)\r\n .filter(checkbox => checkbox.checked)\r\n .map(checkbox => checkbox.value);\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathInput.value = JSON.stringify(selectedFolders);\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.populatePathInput();\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathDialog.close();\r\n});\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.closePathDialogBtn?.addEventListener(\"click\", () => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.pathDialog.close();\r\n});\r\n\r\ndocument.addEventListener('click', _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleClosePathDialog);\r\n\r\n_helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm?.addEventListener(\"submit\", async (event) => {\r\n const dataAction = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.dataset.action;\r\n const action = event.target.querySelector(\"select[name='action']\").value;\r\n const submitButtons = event.target.querySelectorAll(\"input[name='bulk_action']\");\r\n\r\n if (action === 'squeeze_bulk_compress' && dataAction !== 'squeeze_bulk_compressed') {\r\n event.preventDefault();\r\n const mediaList = document.querySelectorAll(\"input[name='media[]']:checked\");\r\n const uncompressedIDs = Array.from(mediaList).map((el) => el.value);\r\n\r\n if (uncompressedIDs.length === 0) return;\r\n\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n\r\n uncompressedIDs.forEach((id) => {\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.querySelectorAll(`#post-${id} .column-squeeze button`).forEach((btn) => {\r\n btn.disabled = true;\r\n });\r\n const squeezeStatusElement = _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.querySelector(`#post-${id} .column-squeeze .squeeze_status`);\r\n if (squeezeStatusElement) {\r\n squeezeStatusElement.innerText = '⏳ ' + __('Squeezing...', 'squeeze');\r\n }\r\n });\r\n\r\n submitButtons.forEach((btn) => {\r\n btn.disabled = true;\r\n btn.value = __('Squeezing...', 'squeeze');\r\n });\r\n\r\n try {\r\n const finalResponse = await _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleRecursiveUpload('uncompressed', uncompressedIDs, 1);\r\n\r\n if (finalResponse?.mediaIDs) {\r\n if (finalResponse.mediaIDs.length === 0) {\r\n window.onbeforeunload = null;\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.dataset.action = 'squeeze_bulk_compressed';\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.elements.postsFilterForm.submit();\r\n }\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n window.onbeforeunload = null;\r\n alert(__('An error has occured. Check the console for details.', 'squeeze'));\r\n }\r\n }\r\n});\r\n\r\n// https://wordpress.stackexchange.com/a/131295/186146 - override wp.Uploader.prototype.success\r\njQuery.extend(wp?.Uploader?.prototype, {\r\n init: function () {\r\n if (!originalUploaderInit) {\r\n console.error('wp.Uploader.prototype.init is not defined');\r\n return;\r\n }\r\n\r\n originalUploaderInit.apply(this, arguments);\r\n const uploader = this.uploader;\r\n\r\n uploader.bind('BeforeUpload', async function (up, pluploadFile) {\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleCompressBeforeUpload(up, pluploadFile, compressOptions);\r\n });\r\n\r\n uploader.bind('FileUploaded', async function (up, file, response) {\r\n if (file?._isExcluded) {\r\n console.warn('File is excluded from compression:', file.name);\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n if (file?._isFailed) {\r\n console.warn('File compression failed:', file.name);\r\n window.onbeforeunload = null;\r\n return;\r\n }\r\n\r\n const attachment = file?.attachment;\r\n\r\n if (!_helpers_js__WEBPACK_IMPORTED_MODULE_1__.maybeCompressAttachment(attachment?.attributes?.type, attachment?.attributes?.subtype, compressOptions)) {\r\n //console.warn('Skipping compression for:', attachment?.attributes?.type, attachment?.attributes?.subtype);\r\n return; // Skip compression for this attachment\r\n }\r\n // set 'uploading' param to true, to pause the uploading process\r\n window.onbeforeunload = _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleOnLeave;\r\n attachment.set('uploading', true);\r\n attachment.set('percent', 50);\r\n attachment.set('status', 'Squeezing'); // Set status to 'Squeezing' to indicate compression is in progress\r\n\r\n _helpers_js__WEBPACK_IMPORTED_MODULE_1__.extendAttachment(attachment, file);\r\n\r\n try {\r\n const compressData = await Squeeze.handleCompress(attachment);\r\n attachment.set('percent', 75); // Set percent to 75% to indicate compression is done\r\n const uploadData = await Squeeze.handleUpload({ attachment, base64: compressData });\r\n\r\n if (uploadData.success) {\r\n const compat = attachment.get('compat');\r\n const tempDiv = document.createElement('div');\r\n let compatItem = compat.item;\r\n\r\n tempDiv.innerHTML = compatItem;\r\n tempDiv.querySelector('.compat-field-squeeze_is_compressed .field').innerHTML = uploadData?.data?.message;\r\n compat.item = tempDiv.innerHTML;\r\n\r\n attachment.set('compat', compat);\r\n } else {\r\n console.warn(uploadData.data);\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n } finally {\r\n attachment.set('uploading', false);\r\n window.onbeforeunload = null;\r\n }\r\n\r\n //console.timeEnd('BeforeUpload')\r\n })\r\n\r\n },\r\n});\r\n\r\ndocument.onreadystatechange = function () {\r\n if (document.readyState === \"complete\") { // equivalent to jQuery $(document).ready()\r\n _handlers_js__WEBPACK_IMPORTED_MODULE_2__.handleMultiFileFormUpload(compressOptions);\r\n }\r\n}\r\n\r\n/**\r\n * Create the toggle preview checkbox\r\n * @param {Integer} attachmentId \r\n * @param {Boolean} isPlaceholder\r\n * @returns HTMLElement\r\n */\r\nconst createTogglePreview = (attachmentId, isPlaceholder = false) => {\r\n\r\n // Create the toggle\r\n const toggleWrap = document.createElement('span');\r\n const toggleInput = document.createElement('input');\r\n const toggleLabel = document.createElement('label');\r\n\r\n toggleInput.type = 'checkbox';\r\n toggleInput.className = 'squeeze-ios8-switch';\r\n toggleInput.id = 'squeeze-ios8-switch-' + attachmentId;\r\n toggleLabel.textContent = __('Squeeze Preview', 'squeeze');\r\n toggleLabel.htmlFor = toggleInput.id;\r\n toggleWrap.style.marginInlineStart = '1em';\r\n\r\n if (isPlaceholder) {\r\n toggleInput.disabled = true;\r\n toggleLabel.innerHTML += ' ' + sprintf(__('(<a href=\"%s\" target=\"_blank\">premium only</a>)', 'squeeze'), squeezeOptions.upgradeUrl);\r\n }\r\n\r\n toggleWrap.appendChild(toggleInput);\r\n toggleWrap.appendChild(toggleLabel);\r\n\r\n return toggleWrap;\r\n}\r\n\r\n\n\n//# sourceURL=webpack:///./assets/js/script.js?"); 40 40 41 41 /***/ }), … … 47 47 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 48 48 49 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SQUEEZE)\n/* harmony export */ });\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nclass SQUEEZE {\r\n\r\n constructor(squeeze) {\r\n this.options = JSON.parse(squeeze.options); // plugin options\r\n this.nonce = squeeze.nonce; // nonce\r\n this.ajaxUrl = squeeze.ajaxUrl; // ajax url\r\n this.timeout = parseInt(this.options.timeout) * 1000; // convert to milliseconds\r\n this.poolSize = navigator.hardwareConcurrency || 1; // number of threads\r\n }\r\n\r\n handleCompress = async ( attachment ) => {\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const name = attachmentData.name;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const sizes = attachmentData.sizes;\r\n const format = mime.split(\"/\")[1];\r\n const sourceType = format;\r\n const outputType = format;\r\n const skipFull = attachmentData.originalImageName === undefined ? true : false;\r\n const timeout = this.timeout;\r\n const isPreview = attachmentData?.isPreview ?? false;\r\n const file = attachmentData?.file ?? null;\r\n\r\n //console.log(attachmentData, 'attachmentData')\r\n\r\n const worker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(\"assets_js_worker_js\"), __webpack_require__.b), {type: undefined}); // worker url\r\n worker.postMessage({\r\n action: 'compress',\r\n format,\r\n url,\r\n name,\r\n sourceType,\r\n outputType,\r\n mime,\r\n sizes,\r\n skipFull,\r\n timeout,\r\n isPreview,\r\n file,\r\n options: this.options,\r\n //urlOriginal: urlOriginal,\r\n });\r\n\r\n return new Promise((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n worker.terminate();\r\n console.warn('Worker terminated');\r\n reject(__('Request timed out.', 'squeeze'));\r\n }, timeout);\r\n\r\n worker.onmessage = (event) => {\r\n clearTimeout(timeoutId);\r\n if (event.data.error) {\r\n reject(event.data.error);\r\n } else {\r\n resolve(event.data);\r\n }\r\n worker.terminate();\r\n };\r\n\r\n worker.onerror = (error) => {\r\n clearTimeout(timeoutId);\r\n reject(`Worker error: ${error.message}`);\r\n };\r\n });\r\n\r\n }\r\n\r\n handleUpload = async ({ attachment, base64, type = 'uncompressed', mediaIDs = [] }) => {\r\n\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const format = mime.split(\"/\")[1];\r\n const sizes = attachmentData.sizes;\r\n\r\n //console.log(attachmentData, 'attachmentData')\r\n\r\n const data = {\r\n action: 'squeeze_update_attachment',\r\n _ajax_nonce: this.nonce,\r\n filename: filename,\r\n type: 'image',\r\n format: format,\r\n base64: base64.base64,\r\n base64Sizes: base64.base64Sizes,\r\n base64Webp: base64.base64Webp,\r\n base64SizesWebp: base64.base64SizesWebp,\r\n attachmentID: attachmentID,\r\n url: url,\r\n process: type,\r\n }\r\n\r\n console.log(data, 'squeeze_update_attachment') \r\n\r\n try {\r\n const uploadResponse = await jQuery.ajax({\r\n url: this.ajaxUrl, // + '111',\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n //if (type === 'uncompressed' || type === 'all' || type === 'path') {\r\n //if (uploadResponse.success) {\r\n uploadResponse['mediaIDs'] = mediaIDs;\r\n //}\r\n\r\n uploadResponse['filename'] = filename;\r\n uploadResponse['url'] = url;\r\n uploadResponse['sizes'] = sizes;\r\n\r\n return uploadResponse;\r\n \r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n };\r\n }\r\n\r\n }\r\n\r\n handleBulkUpload = async (type = 'uncompressed', mediaIDs = []) => {\r\n let currentID;\r\n let attachment;\r\n\r\n switch (type) {\r\n case 'all':\r\n case 'uncompressed':\r\n currentID = mediaIDs[0];\r\n break;\r\n case 'path':\r\n currentID = mediaIDs[0]?.filename;\r\n break;\r\n default:\r\n currentID = 0;\r\n break;\r\n }\r\n\r\n if (type === 'path') {\r\n\r\n \r\n\r\n attachment = {\r\n attributes: {\r\n url: mediaIDs[0].url,\r\n mime: mediaIDs[0].mime,\r\n name: mediaIDs[0].name,\r\n filename: mediaIDs[0].filename,\r\n id: mediaIDs[0].id,\r\n sizes: mediaIDs[0]?.sizes,\r\n }\r\n }\r\n\r\n } else {\r\n\r\n const attachmentResponse = await this.getAttachment(currentID); \r\n if (attachmentResponse.success === false) {\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': attachmentResponse.data\r\n }\r\n }\r\n const attachmentData = attachmentResponse.data;\r\n attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n\r\n }\r\n\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n\r\n const mediaType = attachment.attributes.mime.split(\"/\")[0];\r\n const mediaSubType = attachment.attributes.mime.split(\"/\")[1];\r\n\r\n if (!this.maybeCompressAttachment(mediaType, mediaSubType)) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': __('Skipped', 'squeeze')\r\n }\r\n }\r\n\r\n try {\r\n const compressData = await this.handleCompress( attachment );\r\n const uploadData = await this.handleUpload({ attachment: attachment, base64: compressData, type: type, mediaIDs: mediaIDs })\r\n\r\n return uploadData;\r\n\r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n }\r\n }\r\n\r\n }\r\n\r\n maybeCompressAttachment = (attachmentType, attachmentSubType) => {\r\n const allowedMimeTypes = ['jpeg', 'png', 'webp', 'avif'];\r\n const isImage = attachmentType === 'image' && allowedMimeTypes.includes(attachmentSubType)\r\n\r\n if (isImage) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n \r\n\r\n handleRestore = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_restore_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n };\r\n\r\n const response = await jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n };\r\n\r\n // Get list of attachments by path\r\n getAttachmentsByPath = async (path) => {\r\n\r\n const data = {\r\n action: 'squeeze_get_attachment_by_path',\r\n path: path,\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getAttachment = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_get_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getNextAttachments = async (page = 1, type = 'uncompressed', lastId = 0) => {\r\n const data = {\r\n action: 'squeeze_get_next_attachments',\r\n _ajax_nonce: this.nonce,\r\n page: page,\r\n type: type,\r\n lastId: lastId,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getDirectories = async (parentDir = false) => {\r\n const data = {\r\n action: 'squeeze_get_directories',\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n if (parentDir) {\r\n data['parentDir'] = parentDir;\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n \r\n\r\n setOptions = async (options) => {\r\n const data = {\r\n action: 'squeeze_set_options',\r\n _ajax_nonce: this.nonce,\r\n options: options,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /*\r\n getSizesFromFile = (file) => {\r\n if (!file) return;\r\n\r\n // get list of thumbnails from file\r\n const sizes = {};\r\n \r\n const fd = new FormData();\r\n fd.append('action', 'squeeze_get_sizes_from_file');\r\n fd.append('_ajax_nonce', this.nonce);\r\n fd.append('file', file);\r\n\r\n jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: fd,\r\n processData: false,\r\n contentType: false,\r\n async: false, // synchronous request\r\n }).done((response) => {\r\n console.log(response, 'getSizesFromFile response');\r\n if (response.success) {\r\n Object.keys(response.data).forEach((size) => {\r\n sizes[size] = response.data[size];\r\n });\r\n } else {\r\n console.error('Error getting sizes from file:', response.data);\r\n }\r\n }).fail((error) => {\r\n console.error('AJAX error:', error);\r\n });\r\n\r\n return sizes;\r\n\r\n }\r\n */\r\n\r\n}\n\n//# sourceURL=webpack:///./assets/js/squeeze.js?"); 49 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SQUEEZE)\n/* harmony export */ });\n/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./helpers.js */ \"./assets/js/helpers.js\");\n/* harmony import */ var browser_image_compression__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! browser-image-compression */ \"./node_modules/browser-image-compression/dist/browser-image-compression.mjs\");\n/* harmony import */ var _jsquash_webp__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @jsquash/webp */ \"./node_modules/@jsquash/webp/encode.js\");\n\r\n\r\n\r\n\r\n\r\n\r\nconst { __ } = wp.i18n; // Import __() from wp.i18n\r\n\r\nclass SQUEEZE {\r\n\r\n constructor(squeeze) {\r\n this.options = JSON.parse(squeeze.options); // plugin options\r\n this.nonce = squeeze.nonce; // nonce\r\n this.ajaxUrl = squeeze.ajaxUrl; // ajax url\r\n this.timeout = parseInt(this.options.timeout) * 1000; // convert to milliseconds\r\n this.poolSize = navigator.hardwareConcurrency || 1; // number of threads\r\n }\r\n\r\n handleCompress = async ( attachment, type = 'uncompressed' ) => {\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const name = attachmentData.name;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const sizes = attachmentData.sizes;\r\n const format = mime.split(\"/\")[1];\r\n const sourceType = format;\r\n const outputType = format;\r\n const skipFull = attachmentData?.skipFull ?? attachmentData.originalImageName === undefined ? true : false;\r\n const timeout = this.timeout;\r\n const isPreview = attachmentData?.isPreview ?? false;\r\n const file = attachmentData?.file ?? null; // the original file, it passed for the newly uploaded attachment to compress it\r\n\r\n // the original compressed image base64, it passed when the attachment was already compressed and we need to compress thumbs only\r\n // we pass it in order to prevent re-compressing the original image when we need to compress thumbs only\r\n const base64Compressed = attachmentData?.base64Compressed ?? null; \r\n const base64WebpCompressed = attachmentData?.base64WebpCompressed ?? null; // the original compressed webp image base64\r\n\r\n const worker = new Worker(new URL(/* worker import */ __webpack_require__.p + __webpack_require__.u(\"assets_js_worker_js\"), __webpack_require__.b), {type: undefined}); // worker url\r\n const channel = new MessageChannel();\r\n worker.postMessage({\r\n action: 'compress',\r\n format,\r\n url,\r\n name,\r\n sourceType,\r\n outputType,\r\n mime,\r\n sizes,\r\n skipFull,\r\n timeout,\r\n isPreview,\r\n file,\r\n base64Compressed,\r\n base64WebpCompressed,\r\n type,\r\n options: this.options,\r\n //urlOriginal: urlOriginal,\r\n }, [channel.port2]);\r\n\r\n // Listen for compression requests from the worker via port1\r\n channel.port1.onmessage = async (ev) => {\r\n //console.log(\"Worker received compression request:\", ev.data);\r\n const { id, action, fileOrArrayBuffer, mime, options } = ev.data;\r\n if (action !== 'imageCompression') return;\r\n\r\n try {\r\n // Accept ArrayBuffer or Blob\r\n const blob = (fileOrArrayBuffer instanceof ArrayBuffer)\r\n ? new Blob([this.toUint8Array(fileOrArrayBuffer)], { type: mime })\r\n : fileOrArrayBuffer;\r\n\r\n const compressedBlob = await (0,browser_image_compression__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(blob, { useWebWorker: true, ...(options || {}) });\r\n\r\n // quick checks\r\n //console.log('compressedBlob.type, size:', compressedBlob.type, compressedBlob.size);\r\n // normalize final binary\r\n const compressedArrayBuffer = await compressedBlob.arrayBuffer();\r\n\r\n // Reply with the compressed ArrayBuffer (transfer to avoid copy)\r\n channel.port1.postMessage({ id, ok: true, arrayBuffer: compressedArrayBuffer }, [compressedArrayBuffer]);\r\n } catch (err) {\r\n channel.port1.postMessage({ id, ok: false, error: err.message || String(err) });\r\n }\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n worker.terminate();\r\n console.warn('Worker compress terminated', name, sourceType, outputType);\r\n reject(__('Request timed out.', 'squeeze'));\r\n }, timeout);\r\n\r\n worker.onmessage = (event) => {\r\n clearTimeout(timeoutId);\r\n if (event.data.error) {\r\n reject(event.data.error);\r\n } else {\r\n resolve(event.data);\r\n }\r\n worker.terminate();\r\n };\r\n\r\n worker.onerror = (error) => {\r\n clearTimeout(timeoutId);\r\n reject(`Worker error: ${error.message}`);\r\n };\r\n });\r\n\r\n }\r\n\r\n handleUpload = async ({ attachment, base64, type = 'uncompressed', mediaIDs = [] }) => {\r\n\r\n const attachmentData = attachment.attributes;\r\n const url = attachmentData?.originalImageURL ?? attachmentData.url;\r\n const mime = attachmentData.mime;\r\n const filename = attachmentData?.originalImageName ?? attachmentData.filename;\r\n const attachmentID = attachmentData.id;\r\n const format = base64?.isDirectWebp && type !== 'path' ? 'webp' : mime.split(\"/\")[1];\r\n const sizes = attachmentData.sizes;\r\n\r\n const isDirectWebp = base64?.isDirectWebp && mime !== 'image/webp';\r\n const isBackupOriginal = this.options?.backup_original ?? false; // check if backup original is enabled\r\n let originalFile = attachmentData?.originalFile ?? null; // the original file, used for creating backup\r\n \r\n // if originalFile is not provided, try to get it from the URL\r\n // used when the attachment needs to be converted to webp from jpg or png\r\n if (!originalFile && type !== 'path' && isBackupOriginal && isDirectWebp) {\r\n const file = await (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.getFileFromUrl)(url, filename, mime.split(\"/\")[1])\r\n //console.log('conveting original file to webp', file);\r\n originalFile = await this.convertFileToWebp(file);\r\n }\r\n //console.log('handleUpload attachmentData', attachmentData)\r\n\r\n const data = {\r\n action: 'squeeze_update_attachment',\r\n _ajax_nonce: this.nonce,\r\n filename: filename,\r\n type: 'image',\r\n format: format,\r\n base64: base64.base64,\r\n base64Sizes: base64.base64Sizes,\r\n base64Webp: base64.base64Webp,\r\n base64SizesWebp: base64.base64SizesWebp,\r\n attachmentID: attachmentID,\r\n url: url,\r\n process: type,\r\n originalFile: originalFile,\r\n }\r\n\r\n const formData = (0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.objectToFormData)(data);\r\n\r\n //console.log('squeeze_update_attachment', JSON.stringify(data, null, 2));\r\n\r\n try {\r\n const uploadResponse = await jQuery.ajax({\r\n url: this.ajaxUrl, // + '111',\r\n type: 'POST',\r\n data: formData,\r\n processData: false, // very important!\r\n contentType: false, // very important!\r\n });\r\n\r\n //if (uploadResponse.success) {\r\n uploadResponse['mediaIDs'] = mediaIDs;\r\n //}\r\n\r\n if (!uploadResponse?.data?.url) {\r\n uploadResponse.url = url; // fallback to original URL if not provided\r\n }\r\n\r\n //console.log('uploadResponse', JSON.stringify(uploadResponse, null, 2));\r\n\r\n return uploadResponse;\r\n \r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error.message,\r\n 'success': false\r\n };\r\n }\r\n\r\n }\r\n\r\n handleBulkUpload = async (type = 'uncompressed', mediaIDs = []) => {\r\n let currentID;\r\n let attachment;\r\n\r\n switch (type) {\r\n case 'all':\r\n case 'uncompressed':\r\n currentID = mediaIDs[0];\r\n break;\r\n case 'path':\r\n currentID = mediaIDs[0]?.filename;\r\n break;\r\n default:\r\n currentID = 0;\r\n break;\r\n }\r\n\r\n if (type === 'path') {\r\n\r\n \r\n\r\n attachment = {\r\n attributes: {\r\n url: mediaIDs[0].url,\r\n mime: mediaIDs[0].mime,\r\n name: mediaIDs[0].name,\r\n filename: mediaIDs[0].filename,\r\n id: mediaIDs[0].id,\r\n sizes: mediaIDs[0]?.sizes,\r\n }\r\n }\r\n\r\n } else {\r\n\r\n const attachmentResponse = await this.getAttachment(currentID); \r\n if (attachmentResponse.success === false) {\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': attachmentResponse.data\r\n }\r\n }\r\n const attachmentData = attachmentResponse.data;\r\n attachment = {\r\n attributes: {\r\n url: attachmentData.url,\r\n mime: attachmentData.mime,\r\n name: attachmentData.name,\r\n filename: attachmentData.filename,\r\n id: attachmentData.id,\r\n sizes: attachmentData.sizes,\r\n }\r\n }\r\n\r\n }\r\n\r\n if (Array.isArray(mediaIDs)) mediaIDs.shift();\r\n\r\n const mediaType = attachment.attributes.mime.split(\"/\")[0];\r\n const mediaSubType = attachment.attributes.mime.split(\"/\")[1];\r\n\r\n if (!(0,_helpers_js__WEBPACK_IMPORTED_MODULE_0__.maybeCompressAttachment)(mediaType, mediaSubType)) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': __('Skipped', 'squeeze')\r\n }\r\n }\r\n\r\n try {\r\n const compressData = await this.handleCompress( attachment, type );\r\n const uploadData = await this.handleUpload({ attachment: attachment, base64: compressData, type: type, mediaIDs: mediaIDs })\r\n\r\n return uploadData;\r\n\r\n } catch (error) {\r\n return {\r\n 'mediaIDs': mediaIDs,\r\n 'data': error?.message ?? error,\r\n 'success': false\r\n }\r\n }\r\n\r\n }\r\n\r\n \r\n\r\n handleRestore = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_restore_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n };\r\n\r\n const response = await jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n };\r\n\r\n // Get list of attachments by path\r\n getAttachmentsByPath = async (path) => {\r\n\r\n const data = {\r\n action: 'squeeze_get_attachment_by_path',\r\n path: path,\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getAttachment = async (attachmentID) => {\r\n const data = {\r\n action: 'squeeze_get_attachment',\r\n _ajax_nonce: this.nonce,\r\n attachmentID: attachmentID,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getNextAttachments = async (page = 1, type = 'uncompressed', lastId = 0) => {\r\n const data = {\r\n action: 'squeeze_get_next_attachments',\r\n _ajax_nonce: this.nonce,\r\n page: page,\r\n type: type,\r\n lastId: lastId,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n getDirectories = async (parentDir = false) => {\r\n const data = {\r\n action: 'squeeze_get_directories',\r\n _ajax_nonce: this.nonce,\r\n }\r\n\r\n if (parentDir) {\r\n data['parentDir'] = parentDir;\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n \r\n\r\n setOptions = async (options) => {\r\n const data = {\r\n action: 'squeeze_set_options',\r\n _ajax_nonce: this.nonce,\r\n options: options,\r\n }\r\n\r\n const response = jQuery.ajax({\r\n url: this.ajaxUrl,\r\n type: 'POST',\r\n data: data,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Compresses an image before upload.\r\n * If the compressSizes parameter is provided, it will compress the sizes specified along with the original image.\r\n * \r\n * @param {File} file - The file to be compressed\r\n * @param {object} compressSizes - Optional sizes for compression\r\n * @returns {Promise<object|boolean>} - Returns a Promise that resolves to the compressed file as a base64 object or false if the file is invalid\r\n */\r\n compressBeforeUpload = async (file, compressSizes = null) => {\r\n if (!(file instanceof Blob) && !(file instanceof File)) {\r\n console.error('Invalid file type:', file);\r\n return false; // Return false if the file is not a Blob or File\r\n }\r\n\r\n const attachment = {\r\n attributes: {\r\n url: null,\r\n mime: file.type,\r\n name: file.name,\r\n filename: file.name,\r\n id: 0,\r\n sizes: compressSizes,\r\n file: file,\r\n skipFull: false,\r\n }\r\n }\r\n\r\n try {\r\n const base64Obj = await this.handleCompress(attachment);\r\n\r\n return base64Obj; // Return the compressed file as base64Obj\r\n } catch (error) {\r\n console.error(error);\r\n return error; // Return the error for further handling\r\n }\r\n }\r\n\r\n isWebpEncodingSupported = async () => {\r\n try {\r\n const canvas = document.createElement('canvas');\r\n if (!canvas.toDataURL) return false;\r\n const data = canvas.toDataURL('image/webp');\r\n // WebP signature starts with \"data:image/webp\"\r\n return data.indexOf('data:image/webp') === 0;\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n\r\n handleConvertFileToWebp = async (args) => {\r\n const timeout = this.timeout;\r\n \r\n const { file, sourceType, name } = args;\r\n const fileBuffer = await file.arrayBuffer();\r\n const mime = sourceType === 'png' ? 'image/png' : 'image/jpeg';\r\n const inputBlob = new Blob([fileBuffer], { type: mime });\r\n // compression options you can tune\r\n const imageCompressionOptions = {\r\n useWebWorker: true,\r\n fileType: 'image/webp',\r\n };\r\n\r\n return new Promise(async (resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n console.warn('Worker convertToWebp terminated', name);\r\n reject(new Error(__('Request timed out.', 'squeeze')));\r\n }, timeout);\r\n\r\n try {\r\n\r\n const compressedBlob = await (0,browser_image_compression__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(inputBlob, imageCompressionOptions);\r\n\r\n // quick checks\r\n //console.log('compressedBlob.type, size:', compressedBlob.type, compressedBlob.size);\r\n // normalize final binary\r\n const webpArrayBuffer = await compressedBlob.arrayBuffer();\r\n\r\n const webpName = name.replace(/\\.\\w+$/, '.webp');\r\n const webpFile = new File([webpArrayBuffer], webpName, { type: 'image/webp', lastModified: Date.now() });\r\n\r\n clearTimeout(timeoutId);\r\n resolve({ webpFile }); // must return object with webpFile prop\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n console.error('Error during image processing:', error);\r\n reject(error);\r\n }\r\n });\r\n \r\n }\r\n\r\n // helper: normalize buffer-like inputs to Uint8Array\r\n toUint8Array = (bufferLike) => {\r\n if (bufferLike instanceof Uint8Array) return bufferLike;\r\n if (bufferLike instanceof ArrayBuffer) return new Uint8Array(bufferLike);\r\n if (ArrayBuffer.isView(bufferLike)) return new Uint8Array(bufferLike.buffer, bufferLike.byteOffset, bufferLike.byteLength);\r\n // Node Buffer (in some environments) has .buffer and .byteOffset\r\n if (bufferLike && typeof bufferLike === 'object' && bufferLike.buffer) {\r\n return new Uint8Array(bufferLike.buffer, bufferLike.byteOffset || 0, bufferLike.byteLength || bufferLike.length);\r\n }\r\n throw new Error('Unsupported buffer type: ' + Object.prototype.toString.call(bufferLike));\r\n }\r\n\r\n /**\r\n * Convert an image File to WebP.\r\n *\r\n * @param {File} inputFile — the original image File (e.g. JPEG, PNG).\r\n * @returns {Promise<File>} — a Promise that resolves to a WebP File.\r\n */\r\n convertFileToWebp = async (inputFile) => {\r\n // Ensure it’s an image\r\n if (!inputFile.type.startsWith('image/')) {\r\n throw new Error('Input must be an image File');\r\n }\r\n const args = {\r\n file: inputFile,\r\n sourceType: inputFile.type.split('/')[1], // e.g. 'jpeg', 'png'\r\n name: inputFile.name,\r\n }\r\n const webpSupported = await this.isWebpEncodingSupported();\r\n try {\r\n // Convert the image to WebP\r\n let webpData;\r\n if (webpSupported) {\r\n webpData = await this.handleConvertFileToWebp(args);\r\n } else {\r\n console.warn('WebP encoding not supported on this device. Using original format instead.');\r\n const webpName = args.name.replace(/\\.\\w+$/, '.webp');\r\n webpData = await this.convertToWebpWithJsquash(inputFile, webpName);\r\n }\r\n if (!webpData || !webpData.webpFile) {\r\n throw new Error('Failed to convert image to WebP');\r\n }\r\n\r\n return webpData.webpFile; // Return the WebP File\r\n\r\n } catch (error) {\r\n console.error('Error converting image to WebP:', error);\r\n throw error; // Re-throw the error for further handling\r\n }\r\n\r\n }\r\n\r\n /**\r\n * Convert an input (File | Blob | ArrayBuffer | Uint8Array) to a WebP File using @jsquash/webp.\r\n * @param {File|Blob|ArrayBuffer|Uint8Array} input\r\n * @param {string} outputName - desired filename for the .webp output\r\n * @param {{quality?: number, lossless?: boolean, method?: number}} [opts] - encoder options (quality 0-100)\r\n * @returns {Promise<File>} - WebP File\r\n */\r\n convertToWebpWithJsquash = async (input, outputName = 'out.webp', opts = { quality: 100 }) => {\r\n // Normalize input to Blob\r\n let blob;\r\n if (input instanceof Blob) {\r\n blob = input;\r\n } else if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) {\r\n blob = new Blob([input]);\r\n } else {\r\n throw new Error('Unsupported input type. Provide File, Blob, ArrayBuffer or TypedArray.');\r\n }\r\n\r\n // Load image into <img>\r\n const dataURL = await new Promise((resolve, reject) => {\r\n const fr = new FileReader();\r\n fr.onload = () => resolve(fr.result);\r\n fr.onerror = reject;\r\n fr.readAsDataURL(blob);\r\n });\r\n\r\n const img = await new Promise((resolve, reject) => {\r\n const i = new Image();\r\n i.onload = () => resolve(i);\r\n i.onerror = () => reject(new Error('Failed to load image for conversion'));\r\n i.src = dataURL;\r\n // avoid cross-origin taint if data-url is used\r\n });\r\n\r\n // Draw to canvas and extract ImageData\r\n const canvas = document.createElement('canvas');\r\n canvas.width = img.naturalWidth || img.width;\r\n canvas.height = img.naturalHeight || img.height;\r\n const ctx = canvas.getContext('2d');\r\n ctx.drawImage(img, 0, 0);\r\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n\r\n // encode -> returns ArrayBuffer (WASM libwebp)\r\n // opts example: { quality: 75, lossless: false, method: 4 }\r\n const webpArrayBuffer = await (0,_jsquash_webp__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(imageData, opts);\r\n\r\n // Validate a little (size)\r\n if (!webpArrayBuffer || webpArrayBuffer.byteLength < 20) {\r\n throw new Error('jsquash produced an invalid WebP buffer');\r\n }\r\n\r\n // Wrap into File\r\n const webpFile = new File([webpArrayBuffer], outputName.replace(/\\.\\w+$/, '.webp'), {\r\n type: 'image/webp',\r\n lastModified: Date.now(),\r\n });\r\n\r\n return {webpFile};\r\n }\r\n\r\n}\n\n//# sourceURL=webpack:///./assets/js/squeeze.js?"); 50 51 /***/ }), 52 53 /***/ "./node_modules/@jsquash/webp/encode.js": 54 /*!**********************************************!*\ 55 !*** ./node_modules/@jsquash/webp/encode.js ***! 56 \**********************************************/ 57 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 58 59 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ encode),\n/* harmony export */ \"init\": () => (/* binding */ init)\n/* harmony export */ });\n/* harmony import */ var _meta_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./meta.js */ \"./node_modules/@jsquash/webp/meta.js\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ \"./node_modules/@jsquash/webp/utils.js\");\n/* harmony import */ var wasm_feature_detect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! wasm-feature-detect */ \"./node_modules/wasm-feature-detect/dist/esm/index.js\");\n/**\n * Copyright 2020 Google Inc. All Rights Reserved.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n\nlet emscriptenModule;\nasync function init(module, moduleOptionOverrides) {\n if (await (0,wasm_feature_detect__WEBPACK_IMPORTED_MODULE_0__.simd)()) {\n const webpEncoder = await __webpack_require__.e(/*! import() */ \"vendors-node_modules_jsquash_webp_codec_enc_webp_enc_simd_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./codec/enc/webp_enc_simd.js */ \"./node_modules/@jsquash/webp/codec/enc/webp_enc_simd.js\"));\n emscriptenModule = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.initEmscriptenModule)(webpEncoder.default, module, moduleOptionOverrides);\n return emscriptenModule;\n }\n const webpEncoder = await __webpack_require__.e(/*! import() */ \"vendors-node_modules_jsquash_webp_codec_enc_webp_enc_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./codec/enc/webp_enc.js */ \"./node_modules/@jsquash/webp/codec/enc/webp_enc.js\"));\n emscriptenModule = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.initEmscriptenModule)(webpEncoder.default, module, moduleOptionOverrides);\n return emscriptenModule;\n}\nasync function encode(data, options = {}) {\n if (!emscriptenModule)\n emscriptenModule = init();\n const _options = { ..._meta_js__WEBPACK_IMPORTED_MODULE_2__.defaultOptions, ...options };\n const module = await emscriptenModule;\n const result = module.encode(data.data, data.width, data.height, _options);\n if (!result)\n throw new Error('Encoding error.');\n return result.buffer;\n}\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/encode.js?"); 60 61 /***/ }), 62 63 /***/ "./node_modules/@jsquash/webp/meta.js": 64 /*!********************************************!*\ 65 !*** ./node_modules/@jsquash/webp/meta.js ***! 66 \********************************************/ 67 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 68 69 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"defaultOptions\": () => (/* binding */ defaultOptions),\n/* harmony export */ \"extension\": () => (/* binding */ extension),\n/* harmony export */ \"label\": () => (/* binding */ label),\n/* harmony export */ \"mimeType\": () => (/* binding */ mimeType)\n/* harmony export */ });\nconst label = 'WebP';\nconst mimeType = 'image/webp';\nconst extension = 'webp';\n// These come from struct WebPConfig in encode.h.\nconst defaultOptions = {\n quality: 75,\n target_size: 0,\n target_PSNR: 0,\n method: 4,\n sns_strength: 50,\n filter_strength: 60,\n filter_sharpness: 0,\n filter_type: 1,\n partitions: 0,\n segments: 4,\n pass: 1,\n show_compressed: 0,\n preprocessing: 0,\n autofilter: 0,\n partition_limit: 0,\n alpha_compression: 1,\n alpha_filtering: 1,\n alpha_quality: 100,\n lossless: 0,\n exact: 0,\n image_hint: 0,\n emulate_jpeg_size: 0,\n thread_level: 0,\n low_memory: 0,\n near_lossless: 100,\n use_delta_palette: 0,\n use_sharp_yuv: 0,\n};\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/meta.js?"); 70 71 /***/ }), 72 73 /***/ "./node_modules/@jsquash/webp/utils.js": 74 /*!*********************************************!*\ 75 !*** ./node_modules/@jsquash/webp/utils.js ***! 76 \*********************************************/ 77 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 78 79 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"initEmscriptenModule\": () => (/* binding */ initEmscriptenModule)\n/* harmony export */ });\n/**\n * Copyright 2020 Google Inc. All Rights Reserved.\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module.\n */\nfunction initEmscriptenModule(moduleFactory, wasmModule, moduleOptionOverrides = {}) {\n let instantiateWasm;\n if (wasmModule) {\n instantiateWasm = (imports, callback) => {\n const instance = new WebAssembly.Instance(wasmModule, imports);\n callback(instance);\n return instance.exports;\n };\n }\n return moduleFactory({\n // Just to be safe, don't automatically invoke any wasm functions\n noInitialRun: true,\n instantiateWasm,\n ...moduleOptionOverrides,\n });\n}\n\n\n//# sourceURL=webpack:///./node_modules/@jsquash/webp/utils.js?"); 80 81 /***/ }), 82 83 /***/ "./node_modules/browser-image-compression/dist/browser-image-compression.mjs": 84 /*!***********************************************************************************!*\ 85 !*** ./node_modules/browser-image-compression/dist/browser-image-compression.mjs ***! 86 \***********************************************************************************/ 87 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 88 89 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ imageCompression)\n/* harmony export */ });\n/**\n * Browser Image Compression\n * v2.0.2\n * by Donald <[email protected]>\n * https://github.com/Donaldcwl/browser-image-compression\n */\n\nfunction _mergeNamespaces(e,t){return t.forEach((function(t){t&&\"string\"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(r){if(\"default\"!==r&&!(r in e)){var i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:function(){return t[r]}})}}))})),Object.freeze(e)}function copyExifWithoutOrientation(e,t){return new Promise((function(r,i){let o;return getApp1Segment(e).then((function(e){try{return o=e,r(new Blob([t.slice(0,2),o,t.slice(2)],{type:\"image/jpeg\"}))}catch(e){return i(e)}}),i)}))}const getApp1Segment=e=>new Promise(((t,r)=>{const i=new FileReader;i.addEventListener(\"load\",(({target:{result:e}})=>{const i=new DataView(e);let o=0;if(65496!==i.getUint16(o))return r(\"not a valid JPEG\");for(o+=2;;){const a=i.getUint16(o);if(65498===a)break;const s=i.getUint16(o+2);if(65505===a&&1165519206===i.getUint32(o+4)){const a=o+10;let f;switch(i.getUint16(a)){case 18761:f=!0;break;case 19789:f=!1;break;default:return r(\"TIFF header contains invalid endian\")}if(42!==i.getUint16(a+2,f))return r(\"TIFF header contains invalid version\");const l=i.getUint32(a+4,f),c=a+l+2+12*i.getUint16(a+l,f);for(let e=a+l+2;e<c;e+=12){if(274==i.getUint16(e,f)){if(3!==i.getUint16(e+2,f))return r(\"Orientation data type is invalid\");if(1!==i.getUint32(e+4,f))return r(\"Orientation data count is invalid\");i.setUint16(e+8,1,f);break}}return t(e.slice(o,o+2+s))}o+=2+s}return t(new Blob)})),i.readAsArrayBuffer(e)}));var e={},t={get exports(){return e},set exports(t){e=t}};!function(e){var r,i,UZIP={};t.exports=UZIP,UZIP.parse=function(e,t){for(var r=UZIP.bin.readUshort,i=UZIP.bin.readUint,o=0,a={},s=new Uint8Array(e),f=s.length-4;101010256!=i(s,f);)f--;o=f;o+=4;var l=r(s,o+=4);r(s,o+=2);var c=i(s,o+=2),u=i(s,o+=4);o+=4,o=u;for(var h=0;h<l;h++){i(s,o),o+=4,o+=4,o+=4,i(s,o+=4);c=i(s,o+=4);var d=i(s,o+=4),A=r(s,o+=4),g=r(s,o+2),p=r(s,o+4);o+=6;var m=i(s,o+=8);o+=4,o+=A+g+p,UZIP._readLocal(s,m,a,c,d,t)}return a},UZIP._readLocal=function(e,t,r,i,o,a){var s=UZIP.bin.readUshort,f=UZIP.bin.readUint;f(e,t),s(e,t+=4),s(e,t+=2);var l=s(e,t+=2);f(e,t+=2),f(e,t+=4),t+=4;var c=s(e,t+=8),u=s(e,t+=2);t+=2;var h=UZIP.bin.readUTF8(e,t,c);if(t+=c,t+=u,a)r[h]={size:o,csize:i};else{var d=new Uint8Array(e.buffer,t);if(0==l)r[h]=new Uint8Array(d.buffer.slice(t,t+i));else{if(8!=l)throw\"unknown compression method: \"+l;var A=new Uint8Array(o);UZIP.inflateRaw(d,A),r[h]=A}}},UZIP.inflateRaw=function(e,t){return UZIP.F.inflate(e,t)},UZIP.inflate=function(e,t){return e[0],e[1],UZIP.inflateRaw(new Uint8Array(e.buffer,e.byteOffset+2,e.length-6),t)},UZIP.deflate=function(e,t){null==t&&(t={level:6});var r=0,i=new Uint8Array(50+Math.floor(1.1*e.length));i[r]=120,i[r+1]=156,r+=2,r=UZIP.F.deflateRaw(e,i,r,t.level);var o=UZIP.adler(e,0,e.length);return i[r+0]=o>>>24&255,i[r+1]=o>>>16&255,i[r+2]=o>>>8&255,i[r+3]=o>>>0&255,new Uint8Array(i.buffer,0,r+4)},UZIP.deflateRaw=function(e,t){null==t&&(t={level:6});var r=new Uint8Array(50+Math.floor(1.1*e.length)),i=UZIP.F.deflateRaw(e,r,i,t.level);return new Uint8Array(r.buffer,0,i)},UZIP.encode=function(e,t){null==t&&(t=!1);var r=0,i=UZIP.bin.writeUint,o=UZIP.bin.writeUshort,a={};for(var s in e){var f=!UZIP._noNeed(s)&&!t,l=e[s],c=UZIP.crc.crc(l,0,l.length);a[s]={cpr:f,usize:l.length,crc:c,file:f?UZIP.deflateRaw(l):l}}for(var s in a)r+=a[s].file.length+30+46+2*UZIP.bin.sizeUTF8(s);r+=22;var u=new Uint8Array(r),h=0,d=[];for(var s in a){var A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,0)}var g=0,p=h;for(var s in a){A=a[s];d.push(h),h=UZIP._writeHeader(u,h,s,A,1,d[g++])}var m=h-p;return i(u,h,101010256),h+=4,o(u,h+=4,g),o(u,h+=2,g),i(u,h+=2,m),i(u,h+=4,p),h+=4,h+=2,u.buffer},UZIP._noNeed=function(e){var t=e.split(\".\").pop().toLowerCase();return-1!=\"png,jpg,jpeg,zip\".indexOf(t)},UZIP._writeHeader=function(e,t,r,i,o,a){var s=UZIP.bin.writeUint,f=UZIP.bin.writeUshort,l=i.file;return s(e,t,0==o?67324752:33639248),t+=4,1==o&&(t+=2),f(e,t,20),f(e,t+=2,0),f(e,t+=2,i.cpr?8:0),s(e,t+=2,0),s(e,t+=4,i.crc),s(e,t+=4,l.length),s(e,t+=4,i.usize),f(e,t+=4,UZIP.bin.sizeUTF8(r)),f(e,t+=2,0),t+=2,1==o&&(t+=2,t+=2,s(e,t+=6,a),t+=4),t+=UZIP.bin.writeUTF8(e,t,r),0==o&&(e.set(l,t),t+=l.length),t},UZIP.crc={table:function(){for(var e=new Uint32Array(256),t=0;t<256;t++){for(var r=t,i=0;i<8;i++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update:function(e,t,r,i){for(var o=0;o<i;o++)e=UZIP.crc.table[255&(e^t[r+o])]^e>>>8;return e},crc:function(e,t,r){return 4294967295^UZIP.crc.update(4294967295,e,t,r)}},UZIP.adler=function(e,t,r){for(var i=1,o=0,a=t,s=t+r;a<s;){for(var f=Math.min(a+5552,s);a<f;)o+=i+=e[a++];i%=65521,o%=65521}return o<<16|i},UZIP.bin={readUshort:function(e,t){return e[t]|e[t+1]<<8},writeUshort:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255},readUint:function(e,t){return 16777216*e[t+3]+(e[t+2]<<16|e[t+1]<<8|e[t])},writeUint:function(e,t,r){e[t]=255&r,e[t+1]=r>>8&255,e[t+2]=r>>16&255,e[t+3]=r>>24&255},readASCII:function(e,t,r){for(var i=\"\",o=0;o<r;o++)i+=String.fromCharCode(e[t+o]);return i},writeASCII:function(e,t,r){for(var i=0;i<r.length;i++)e[t+i]=r.charCodeAt(i)},pad:function(e){return e.length<2?\"0\"+e:e},readUTF8:function(e,t,r){for(var i,o=\"\",a=0;a<r;a++)o+=\"%\"+UZIP.bin.pad(e[t+a].toString(16));try{i=decodeURIComponent(o)}catch(i){return UZIP.bin.readASCII(e,t,r)}return i},writeUTF8:function(e,t,r){for(var i=r.length,o=0,a=0;a<i;a++){var s=r.charCodeAt(a);if(0==(4294967168&s))e[t+o]=s,o++;else if(0==(4294965248&s))e[t+o]=192|s>>6,e[t+o+1]=128|s>>0&63,o+=2;else if(0==(4294901760&s))e[t+o]=224|s>>12,e[t+o+1]=128|s>>6&63,e[t+o+2]=128|s>>0&63,o+=3;else{if(0!=(4292870144&s))throw\"e\";e[t+o]=240|s>>18,e[t+o+1]=128|s>>12&63,e[t+o+2]=128|s>>6&63,e[t+o+3]=128|s>>0&63,o+=4}}return o},sizeUTF8:function(e){for(var t=e.length,r=0,i=0;i<t;i++){var o=e.charCodeAt(i);if(0==(4294967168&o))r++;else if(0==(4294965248&o))r+=2;else if(0==(4294901760&o))r+=3;else{if(0!=(4292870144&o))throw\"e\";r+=4}}return r}},UZIP.F={},UZIP.F.deflateRaw=function(e,t,r,i){var o=[[0,0,0,0,0],[4,4,8,4,0],[4,5,16,8,0],[4,6,16,16,0],[4,10,16,32,0],[8,16,32,32,0],[8,16,128,128,0],[8,32,128,256,0],[32,128,258,1024,1],[32,258,258,4096,1]][i],a=UZIP.F.U,s=UZIP.F._goodIndex;UZIP.F._hash;var f=UZIP.F._putsE,l=0,c=r<<3,u=0,h=e.length;if(0==i){for(;l<h;){f(t,c,l+(_=Math.min(65535,h-l))==h?1:0),c=UZIP.F._copyExact(e,l,_,t,c+8),l+=_}return c>>>3}var d=a.lits,A=a.strt,g=a.prev,p=0,m=0,w=0,v=0,b=0,y=0;for(h>2&&(A[y=UZIP.F._hash(e,0)]=0),l=0;l<h;l++){if(b=y,l+1<h-2){y=UZIP.F._hash(e,l+1);var E=l+1&32767;g[E]=A[y],A[y]=E}if(u<=l){(p>14e3||m>26697)&&h-l>100&&(u<l&&(d[p]=l-u,p+=2,u=l),c=UZIP.F._writeBlock(l==h-1||u==h?1:0,d,p,v,e,w,l-w,t,c),p=m=v=0,w=l);var F=0;l<h-2&&(F=UZIP.F._bestMatch(e,l,g,b,Math.min(o[2],h-l),o[3]));var _=F>>>16,B=65535&F;if(0!=F){B=65535&F;var U=s(_=F>>>16,a.of0);a.lhst[257+U]++;var C=s(B,a.df0);a.dhst[C]++,v+=a.exb[U]+a.dxb[C],d[p]=_<<23|l-u,d[p+1]=B<<16|U<<8|C,p+=2,u=l+_}else a.lhst[e[l]]++;m++}}for(w==l&&0!=e.length||(u<l&&(d[p]=l-u,p+=2,u=l),c=UZIP.F._writeBlock(1,d,p,v,e,w,l-w,t,c),p=0,m=0,p=m=v=0,w=l);0!=(7&c);)c++;return c>>>3},UZIP.F._bestMatch=function(e,t,r,i,o,a){var s=32767&t,f=r[s],l=s-f+32768&32767;if(f==s||i!=UZIP.F._hash(e,t-l))return 0;for(var c=0,u=0,h=Math.min(32767,t);l<=h&&0!=--a&&f!=s;){if(0==c||e[t+c]==e[t+c-l]){var d=UZIP.F._howLong(e,t,l);if(d>c){if(u=l,(c=d)>=o)break;l+2<d&&(d=l+2);for(var A=0,g=0;g<d-2;g++){var p=t-l+g+32768&32767,m=p-r[p]+32768&32767;m>A&&(A=m,f=p)}}}l+=(s=f)-(f=r[s])+32768&32767}return c<<16|u},UZIP.F._howLong=function(e,t,r){if(e[t]!=e[t-r]||e[t+1]!=e[t+1-r]||e[t+2]!=e[t+2-r])return 0;var i=t,o=Math.min(e.length,t+258);for(t+=3;t<o&&e[t]==e[t-r];)t++;return t-i},UZIP.F._hash=function(e,t){return(e[t]<<8|e[t+1])+(e[t+2]<<4)&65535},UZIP.saved=0,UZIP.F._writeBlock=function(e,t,r,i,o,a,s,f,l){var c,u,h,d,A,g,p,m,w,v=UZIP.F.U,b=UZIP.F._putsF,y=UZIP.F._putsE;v.lhst[256]++,u=(c=UZIP.F.getTrees())[0],h=c[1],d=c[2],A=c[3],g=c[4],p=c[5],m=c[6],w=c[7];var E=32+(0==(l+3&7)?0:8-(l+3&7))+(s<<3),F=i+UZIP.F.contSize(v.fltree,v.lhst)+UZIP.F.contSize(v.fdtree,v.dhst),_=i+UZIP.F.contSize(v.ltree,v.lhst)+UZIP.F.contSize(v.dtree,v.dhst);_+=14+3*p+UZIP.F.contSize(v.itree,v.ihst)+(2*v.ihst[16]+3*v.ihst[17]+7*v.ihst[18]);for(var B=0;B<286;B++)v.lhst[B]=0;for(B=0;B<30;B++)v.dhst[B]=0;for(B=0;B<19;B++)v.ihst[B]=0;var U=E<F&&E<_?0:F<_?1:2;if(b(f,l,e),b(f,l+1,U),l+=3,0==U){for(;0!=(7&l);)l++;l=UZIP.F._copyExact(o,a,s,f,l)}else{var C,I;if(1==U&&(C=v.fltree,I=v.fdtree),2==U){UZIP.F.makeCodes(v.ltree,u),UZIP.F.revCodes(v.ltree,u),UZIP.F.makeCodes(v.dtree,h),UZIP.F.revCodes(v.dtree,h),UZIP.F.makeCodes(v.itree,d),UZIP.F.revCodes(v.itree,d),C=v.ltree,I=v.dtree,y(f,l,A-257),y(f,l+=5,g-1),y(f,l+=5,p-4),l+=4;for(var Q=0;Q<p;Q++)y(f,l+3*Q,v.itree[1+(v.ordr[Q]<<1)]);l+=3*p,l=UZIP.F._codeTiny(m,v.itree,f,l),l=UZIP.F._codeTiny(w,v.itree,f,l)}for(var M=a,x=0;x<r;x+=2){for(var S=t[x],R=S>>>23,T=M+(8388607&S);M<T;)l=UZIP.F._writeLit(o[M++],C,f,l);if(0!=R){var O=t[x+1],P=O>>16,H=O>>8&255,L=255&O;y(f,l=UZIP.F._writeLit(257+H,C,f,l),R-v.of0[H]),l+=v.exb[H],b(f,l=UZIP.F._writeLit(L,I,f,l),P-v.df0[L]),l+=v.dxb[L],M+=R}}l=UZIP.F._writeLit(256,C,f,l)}return l},UZIP.F._copyExact=function(e,t,r,i,o){var a=o>>>3;return i[a]=r,i[a+1]=r>>>8,i[a+2]=255-i[a],i[a+3]=255-i[a+1],a+=4,i.set(new Uint8Array(e.buffer,t,r),a),o+(r+4<<3)},UZIP.F.getTrees=function(){for(var e=UZIP.F.U,t=UZIP.F._hufTree(e.lhst,e.ltree,15),r=UZIP.F._hufTree(e.dhst,e.dtree,15),i=[],o=UZIP.F._lenCodes(e.ltree,i),a=[],s=UZIP.F._lenCodes(e.dtree,a),f=0;f<i.length;f+=2)e.ihst[i[f]]++;for(f=0;f<a.length;f+=2)e.ihst[a[f]]++;for(var l=UZIP.F._hufTree(e.ihst,e.itree,7),c=19;c>4&&0==e.itree[1+(e.ordr[c-1]<<1)];)c--;return[t,r,l,o,s,c,i,a]},UZIP.F.getSecond=function(e){for(var t=[],r=0;r<e.length;r+=2)t.push(e[r+1]);return t},UZIP.F.nonZero=function(e){for(var t=\"\",r=0;r<e.length;r+=2)0!=e[r+1]&&(t+=(r>>1)+\",\");return t},UZIP.F.contSize=function(e,t){for(var r=0,i=0;i<t.length;i++)r+=t[i]*e[1+(i<<1)];return r},UZIP.F._codeTiny=function(e,t,r,i){for(var o=0;o<e.length;o+=2){var a=e[o],s=e[o+1];i=UZIP.F._writeLit(a,t,r,i);var f=16==a?2:17==a?3:7;a>15&&(UZIP.F._putsE(r,i,s,f),i+=f)}return i},UZIP.F._lenCodes=function(e,t){for(var r=e.length;2!=r&&0==e[r-1];)r-=2;for(var i=0;i<r;i+=2){var o=e[i+1],a=i+3<r?e[i+3]:-1,s=i+5<r?e[i+5]:-1,f=0==i?-1:e[i-1];if(0==o&&a==o&&s==o){for(var l=i+5;l+2<r&&e[l+2]==o;)l+=2;(c=Math.min(l+1-i>>>1,138))<11?t.push(17,c-3):t.push(18,c-11),i+=2*c-2}else if(o==f&&a==o&&s==o){for(l=i+5;l+2<r&&e[l+2]==o;)l+=2;var c=Math.min(l+1-i>>>1,6);t.push(16,c-3),i+=2*c-2}else t.push(o,0)}return r>>>1},UZIP.F._hufTree=function(e,t,r){var i=[],o=e.length,a=t.length,s=0;for(s=0;s<a;s+=2)t[s]=0,t[s+1]=0;for(s=0;s<o;s++)0!=e[s]&&i.push({lit:s,f:e[s]});var f=i.length,l=i.slice(0);if(0==f)return 0;if(1==f){var c=i[0].lit;l=0==c?1:0;return t[1+(c<<1)]=1,t[1+(l<<1)]=1,1}i.sort((function(e,t){return e.f-t.f}));var u=i[0],h=i[1],d=0,A=1,g=2;for(i[0]={lit:-1,f:u.f+h.f,l:u,r:h,d:0};A!=f-1;)u=d!=A&&(g==f||i[d].f<i[g].f)?i[d++]:i[g++],h=d!=A&&(g==f||i[d].f<i[g].f)?i[d++]:i[g++],i[A++]={lit:-1,f:u.f+h.f,l:u,r:h};var p=UZIP.F.setDepth(i[A-1],0);for(p>r&&(UZIP.F.restrictDepth(l,r,p),p=r),s=0;s<f;s++)t[1+(l[s].lit<<1)]=l[s].d;return p},UZIP.F.setDepth=function(e,t){return-1!=e.lit?(e.d=t,t):Math.max(UZIP.F.setDepth(e.l,t+1),UZIP.F.setDepth(e.r,t+1))},UZIP.F.restrictDepth=function(e,t,r){var i=0,o=1<<r-t,a=0;for(e.sort((function(e,t){return t.d==e.d?e.f-t.f:t.d-e.d})),i=0;i<e.length&&e[i].d>t;i++){var s=e[i].d;e[i].d=t,a+=o-(1<<r-s)}for(a>>>=r-t;a>0;){(s=e[i].d)<t?(e[i].d++,a-=1<<t-s-1):i++}for(;i>=0;i--)e[i].d==t&&a<0&&(e[i].d--,a++);0!=a&&console.log(\"debt left\")},UZIP.F._goodIndex=function(e,t){var r=0;return t[16|r]<=e&&(r|=16),t[8|r]<=e&&(r|=8),t[4|r]<=e&&(r|=4),t[2|r]<=e&&(r|=2),t[1|r]<=e&&(r|=1),r},UZIP.F._writeLit=function(e,t,r,i){return UZIP.F._putsF(r,i,t[e<<1]),i+t[1+(e<<1)]},UZIP.F.inflate=function(e,t){var r=Uint8Array;if(3==e[0]&&0==e[1])return t||new r(0);var i=UZIP.F,o=i._bitsF,a=i._bitsE,s=i._decodeTiny,f=i.makeCodes,l=i.codes2map,c=i._get17,u=i.U,h=null==t;h&&(t=new r(e.length>>>2<<3));for(var d,A,g=0,p=0,m=0,w=0,v=0,b=0,y=0,E=0,F=0;0==g;)if(g=o(e,F,1),p=o(e,F+1,2),F+=3,0!=p){if(h&&(t=UZIP.F._check(t,E+(1<<17))),1==p&&(d=u.flmap,A=u.fdmap,b=511,y=31),2==p){m=a(e,F,5)+257,w=a(e,F+5,5)+1,v=a(e,F+10,4)+4,F+=14;for(var _=0;_<38;_+=2)u.itree[_]=0,u.itree[_+1]=0;var B=1;for(_=0;_<v;_++){var U=a(e,F+3*_,3);u.itree[1+(u.ordr[_]<<1)]=U,U>B&&(B=U)}F+=3*v,f(u.itree,B),l(u.itree,B,u.imap),d=u.lmap,A=u.dmap,F=s(u.imap,(1<<B)-1,m+w,e,F,u.ttree);var C=i._copyOut(u.ttree,0,m,u.ltree);b=(1<<C)-1;var I=i._copyOut(u.ttree,m,w,u.dtree);y=(1<<I)-1,f(u.ltree,C),l(u.ltree,C,d),f(u.dtree,I),l(u.dtree,I,A)}for(;;){var Q=d[c(e,F)&b];F+=15&Q;var M=Q>>>4;if(M>>>8==0)t[E++]=M;else{if(256==M)break;var x=E+M-254;if(M>264){var S=u.ldef[M-257];x=E+(S>>>3)+a(e,F,7&S),F+=7&S}var R=A[c(e,F)&y];F+=15&R;var T=R>>>4,O=u.ddef[T],P=(O>>>4)+o(e,F,15&O);for(F+=15&O,h&&(t=UZIP.F._check(t,E+(1<<17)));E<x;)t[E]=t[E++-P],t[E]=t[E++-P],t[E]=t[E++-P],t[E]=t[E++-P];E=x}}}else{0!=(7&F)&&(F+=8-(7&F));var H=4+(F>>>3),L=e[H-4]|e[H-3]<<8;h&&(t=UZIP.F._check(t,E+L)),t.set(new r(e.buffer,e.byteOffset+H,L),E),F=H+L<<3,E+=L}return t.length==E?t:t.slice(0,E)},UZIP.F._check=function(e,t){var r=e.length;if(t<=r)return e;var i=new Uint8Array(Math.max(r<<1,t));return i.set(e,0),i},UZIP.F._decodeTiny=function(e,t,r,i,o,a){for(var s=UZIP.F._bitsE,f=UZIP.F._get17,l=0;l<r;){var c=e[f(i,o)&t];o+=15&c;var u=c>>>4;if(u<=15)a[l]=u,l++;else{var h=0,d=0;16==u?(d=3+s(i,o,2),o+=2,h=a[l-1]):17==u?(d=3+s(i,o,3),o+=3):18==u&&(d=11+s(i,o,7),o+=7);for(var A=l+d;l<A;)a[l]=h,l++}}return o},UZIP.F._copyOut=function(e,t,r,i){for(var o=0,a=0,s=i.length>>>1;a<r;){var f=e[a+t];i[a<<1]=0,i[1+(a<<1)]=f,f>o&&(o=f),a++}for(;a<s;)i[a<<1]=0,i[1+(a<<1)]=0,a++;return o},UZIP.F.makeCodes=function(e,t){for(var r,i,o,a,s=UZIP.F.U,f=e.length,l=s.bl_count,c=0;c<=t;c++)l[c]=0;for(c=1;c<f;c+=2)l[e[c]]++;var u=s.next_code;for(r=0,l[0]=0,i=1;i<=t;i++)r=r+l[i-1]<<1,u[i]=r;for(o=0;o<f;o+=2)0!=(a=e[o+1])&&(e[o]=u[a],u[a]++)},UZIP.F.codes2map=function(e,t,r){for(var i=e.length,o=UZIP.F.U.rev15,a=0;a<i;a+=2)if(0!=e[a+1])for(var s=a>>1,f=e[a+1],l=s<<4|f,c=t-f,u=e[a]<<c,h=u+(1<<c);u!=h;){r[o[u]>>>15-t]=l,u++}},UZIP.F.revCodes=function(e,t){for(var r=UZIP.F.U.rev15,i=15-t,o=0;o<e.length;o+=2){var a=e[o]<<t-e[o+1];e[o]=r[a]>>>i}},UZIP.F._putsE=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},UZIP.F._putsF=function(e,t,r){r<<=7&t;var i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},UZIP.F._bitsE=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<<r)-1},UZIP.F._bitsF=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<<r)-1},UZIP.F._get17=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},UZIP.F._get25=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},UZIP.F.U=(r=Uint16Array,i=Uint32Array,{next_code:new r(16),bl_count:new r(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new r(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new i(32),flmap:new r(512),fltree:[],fdmap:new r(32),fdtree:[],lmap:new r(32768),ltree:[],ttree:[],dmap:new r(32768),dtree:[],imap:new r(512),itree:[],rev15:new r(32768),lhst:new i(286),dhst:new i(30),ihst:new i(19),lits:new i(15e3),strt:new r(65536),prev:new r(32768)}),function(){for(var e=UZIP.F.U,t=0;t<32768;t++){var r=t;r=(4278255360&(r=(4042322160&(r=(3435973836&(r=(2863311530&r)>>>1|(1431655765&r)<<1))>>>2|(858993459&r)<<2))>>>4|(252645135&r)<<4))>>>8|(16711935&r)<<8,e.rev15[t]=(r>>>16|r<<16)>>>17}function pushV(e,t,r){for(;0!=t--;)e.push(0,r)}for(t=0;t<32;t++)e.ldef[t]=e.of0[t]<<3|e.exb[t],e.ddef[t]=e.df0[t]<<4|e.dxb[t];pushV(e.fltree,144,8),pushV(e.fltree,112,9),pushV(e.fltree,24,7),pushV(e.fltree,8,8),UZIP.F.makeCodes(e.fltree,9),UZIP.F.codes2map(e.fltree,9,e.flmap),UZIP.F.revCodes(e.fltree,9),pushV(e.fdtree,32,5),UZIP.F.makeCodes(e.fdtree,5),UZIP.F.codes2map(e.fdtree,5,e.fdmap),UZIP.F.revCodes(e.fdtree,5),pushV(e.itree,19,0),pushV(e.ltree,286,0),pushV(e.dtree,30,0),pushV(e.ttree,320,0)}()}();var UZIP=_mergeNamespaces({__proto__:null,default:e},[e]);const UPNG=function(){var e={nextZero(e,t){for(;0!=e[t];)t++;return t},readUshort:(e,t)=>e[t]<<8|e[t+1],writeUshort(e,t,r){e[t]=r>>8&255,e[t+1]=255&r},readUint:(e,t)=>16777216*e[t]+(e[t+1]<<16|e[t+2]<<8|e[t+3]),writeUint(e,t,r){e[t]=r>>24&255,e[t+1]=r>>16&255,e[t+2]=r>>8&255,e[t+3]=255&r},readASCII(e,t,r){let i=\"\";for(let o=0;o<r;o++)i+=String.fromCharCode(e[t+o]);return i},writeASCII(e,t,r){for(let i=0;i<r.length;i++)e[t+i]=r.charCodeAt(i)},readBytes(e,t,r){const i=[];for(let o=0;o<r;o++)i.push(e[t+o]);return i},pad:e=>e.length<2?`0${e}`:e,readUTF8(t,r,i){let o,a=\"\";for(let o=0;o<i;o++)a+=`%${e.pad(t[r+o].toString(16))}`;try{o=decodeURIComponent(a)}catch(o){return e.readASCII(t,r,i)}return o}};function decodeImage(t,r,i,o){const a=r*i,s=_getBPP(o),f=Math.ceil(r*s/8),l=new Uint8Array(4*a),c=new Uint32Array(l.buffer),{ctype:u}=o,{depth:h}=o,d=e.readUshort;if(6==u){const e=a<<2;if(8==h)for(var A=0;A<e;A+=4)l[A]=t[A],l[A+1]=t[A+1],l[A+2]=t[A+2],l[A+3]=t[A+3];if(16==h)for(A=0;A<e;A++)l[A]=t[A<<1]}else if(2==u){const e=o.tabs.tRNS;if(null==e){if(8==h)for(A=0;A<a;A++){var g=3*A;c[A]=255<<24|t[g+2]<<16|t[g+1]<<8|t[g]}if(16==h)for(A=0;A<a;A++){g=6*A;c[A]=255<<24|t[g+4]<<16|t[g+2]<<8|t[g]}}else{var p=e[0];const r=e[1],i=e[2];if(8==h)for(A=0;A<a;A++){var m=A<<2;g=3*A;c[A]=255<<24|t[g+2]<<16|t[g+1]<<8|t[g],t[g]==p&&t[g+1]==r&&t[g+2]==i&&(l[m+3]=0)}if(16==h)for(A=0;A<a;A++){m=A<<2,g=6*A;c[A]=255<<24|t[g+4]<<16|t[g+2]<<8|t[g],d(t,g)==p&&d(t,g+2)==r&&d(t,g+4)==i&&(l[m+3]=0)}}}else if(3==u){const e=o.tabs.PLTE,s=o.tabs.tRNS,c=s?s.length:0;if(1==h)for(var w=0;w<i;w++){var v=w*f,b=w*r;for(A=0;A<r;A++){m=b+A<<2;var y=3*(E=t[v+(A>>3)]>>7-((7&A)<<0)&1);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}}if(2==h)for(w=0;w<i;w++)for(v=w*f,b=w*r,A=0;A<r;A++){m=b+A<<2,y=3*(E=t[v+(A>>2)]>>6-((3&A)<<1)&3);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}if(4==h)for(w=0;w<i;w++)for(v=w*f,b=w*r,A=0;A<r;A++){m=b+A<<2,y=3*(E=t[v+(A>>1)]>>4-((1&A)<<2)&15);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}if(8==h)for(A=0;A<a;A++){var E;m=A<<2,y=3*(E=t[A]);l[m]=e[y],l[m+1]=e[y+1],l[m+2]=e[y+2],l[m+3]=E<c?s[E]:255}}else if(4==u){if(8==h)for(A=0;A<a;A++){m=A<<2;var F=t[_=A<<1];l[m]=F,l[m+1]=F,l[m+2]=F,l[m+3]=t[_+1]}if(16==h)for(A=0;A<a;A++){var _;m=A<<2,F=t[_=A<<2];l[m]=F,l[m+1]=F,l[m+2]=F,l[m+3]=t[_+2]}}else if(0==u)for(p=o.tabs.tRNS?o.tabs.tRNS:-1,w=0;w<i;w++){const e=w*f,i=w*r;if(1==h)for(var B=0;B<r;B++){var U=(F=255*(t[e+(B>>>3)]>>>7-(7&B)&1))==255*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(2==h)for(B=0;B<r;B++){U=(F=85*(t[e+(B>>>2)]>>>6-((3&B)<<1)&3))==85*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(4==h)for(B=0;B<r;B++){U=(F=17*(t[e+(B>>>1)]>>>4-((1&B)<<2)&15))==17*p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(8==h)for(B=0;B<r;B++){U=(F=t[e+B])==p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}else if(16==h)for(B=0;B<r;B++){F=t[e+(B<<1)],U=d(t,e+(B<<1))==p?0:255;c[i+B]=U<<24|F<<16|F<<8|F}}return l}function _decompress(e,r,i,o){const a=_getBPP(e),s=Math.ceil(i*a/8),f=new Uint8Array((s+1+e.interlace)*o);return r=e.tabs.CgBI?t(r,f):_inflate(r,f),0==e.interlace?r=_filterZero(r,e,0,i,o):1==e.interlace&&(r=function _readInterlace(e,t){const r=t.width,i=t.height,o=_getBPP(t),a=o>>3,s=Math.ceil(r*o/8),f=new Uint8Array(i*s);let l=0;const c=[0,0,4,0,2,0,1],u=[0,4,0,2,0,1,0],h=[8,8,8,4,4,2,2],d=[8,8,4,4,2,2,1];let A=0;for(;A<7;){const p=h[A],m=d[A];let w=0,v=0,b=c[A];for(;b<i;)b+=p,v++;let y=u[A];for(;y<r;)y+=m,w++;const E=Math.ceil(w*o/8);_filterZero(e,t,l,w,v);let F=0,_=c[A];for(;_<i;){let t=u[A],i=l+F*E<<3;for(;t<r;){var g;if(1==o)g=(g=e[i>>3])>>7-(7&i)&1,f[_*s+(t>>3)]|=g<<7-((7&t)<<0);if(2==o)g=(g=e[i>>3])>>6-(7&i)&3,f[_*s+(t>>2)]|=g<<6-((3&t)<<1);if(4==o)g=(g=e[i>>3])>>4-(7&i)&15,f[_*s+(t>>1)]|=g<<4-((1&t)<<2);if(o>=8){const r=_*s+t*a;for(let t=0;t<a;t++)f[r+t]=e[(i>>3)+t]}i+=o,t+=m}F++,_+=p}w*v!=0&&(l+=v*(1+E)),A+=1}return f}(r,e)),r}function _inflate(e,r){return t(new Uint8Array(e.buffer,2,e.length-6),r)}var t=function(){const e={H:{}};return e.H.N=function(t,r){const i=Uint8Array;let o,a,s=0,f=0,l=0,c=0,u=0,h=0,d=0,A=0,g=0;if(3==t[0]&&0==t[1])return r||new i(0);const p=e.H,m=p.b,w=p.e,v=p.R,b=p.n,y=p.A,E=p.Z,F=p.m,_=null==r;for(_&&(r=new i(t.length>>>2<<5));0==s;)if(s=m(t,g,1),f=m(t,g+1,2),g+=3,0!=f){if(_&&(r=e.H.W(r,A+(1<<17))),1==f&&(o=F.J,a=F.h,h=511,d=31),2==f){l=w(t,g,5)+257,c=w(t,g+5,5)+1,u=w(t,g+10,4)+4,g+=14;let e=1;for(var B=0;B<38;B+=2)F.Q[B]=0,F.Q[B+1]=0;for(B=0;B<u;B++){const r=w(t,g+3*B,3);F.Q[1+(F.X[B]<<1)]=r,r>e&&(e=r)}g+=3*u,b(F.Q,e),y(F.Q,e,F.u),o=F.w,a=F.d,g=v(F.u,(1<<e)-1,l+c,t,g,F.v);const r=p.V(F.v,0,l,F.C);h=(1<<r)-1;const i=p.V(F.v,l,c,F.D);d=(1<<i)-1,b(F.C,r),y(F.C,r,o),b(F.D,i),y(F.D,i,a)}for(;;){const e=o[E(t,g)&h];g+=15&e;const i=e>>>4;if(i>>>8==0)r[A++]=i;else{if(256==i)break;{let e=A+i-254;if(i>264){const r=F.q[i-257];e=A+(r>>>3)+w(t,g,7&r),g+=7&r}const o=a[E(t,g)&d];g+=15&o;const s=o>>>4,f=F.c[s],l=(f>>>4)+m(t,g,15&f);for(g+=15&f;A<e;)r[A]=r[A++-l],r[A]=r[A++-l],r[A]=r[A++-l],r[A]=r[A++-l];A=e}}}}else{0!=(7&g)&&(g+=8-(7&g));const o=4+(g>>>3),a=t[o-4]|t[o-3]<<8;_&&(r=e.H.W(r,A+a)),r.set(new i(t.buffer,t.byteOffset+o,a),A),g=o+a<<3,A+=a}return r.length==A?r:r.slice(0,A)},e.H.W=function(e,t){const r=e.length;if(t<=r)return e;const i=new Uint8Array(r<<1);return i.set(e,0),i},e.H.R=function(t,r,i,o,a,s){const f=e.H.e,l=e.H.Z;let c=0;for(;c<i;){const e=t[l(o,a)&r];a+=15&e;const i=e>>>4;if(i<=15)s[c]=i,c++;else{let e=0,t=0;16==i?(t=3+f(o,a,2),a+=2,e=s[c-1]):17==i?(t=3+f(o,a,3),a+=3):18==i&&(t=11+f(o,a,7),a+=7);const r=c+t;for(;c<r;)s[c]=e,c++}}return a},e.H.V=function(e,t,r,i){let o=0,a=0;const s=i.length>>>1;for(;a<r;){const r=e[a+t];i[a<<1]=0,i[1+(a<<1)]=r,r>o&&(o=r),a++}for(;a<s;)i[a<<1]=0,i[1+(a<<1)]=0,a++;return o},e.H.n=function(t,r){const i=e.H.m,o=t.length;let a,s,f;let l;const c=i.j;for(var u=0;u<=r;u++)c[u]=0;for(u=1;u<o;u+=2)c[t[u]]++;const h=i.K;for(a=0,c[0]=0,s=1;s<=r;s++)a=a+c[s-1]<<1,h[s]=a;for(f=0;f<o;f+=2)l=t[f+1],0!=l&&(t[f]=h[l],h[l]++)},e.H.A=function(t,r,i){const o=t.length,a=e.H.m.r;for(let e=0;e<o;e+=2)if(0!=t[e+1]){const o=e>>1,s=t[e+1],f=o<<4|s,l=r-s;let c=t[e]<<l;const u=c+(1<<l);for(;c!=u;){i[a[c]>>>15-r]=f,c++}}},e.H.l=function(t,r){const i=e.H.m.r,o=15-r;for(let e=0;e<t.length;e+=2){const a=t[e]<<r-t[e+1];t[e]=i[a]>>>o}},e.H.M=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8},e.H.I=function(e,t,r){r<<=7&t;const i=t>>>3;e[i]|=r,e[i+1]|=r>>>8,e[i+2]|=r>>>16},e.H.e=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8)>>>(7&t)&(1<<r)-1},e.H.b=function(e,t,r){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)&(1<<r)-1},e.H.Z=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16)>>>(7&t)},e.H.i=function(e,t){return(e[t>>>3]|e[1+(t>>>3)]<<8|e[2+(t>>>3)]<<16|e[3+(t>>>3)]<<24)>>>(7&t)},e.H.m=function(){const e=Uint16Array,t=Uint32Array;return{K:new e(16),j:new e(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new e(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new t(32),J:new e(512),_:[],h:new e(32),$:[],w:new e(32768),C:[],v:[],d:new e(32768),D:[],u:new e(512),Q:[],r:new e(32768),s:new t(286),Y:new t(30),a:new t(19),t:new t(15e3),k:new e(65536),g:new e(32768)}}(),function(){const t=e.H.m;for(var r=0;r<32768;r++){let e=r;e=(2863311530&e)>>>1|(1431655765&e)<<1,e=(3435973836&e)>>>2|(858993459&e)<<2,e=(4042322160&e)>>>4|(252645135&e)<<4,e=(4278255360&e)>>>8|(16711935&e)<<8,t.r[r]=(e>>>16|e<<16)>>>17}function n(e,t,r){for(;0!=t--;)e.push(0,r)}for(r=0;r<32;r++)t.q[r]=t.S[r]<<3|t.T[r],t.c[r]=t.p[r]<<4|t.z[r];n(t._,144,8),n(t._,112,9),n(t._,24,7),n(t._,8,8),e.H.n(t._,9),e.H.A(t._,9,t.J),e.H.l(t._,9),n(t.$,32,5),e.H.n(t.$,5),e.H.A(t.$,5,t.h),e.H.l(t.$,5),n(t.Q,19,0),n(t.C,286,0),n(t.D,30,0),n(t.v,320,0)}(),e.H.N}();function _getBPP(e){return[1,null,3,1,2,null,4][e.ctype]*e.depth}function _filterZero(e,t,r,i,o){let a=_getBPP(t);const s=Math.ceil(i*a/8);let f,l;a=Math.ceil(a/8);let c=e[r],u=0;if(c>1&&(e[r]=[0,0,1][c-2]),3==c)for(u=a;u<s;u++)e[u+1]=e[u+1]+(e[u+1-a]>>>1)&255;for(let t=0;t<o;t++)if(f=r+t*s,l=f+t+1,c=e[l-1],u=0,0==c)for(;u<s;u++)e[f+u]=e[l+u];else if(1==c){for(;u<a;u++)e[f+u]=e[l+u];for(;u<s;u++)e[f+u]=e[l+u]+e[f+u-a]}else if(2==c)for(;u<s;u++)e[f+u]=e[l+u]+e[f+u-s];else if(3==c){for(;u<a;u++)e[f+u]=e[l+u]+(e[f+u-s]>>>1);for(;u<s;u++)e[f+u]=e[l+u]+(e[f+u-s]+e[f+u-a]>>>1)}else{for(;u<a;u++)e[f+u]=e[l+u]+_paeth(0,e[f+u-s],0);for(;u<s;u++)e[f+u]=e[l+u]+_paeth(e[f+u-a],e[f+u-s],e[f+u-a-s])}return e}function _paeth(e,t,r){const i=e+t-r,o=i-e,a=i-t,s=i-r;return o*o<=a*a&&o*o<=s*s?e:a*a<=s*s?t:r}function _IHDR(t,r,i){i.width=e.readUint(t,r),r+=4,i.height=e.readUint(t,r),r+=4,i.depth=t[r],r++,i.ctype=t[r],r++,i.compress=t[r],r++,i.filter=t[r],r++,i.interlace=t[r],r++}function _copyTile(e,t,r,i,o,a,s,f,l){const c=Math.min(t,o),u=Math.min(r,a);let h=0,d=0;for(let r=0;r<u;r++)for(let a=0;a<c;a++)if(s>=0&&f>=0?(h=r*t+a<<2,d=(f+r)*o+s+a<<2):(h=(-f+r)*t-s+a<<2,d=r*o+a<<2),0==l)i[d]=e[h],i[d+1]=e[h+1],i[d+2]=e[h+2],i[d+3]=e[h+3];else if(1==l){var A=e[h+3]*(1/255),g=e[h]*A,p=e[h+1]*A,m=e[h+2]*A,w=i[d+3]*(1/255),v=i[d]*w,b=i[d+1]*w,y=i[d+2]*w;const t=1-A,r=A+w*t,o=0==r?0:1/r;i[d+3]=255*r,i[d+0]=(g+v*t)*o,i[d+1]=(p+b*t)*o,i[d+2]=(m+y*t)*o}else if(2==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];A==w&&g==v&&p==b&&m==y?(i[d]=0,i[d+1]=0,i[d+2]=0,i[d+3]=0):(i[d]=g,i[d+1]=p,i[d+2]=m,i[d+3]=A)}else if(3==l){A=e[h+3],g=e[h],p=e[h+1],m=e[h+2],w=i[d+3],v=i[d],b=i[d+1],y=i[d+2];if(A==w&&g==v&&p==b&&m==y)continue;if(A<220&&w>20)return!1}return!0}return{decode:function decode(r){const i=new Uint8Array(r);let o=8;const a=e,s=a.readUshort,f=a.readUint,l={tabs:{},frames:[]},c=new Uint8Array(i.length);let u,h=0,d=0;const A=[137,80,78,71,13,10,26,10];for(var g=0;g<8;g++)if(i[g]!=A[g])throw\"The input is not a PNG file!\";for(;o<i.length;){const e=a.readUint(i,o);o+=4;const r=a.readASCII(i,o,4);if(o+=4,\"IHDR\"==r)_IHDR(i,o,l);else if(\"iCCP\"==r){for(var p=o;0!=i[p];)p++;a.readASCII(i,o,p-o),i[p+1];const s=i.slice(p+2,o+e);let f=null;try{f=_inflate(s)}catch(e){f=t(s)}l.tabs[r]=f}else if(\"CgBI\"==r)l.tabs[r]=i.slice(o,o+4);else if(\"IDAT\"==r){for(g=0;g<e;g++)c[h+g]=i[o+g];h+=e}else if(\"acTL\"==r)l.tabs[r]={num_frames:f(i,o),num_plays:f(i,o+4)},u=new Uint8Array(i.length);else if(\"fcTL\"==r){if(0!=d)(E=l.frames[l.frames.length-1]).data=_decompress(l,u.slice(0,d),E.rect.width,E.rect.height),d=0;const e={x:f(i,o+12),y:f(i,o+16),width:f(i,o+4),height:f(i,o+8)};let t=s(i,o+22);t=s(i,o+20)/(0==t?100:t);const r={rect:e,delay:Math.round(1e3*t),dispose:i[o+24],blend:i[o+25]};l.frames.push(r)}else if(\"fdAT\"==r){for(g=0;g<e-4;g++)u[d+g]=i[o+g+4];d+=e-4}else if(\"pHYs\"==r)l.tabs[r]=[a.readUint(i,o),a.readUint(i,o+4),i[o+8]];else if(\"cHRM\"==r){l.tabs[r]=[];for(g=0;g<8;g++)l.tabs[r].push(a.readUint(i,o+4*g))}else if(\"tEXt\"==r||\"zTXt\"==r){null==l.tabs[r]&&(l.tabs[r]={});var m=a.nextZero(i,o),w=a.readASCII(i,o,m-o),v=o+e-m-1;if(\"tEXt\"==r)y=a.readASCII(i,m+1,v);else{var b=_inflate(i.slice(m+2,m+2+v));y=a.readUTF8(b,0,b.length)}l.tabs[r][w]=y}else if(\"iTXt\"==r){null==l.tabs[r]&&(l.tabs[r]={});m=0,p=o;m=a.nextZero(i,p);w=a.readASCII(i,p,m-p);const t=i[p=m+1];var y;i[p+1],p+=2,m=a.nextZero(i,p),a.readASCII(i,p,m-p),p=m+1,m=a.nextZero(i,p),a.readUTF8(i,p,m-p);v=e-((p=m+1)-o);if(0==t)y=a.readUTF8(i,p,v);else{b=_inflate(i.slice(p,p+v));y=a.readUTF8(b,0,b.length)}l.tabs[r][w]=y}else if(\"PLTE\"==r)l.tabs[r]=a.readBytes(i,o,e);else if(\"hIST\"==r){const e=l.tabs.PLTE.length/3;l.tabs[r]=[];for(g=0;g<e;g++)l.tabs[r].push(s(i,o+2*g))}else if(\"tRNS\"==r)3==l.ctype?l.tabs[r]=a.readBytes(i,o,e):0==l.ctype?l.tabs[r]=s(i,o):2==l.ctype&&(l.tabs[r]=[s(i,o),s(i,o+2),s(i,o+4)]);else if(\"gAMA\"==r)l.tabs[r]=a.readUint(i,o)/1e5;else if(\"sRGB\"==r)l.tabs[r]=i[o];else if(\"bKGD\"==r)0==l.ctype||4==l.ctype?l.tabs[r]=[s(i,o)]:2==l.ctype||6==l.ctype?l.tabs[r]=[s(i,o),s(i,o+2),s(i,o+4)]:3==l.ctype&&(l.tabs[r]=i[o]);else if(\"IEND\"==r)break;o+=e,a.readUint(i,o),o+=4}var E;return 0!=d&&((E=l.frames[l.frames.length-1]).data=_decompress(l,u.slice(0,d),E.rect.width,E.rect.height)),l.data=_decompress(l,c,l.width,l.height),delete l.compress,delete l.interlace,delete l.filter,l},toRGBA8:function toRGBA8(e){const t=e.width,r=e.height;if(null==e.tabs.acTL)return[decodeImage(e.data,t,r,e).buffer];const i=[];null==e.frames[0].data&&(e.frames[0].data=e.data);const o=t*r*4,a=new Uint8Array(o),s=new Uint8Array(o),f=new Uint8Array(o);for(let c=0;c<e.frames.length;c++){const u=e.frames[c],h=u.rect.x,d=u.rect.y,A=u.rect.width,g=u.rect.height,p=decodeImage(u.data,A,g,e);if(0!=c)for(var l=0;l<o;l++)f[l]=a[l];if(0==u.blend?_copyTile(p,A,g,a,t,r,h,d,0):1==u.blend&&_copyTile(p,A,g,a,t,r,h,d,1),i.push(a.buffer.slice(0)),0==u.dispose);else if(1==u.dispose)_copyTile(s,A,g,a,t,r,h,d,0);else if(2==u.dispose)for(l=0;l<o;l++)a[l]=f[l]}return i},_paeth:_paeth,_copyTile:_copyTile,_bin:e}}();!function(){const{_copyTile:e}=UPNG,{_bin:t}=UPNG,r=UPNG._paeth;var i={table:function(){const e=new Uint32Array(256);for(let t=0;t<256;t++){let r=t;for(let e=0;e<8;e++)1&r?r=3988292384^r>>>1:r>>>=1;e[t]=r}return e}(),update(e,t,r,o){for(let a=0;a<o;a++)e=i.table[255&(e^t[r+a])]^e>>>8;return e},crc:(e,t,r)=>4294967295^i.update(4294967295,e,t,r)};function addErr(e,t,r,i){t[r]+=e[0]*i>>4,t[r+1]+=e[1]*i>>4,t[r+2]+=e[2]*i>>4,t[r+3]+=e[3]*i>>4}function N(e){return Math.max(0,Math.min(255,e))}function D(e,t){const r=e[0]-t[0],i=e[1]-t[1],o=e[2]-t[2],a=e[3]-t[3];return r*r+i*i+o*o+a*a}function dither(e,t,r,i,o,a,s){null==s&&(s=1);const f=i.length,l=[];for(var c=0;c<f;c++){const e=i[c];l.push([e>>>0&255,e>>>8&255,e>>>16&255,e>>>24&255])}for(c=0;c<f;c++){let e=4294967295;for(var u=0,h=0;h<f;h++){var d=D(l[c],l[h]);h!=c&&d<e&&(e=d,u=h)}}const A=new Uint32Array(o.buffer),g=new Int16Array(t*r*4),p=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5];for(c=0;c<p.length;c++)p[c]=255*((p[c]+.5)/16-.5);for(let o=0;o<r;o++)for(let w=0;w<t;w++){var m;c=4*(o*t+w);if(2!=s)m=[N(e[c]+g[c]),N(e[c+1]+g[c+1]),N(e[c+2]+g[c+2]),N(e[c+3]+g[c+3])];else{d=p[4*(3&o)+(3&w)];m=[N(e[c]+d),N(e[c+1]+d),N(e[c+2]+d),N(e[c+3]+d)]}u=0;let v=16777215;for(h=0;h<f;h++){const e=D(m,l[h]);e<v&&(v=e,u=h)}const b=l[u],y=[m[0]-b[0],m[1]-b[1],m[2]-b[2],m[3]-b[3]];1==s&&(w!=t-1&&addErr(y,g,c+4,7),o!=r-1&&(0!=w&&addErr(y,g,c+4*t-4,3),addErr(y,g,c+4*t,5),w!=t-1&&addErr(y,g,c+4*t+4,1))),a[c>>2]=u,A[c>>2]=i[u]}}function _main(e,r,o,a,s){null==s&&(s={});const{crc:f}=i,l=t.writeUint,c=t.writeUshort,u=t.writeASCII;let h=8;const d=e.frames.length>1;let A,g=!1,p=33+(d?20:0);if(null!=s.sRGB&&(p+=13),null!=s.pHYs&&(p+=21),null!=s.iCCP&&(A=pako.deflate(s.iCCP),p+=21+A.length+4),3==e.ctype){for(var m=e.plte.length,w=0;w<m;w++)e.plte[w]>>>24!=255&&(g=!0);p+=8+3*m+4+(g?8+1*m+4:0)}for(var v=0;v<e.frames.length;v++){d&&(p+=38),p+=(F=e.frames[v]).cimg.length+12,0!=v&&(p+=4)}p+=12;const b=new Uint8Array(p),y=[137,80,78,71,13,10,26,10];for(w=0;w<8;w++)b[w]=y[w];if(l(b,h,13),h+=4,u(b,h,\"IHDR\"),h+=4,l(b,h,r),h+=4,l(b,h,o),h+=4,b[h]=e.depth,h++,b[h]=e.ctype,h++,b[h]=0,h++,b[h]=0,h++,b[h]=0,h++,l(b,h,f(b,h-17,17)),h+=4,null!=s.sRGB&&(l(b,h,1),h+=4,u(b,h,\"sRGB\"),h+=4,b[h]=s.sRGB,h++,l(b,h,f(b,h-5,5)),h+=4),null!=s.iCCP){const e=13+A.length;l(b,h,e),h+=4,u(b,h,\"iCCP\"),h+=4,u(b,h,\"ICC profile\"),h+=11,h+=2,b.set(A,h),h+=A.length,l(b,h,f(b,h-(e+4),e+4)),h+=4}if(null!=s.pHYs&&(l(b,h,9),h+=4,u(b,h,\"pHYs\"),h+=4,l(b,h,s.pHYs[0]),h+=4,l(b,h,s.pHYs[1]),h+=4,b[h]=s.pHYs[2],h++,l(b,h,f(b,h-13,13)),h+=4),d&&(l(b,h,8),h+=4,u(b,h,\"acTL\"),h+=4,l(b,h,e.frames.length),h+=4,l(b,h,null!=s.loop?s.loop:0),h+=4,l(b,h,f(b,h-12,12)),h+=4),3==e.ctype){l(b,h,3*(m=e.plte.length)),h+=4,u(b,h,\"PLTE\"),h+=4;for(w=0;w<m;w++){const t=3*w,r=e.plte[w],i=255&r,o=r>>>8&255,a=r>>>16&255;b[h+t+0]=i,b[h+t+1]=o,b[h+t+2]=a}if(h+=3*m,l(b,h,f(b,h-3*m-4,3*m+4)),h+=4,g){l(b,h,m),h+=4,u(b,h,\"tRNS\"),h+=4;for(w=0;w<m;w++)b[h+w]=e.plte[w]>>>24&255;h+=m,l(b,h,f(b,h-m-4,m+4)),h+=4}}let E=0;for(v=0;v<e.frames.length;v++){var F=e.frames[v];d&&(l(b,h,26),h+=4,u(b,h,\"fcTL\"),h+=4,l(b,h,E++),h+=4,l(b,h,F.rect.width),h+=4,l(b,h,F.rect.height),h+=4,l(b,h,F.rect.x),h+=4,l(b,h,F.rect.y),h+=4,c(b,h,a[v]),h+=2,c(b,h,1e3),h+=2,b[h]=F.dispose,h++,b[h]=F.blend,h++,l(b,h,f(b,h-30,30)),h+=4);const t=F.cimg;l(b,h,(m=t.length)+(0==v?0:4)),h+=4;const r=h;u(b,h,0==v?\"IDAT\":\"fdAT\"),h+=4,0!=v&&(l(b,h,E++),h+=4),b.set(t,h),h+=m,l(b,h,f(b,r,h-r)),h+=4}return l(b,h,0),h+=4,u(b,h,\"IEND\"),h+=4,l(b,h,f(b,h-4,4)),h+=4,b.buffer}function compressPNG(e,t,r){for(let i=0;i<e.frames.length;i++){const o=e.frames[i];o.rect.width;const a=o.rect.height,s=new Uint8Array(a*o.bpl+a);o.cimg=_filterZero(o.img,a,o.bpp,o.bpl,s,t,r)}}function compress(t,r,i,o,a){const s=a[0],f=a[1],l=a[2],c=a[3],u=a[4],h=a[5];let d=6,A=8,g=255;for(var p=0;p<t.length;p++){const e=new Uint8Array(t[p]);for(var m=e.length,w=0;w<m;w+=4)g&=e[w+3]}const v=255!=g,b=function framize(t,r,i,o,a,s){const f=[];for(var l=0;l<t.length;l++){const h=new Uint8Array(t[l]),A=new Uint32Array(h.buffer);var c;let g=0,p=0,m=r,w=i,v=o?1:0;if(0!=l){const b=s||o||1==l||0!=f[l-2].dispose?1:2;let y=0,E=1e9;for(let e=0;e<b;e++){var u=new Uint8Array(t[l-1-e]);const o=new Uint32Array(t[l-1-e]);let s=r,f=i,c=-1,h=-1;for(let e=0;e<i;e++)for(let t=0;t<r;t++){A[d=e*r+t]!=o[d]&&(t<s&&(s=t),t>c&&(c=t),e<f&&(f=e),e>h&&(h=e))}-1==c&&(s=f=c=h=0),a&&(1==(1&s)&&s--,1==(1&f)&&f--);const v=(c-s+1)*(h-f+1);v<E&&(E=v,y=e,g=s,p=f,m=c-s+1,w=h-f+1)}u=new Uint8Array(t[l-1-y]);1==y&&(f[l-1].dispose=2),c=new Uint8Array(m*w*4),e(u,r,i,c,m,w,-g,-p,0),v=e(h,r,i,c,m,w,-g,-p,3)?1:0,1==v?_prepareDiff(h,r,i,c,{x:g,y:p,width:m,height:w}):e(h,r,i,c,m,w,-g,-p,0)}else c=h.slice(0);f.push({rect:{x:g,y:p,width:m,height:w},img:c,blend:v,dispose:0})}if(o)for(l=0;l<f.length;l++){if(1==(A=f[l]).blend)continue;const e=A.rect,o=f[l-1].rect,s=Math.min(e.x,o.x),c=Math.min(e.y,o.y),u={x:s,y:c,width:Math.max(e.x+e.width,o.x+o.width)-s,height:Math.max(e.y+e.height,o.y+o.height)-c};f[l-1].dispose=1,l-1!=0&&_updateFrame(t,r,i,f,l-1,u,a),_updateFrame(t,r,i,f,l,u,a)}let h=0;if(1!=t.length)for(var d=0;d<f.length;d++){var A;h+=(A=f[d]).rect.width*A.rect.height}return f}(t,r,i,s,f,l),y={},E=[],F=[];if(0!=o){const e=[];for(w=0;w<b.length;w++)e.push(b[w].img.buffer);const t=function concatRGBA(e){let t=0;for(var r=0;r<e.length;r++)t+=e[r].byteLength;const i=new Uint8Array(t);let o=0;for(r=0;r<e.length;r++){const t=new Uint8Array(e[r]),a=t.length;for(let e=0;e<a;e+=4){let r=t[e],a=t[e+1],s=t[e+2];const f=t[e+3];0==f&&(r=a=s=0),i[o+e]=r,i[o+e+1]=a,i[o+e+2]=s,i[o+e+3]=f}o+=a}return i.buffer}(e),r=quantize(t,o);for(w=0;w<r.plte.length;w++)E.push(r.plte[w].est.rgba);let i=0;for(w=0;w<b.length;w++){const e=(B=b[w]).img.length;var _=new Uint8Array(r.inds.buffer,i>>2,e>>2);F.push(_);const t=new Uint8Array(r.abuf,i,e);h&&dither(B.img,B.rect.width,B.rect.height,E,t,_),B.img.set(t),i+=e}}else for(p=0;p<b.length;p++){var B=b[p];const e=new Uint32Array(B.img.buffer);var U=B.rect.width;m=e.length,_=new Uint8Array(m);F.push(_);for(w=0;w<m;w++){const t=e[w];if(0!=w&&t==e[w-1])_[w]=_[w-1];else if(w>U&&t==e[w-U])_[w]=_[w-U];else{let e=y[t];if(null==e&&(y[t]=e=E.length,E.push(t),E.length>=300))break;_[w]=e}}}const C=E.length;C<=256&&0==u&&(A=C<=2?1:C<=4?2:C<=16?4:8,A=Math.max(A,c));for(p=0;p<b.length;p++){(B=b[p]).rect.x,B.rect.y;U=B.rect.width;const e=B.rect.height;let t=B.img;new Uint32Array(t.buffer);let r=4*U,i=4;if(C<=256&&0==u){r=Math.ceil(A*U/8);var I=new Uint8Array(r*e);const o=F[p];for(let t=0;t<e;t++){w=t*r;const e=t*U;if(8==A)for(var Q=0;Q<U;Q++)I[w+Q]=o[e+Q];else if(4==A)for(Q=0;Q<U;Q++)I[w+(Q>>1)]|=o[e+Q]<<4-4*(1&Q);else if(2==A)for(Q=0;Q<U;Q++)I[w+(Q>>2)]|=o[e+Q]<<6-2*(3&Q);else if(1==A)for(Q=0;Q<U;Q++)I[w+(Q>>3)]|=o[e+Q]<<7-1*(7&Q)}t=I,d=3,i=1}else if(0==v&&1==b.length){I=new Uint8Array(U*e*3);const o=U*e;for(w=0;w<o;w++){const e=3*w,r=4*w;I[e]=t[r],I[e+1]=t[r+1],I[e+2]=t[r+2]}t=I,d=2,i=3,r=3*U}B.img=t,B.bpl=r,B.bpp=i}return{ctype:d,depth:A,plte:E,frames:b}}function _updateFrame(t,r,i,o,a,s,f){const l=Uint8Array,c=Uint32Array,u=new l(t[a-1]),h=new c(t[a-1]),d=a+1<t.length?new l(t[a+1]):null,A=new l(t[a]),g=new c(A.buffer);let p=r,m=i,w=-1,v=-1;for(let e=0;e<s.height;e++)for(let t=0;t<s.width;t++){const i=s.x+t,f=s.y+e,l=f*r+i,c=g[l];0==c||0==o[a-1].dispose&&h[l]==c&&(null==d||0!=d[4*l+3])||(i<p&&(p=i),i>w&&(w=i),f<m&&(m=f),f>v&&(v=f))}-1==w&&(p=m=w=v=0),f&&(1==(1&p)&&p--,1==(1&m)&&m--),s={x:p,y:m,width:w-p+1,height:v-m+1};const b=o[a];b.rect=s,b.blend=1,b.img=new Uint8Array(s.width*s.height*4),0==o[a-1].dispose?(e(u,r,i,b.img,s.width,s.height,-s.x,-s.y,0),_prepareDiff(A,r,i,b.img,s)):e(A,r,i,b.img,s.width,s.height,-s.x,-s.y,0)}function _prepareDiff(t,r,i,o,a){e(t,r,i,o,a.width,a.height,-a.x,-a.y,2)}function _filterZero(e,t,r,i,o,a,s){const f=[];let l,c=[0,1,2,3,4];-1!=a?c=[a]:(t*i>5e5||1==r)&&(c=[0]),s&&(l={level:0});const u=UZIP;for(var h=0;h<c.length;h++){for(let a=0;a<t;a++)_filterLine(o,e,a,i,r,c[h]);f.push(u.deflate(o,l))}let d,A=1e9;for(h=0;h<f.length;h++)f[h].length<A&&(d=h,A=f[h].length);return f[d]}function _filterLine(e,t,i,o,a,s){const f=i*o;let l=f+i;if(e[l]=s,l++,0==s)if(o<500)for(var c=0;c<o;c++)e[l+c]=t[f+c];else e.set(new Uint8Array(t.buffer,f,o),l);else if(1==s){for(c=0;c<a;c++)e[l+c]=t[f+c];for(c=a;c<o;c++)e[l+c]=t[f+c]-t[f+c-a]+256&255}else if(0==i){for(c=0;c<a;c++)e[l+c]=t[f+c];if(2==s)for(c=a;c<o;c++)e[l+c]=t[f+c];if(3==s)for(c=a;c<o;c++)e[l+c]=t[f+c]-(t[f+c-a]>>1)+256&255;if(4==s)for(c=a;c<o;c++)e[l+c]=t[f+c]-r(t[f+c-a],0,0)+256&255}else{if(2==s)for(c=0;c<o;c++)e[l+c]=t[f+c]+256-t[f+c-o]&255;if(3==s){for(c=0;c<a;c++)e[l+c]=t[f+c]+256-(t[f+c-o]>>1)&255;for(c=a;c<o;c++)e[l+c]=t[f+c]+256-(t[f+c-o]+t[f+c-a]>>1)&255}if(4==s){for(c=0;c<a;c++)e[l+c]=t[f+c]+256-r(0,t[f+c-o],0)&255;for(c=a;c<o;c++)e[l+c]=t[f+c]+256-r(t[f+c-a],t[f+c-o],t[f+c-a-o])&255}}}function quantize(e,t){const r=new Uint8Array(e),i=r.slice(0),o=new Uint32Array(i.buffer),a=getKDtree(i,t),s=a[0],f=a[1],l=r.length,c=new Uint8Array(l>>2);let u;if(r.length<2e7)for(var h=0;h<l;h+=4){u=getNearest(s,d=r[h]*(1/255),A=r[h+1]*(1/255),g=r[h+2]*(1/255),p=r[h+3]*(1/255)),c[h>>2]=u.ind,o[h>>2]=u.est.rgba}else for(h=0;h<l;h+=4){var d=r[h]*(1/255),A=r[h+1]*(1/255),g=r[h+2]*(1/255),p=r[h+3]*(1/255);for(u=s;u.left;)u=planeDst(u.est,d,A,g,p)<=0?u.left:u.right;c[h>>2]=u.ind,o[h>>2]=u.est.rgba}return{abuf:i.buffer,inds:c,plte:f}}function getKDtree(e,t,r){null==r&&(r=1e-4);const i=new Uint32Array(e.buffer),o={i0:0,i1:e.length,bst:null,est:null,tdst:0,left:null,right:null};o.bst=stats(e,o.i0,o.i1),o.est=estats(o.bst);const a=[o];for(;a.length<t;){let t=0,o=0;for(var s=0;s<a.length;s++)a[s].est.L>t&&(t=a[s].est.L,o=s);if(t<r)break;const f=a[o],l=splitPixels(e,i,f.i0,f.i1,f.est.e,f.est.eMq255);if(f.i0>=l||f.i1<=l){f.est.L=0;continue}const c={i0:f.i0,i1:l,bst:null,est:null,tdst:0,left:null,right:null};c.bst=stats(e,c.i0,c.i1),c.est=estats(c.bst);const u={i0:l,i1:f.i1,bst:null,est:null,tdst:0,left:null,right:null};u.bst={R:[],m:[],N:f.bst.N-c.bst.N};for(s=0;s<16;s++)u.bst.R[s]=f.bst.R[s]-c.bst.R[s];for(s=0;s<4;s++)u.bst.m[s]=f.bst.m[s]-c.bst.m[s];u.est=estats(u.bst),f.left=c,f.right=u,a[o]=c,a.push(u)}a.sort(((e,t)=>t.bst.N-e.bst.N));for(s=0;s<a.length;s++)a[s].ind=s;return[o,a]}function getNearest(e,t,r,i,o){if(null==e.left)return e.tdst=function dist(e,t,r,i,o){const a=t-e[0],s=r-e[1],f=i-e[2],l=o-e[3];return a*a+s*s+f*f+l*l}(e.est.q,t,r,i,o),e;const a=planeDst(e.est,t,r,i,o);let s=e.left,f=e.right;a>0&&(s=e.right,f=e.left);const l=getNearest(s,t,r,i,o);if(l.tdst<=a*a)return l;const c=getNearest(f,t,r,i,o);return c.tdst<l.tdst?c:l}function planeDst(e,t,r,i,o){const{e:a}=e;return a[0]*t+a[1]*r+a[2]*i+a[3]*o-e.eMq}function splitPixels(e,t,r,i,o,a){for(i-=4;r<i;){for(;vecDot(e,r,o)<=a;)r+=4;for(;vecDot(e,i,o)>a;)i-=4;if(r>=i)break;const s=t[r>>2];t[r>>2]=t[i>>2],t[i>>2]=s,r+=4,i-=4}for(;vecDot(e,r,o)>a;)r-=4;return r+4}function vecDot(e,t,r){return e[t]*r[0]+e[t+1]*r[1]+e[t+2]*r[2]+e[t+3]*r[3]}function stats(e,t,r){const i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],o=[0,0,0,0],a=r-t>>2;for(let a=t;a<r;a+=4){const t=e[a]*(1/255),r=e[a+1]*(1/255),s=e[a+2]*(1/255),f=e[a+3]*(1/255);o[0]+=t,o[1]+=r,o[2]+=s,o[3]+=f,i[0]+=t*t,i[1]+=t*r,i[2]+=t*s,i[3]+=t*f,i[5]+=r*r,i[6]+=r*s,i[7]+=r*f,i[10]+=s*s,i[11]+=s*f,i[15]+=f*f}return i[4]=i[1],i[8]=i[2],i[9]=i[6],i[12]=i[3],i[13]=i[7],i[14]=i[11],{R:i,m:o,N:a}}function estats(e){const{R:t}=e,{m:r}=e,{N:i}=e,a=r[0],s=r[1],f=r[2],l=r[3],c=0==i?0:1/i,u=[t[0]-a*a*c,t[1]-a*s*c,t[2]-a*f*c,t[3]-a*l*c,t[4]-s*a*c,t[5]-s*s*c,t[6]-s*f*c,t[7]-s*l*c,t[8]-f*a*c,t[9]-f*s*c,t[10]-f*f*c,t[11]-f*l*c,t[12]-l*a*c,t[13]-l*s*c,t[14]-l*f*c,t[15]-l*l*c],h=u,d=o;let A=[Math.random(),Math.random(),Math.random(),Math.random()],g=0,p=0;if(0!=i)for(let e=0;e<16&&(A=d.multVec(h,A),p=Math.sqrt(d.dot(A,A)),A=d.sml(1/p,A),!(0!=e&&Math.abs(p-g)<1e-9));e++)g=p;const m=[a*c,s*c,f*c,l*c];return{Cov:u,q:m,e:A,L:g,eMq255:d.dot(d.sml(255,m),A),eMq:d.dot(A,m),rgba:(Math.round(255*m[3])<<24|Math.round(255*m[2])<<16|Math.round(255*m[1])<<8|Math.round(255*m[0])<<0)>>>0}}var o={multVec:(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],e[4]*t[0]+e[5]*t[1]+e[6]*t[2]+e[7]*t[3],e[8]*t[0]+e[9]*t[1]+e[10]*t[2]+e[11]*t[3],e[12]*t[0]+e[13]*t[1]+e[14]*t[2]+e[15]*t[3]],dot:(e,t)=>e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3],sml:(e,t)=>[e*t[0],e*t[1],e*t[2],e*t[3]]};UPNG.encode=function encode(e,t,r,i,o,a,s){null==i&&(i=0),null==s&&(s=!1);const f=compress(e,t,r,i,[!1,!1,!1,0,s,!1]);return compressPNG(f,-1),_main(f,t,r,o,a)},UPNG.encodeLL=function encodeLL(e,t,r,i,o,a,s,f){const l={ctype:0+(1==i?0:2)+(0==o?0:4),depth:a,frames:[]},c=(i+o)*a,u=c*t;for(let i=0;i<e.length;i++)l.frames.push({rect:{x:0,y:0,width:t,height:r},img:new Uint8Array(e[i]),blend:0,dispose:1,bpp:Math.ceil(c/8),bpl:Math.ceil(u/8)});return compressPNG(l,0,!0),_main(l,t,r,s,f)},UPNG.encode.compress=compress,UPNG.encode.dither=dither,UPNG.quantize=quantize,UPNG.quantize.getKDtree=getKDtree,UPNG.quantize.getNearest=getNearest}();const r={toArrayBuffer(e,t){const i=e.width,o=e.height,a=i<<2,s=e.getContext(\"2d\").getImageData(0,0,i,o),f=new Uint32Array(s.data.buffer),l=(32*i+31)/32<<2,c=l*o,u=122+c,h=new ArrayBuffer(u),d=new DataView(h),A=1<<20;let g,p,m,w,v=A,b=0,y=0,E=0;function set16(e){d.setUint16(y,e,!0),y+=2}function set32(e){d.setUint32(y,e,!0),y+=4}function seek(e){y+=e}set16(19778),set32(u),seek(4),set32(122),set32(108),set32(i),set32(-o>>>0),set16(1),set16(32),set32(3),set32(c),set32(2835),set32(2835),seek(8),set32(16711680),set32(65280),set32(255),set32(4278190080),set32(1466527264),function convert(){for(;b<o&&v>0;){for(w=122+b*l,g=0;g<a;)v--,p=f[E++],m=p>>>24,d.setUint32(w+g,p<<8|m),g+=4;b++}E<f.length?(v=A,setTimeout(convert,r._dly)):t(h)}()},toBlob(e,t){this.toArrayBuffer(e,(e=>{t(new Blob([e],{type:\"image/bmp\"}))}))},_dly:9};var i={CHROME:\"CHROME\",FIREFOX:\"FIREFOX\",DESKTOP_SAFARI:\"DESKTOP_SAFARI\",IE:\"IE\",IOS:\"IOS\",ETC:\"ETC\"},o={[i.CHROME]:16384,[i.FIREFOX]:11180,[i.DESKTOP_SAFARI]:16384,[i.IE]:8192,[i.IOS]:4096,[i.ETC]:8192};const a=\"undefined\"!=typeof window,s=\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,f=a&&window.cordova&&window.cordova.require&&window.cordova.require(\"cordova/modulemapper\"),CustomFile=(a||s)&&(f&&f.getOriginalSymbol(window,\"File\")||\"undefined\"!=typeof File&&File),CustomFileReader=(a||s)&&(f&&f.getOriginalSymbol(window,\"FileReader\")||\"undefined\"!=typeof FileReader&&FileReader);function getFilefromDataUrl(e,t,r=Date.now()){return new Promise((i=>{const o=e.split(\",\"),a=o[0].match(/:(.*?);/)[1],s=globalThis.atob(o[1]);let f=s.length;const l=new Uint8Array(f);for(;f--;)l[f]=s.charCodeAt(f);const c=new Blob([l],{type:a});c.name=t,c.lastModified=r,i(c)}))}function getDataUrlFromFile(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=()=>t(i.result),i.onerror=e=>r(e),i.readAsDataURL(e)}))}function loadImage(e){return new Promise(((t,r)=>{const i=new Image;i.onload=()=>t(i),i.onerror=e=>r(e),i.src=e}))}function getBrowserName(){if(void 0!==getBrowserName.cachedResult)return getBrowserName.cachedResult;let e=i.ETC;const{userAgent:t}=navigator;return/Chrom(e|ium)/i.test(t)?e=i.CHROME:/iP(ad|od|hone)/i.test(t)&&/WebKit/i.test(t)?e=i.IOS:/Safari/i.test(t)?e=i.DESKTOP_SAFARI:/Firefox/i.test(t)?e=i.FIREFOX:(/MSIE/i.test(t)||!0==!!document.documentMode)&&(e=i.IE),getBrowserName.cachedResult=e,getBrowserName.cachedResult}function approximateBelowMaximumCanvasSizeOfBrowser(e,t){const r=getBrowserName(),i=o[r];let a=e,s=t,f=a*s;const l=a>s?s/a:a/s;for(;f>i*i;){const e=(i+a)/2,t=(i+s)/2;e<t?(s=t,a=t*l):(s=e*l,a=e),f=a*s}return{width:a,height:s}}function getNewCanvasAndCtx(e,t){let r,i;try{if(r=new OffscreenCanvas(e,t),i=r.getContext(\"2d\"),null===i)throw new Error(\"getContext of OffscreenCanvas returns null\")}catch(e){r=document.createElement(\"canvas\"),i=r.getContext(\"2d\")}return r.width=e,r.height=t,[r,i]}function drawImageInCanvas(e,t){const{width:r,height:i}=approximateBelowMaximumCanvasSizeOfBrowser(e.width,e.height),[o,a]=getNewCanvasAndCtx(r,i);return t&&/jpe?g/.test(t)&&(a.fillStyle=\"white\",a.fillRect(0,0,o.width,o.height)),a.drawImage(e,0,0,o.width,o.height),o}function isIOS(){return void 0!==isIOS.cachedResult||(isIOS.cachedResult=[\"iPad Simulator\",\"iPhone Simulator\",\"iPod Simulator\",\"iPad\",\"iPhone\",\"iPod\"].includes(navigator.platform)||navigator.userAgent.includes(\"Mac\")&&\"undefined\"!=typeof document&&\"ontouchend\"in document),isIOS.cachedResult}function drawFileInCanvas(e,t={}){return new Promise((function(r,o){let a,s;var $Try_2_Post=function(){try{return s=drawImageInCanvas(a,t.fileType||e.type),r([a,s])}catch(e){return o(e)}},$Try_2_Catch=function(t){try{0;var $Try_3_Catch=function(e){try{throw e}catch(e){return o(e)}};try{let t;return getDataUrlFromFile(e).then((function(e){try{return t=e,loadImage(t).then((function(e){try{return a=e,function(){try{return $Try_2_Post()}catch(e){return o(e)}}()}catch(e){return $Try_3_Catch(e)}}),$Try_3_Catch)}catch(e){return $Try_3_Catch(e)}}),$Try_3_Catch)}catch(e){$Try_3_Catch(e)}}catch(e){return o(e)}};try{if(isIOS()||[i.DESKTOP_SAFARI,i.MOBILE_SAFARI].includes(getBrowserName()))throw new Error(\"Skip createImageBitmap on IOS and Safari\");return createImageBitmap(e).then((function(e){try{return a=e,$Try_2_Post()}catch(e){return $Try_2_Catch()}}),$Try_2_Catch)}catch(e){$Try_2_Catch()}}))}function canvasToFile(e,t,i,o,a=1){return new Promise((function(s,f){let l;if(\"image/png\"===t){let c,u,h;return c=e.getContext(\"2d\"),({data:u}=c.getImageData(0,0,e.width,e.height)),h=UPNG.encode([u.buffer],e.width,e.height,4096*a),l=new Blob([h],{type:t}),l.name=i,l.lastModified=o,$If_4.call(this)}{if(\"image/bmp\"===t)return new Promise((t=>r.toBlob(e,t))).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_5.call(this)}catch(e){return f(e)}}.bind(this),f);{if(\"function\"==typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return e.convertToBlob({type:t,quality:a}).then(function(e){try{return l=e,l.name=i,l.lastModified=o,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f);{let d;return d=e.toDataURL(t,a),getFilefromDataUrl(d,i,o).then(function(e){try{return l=e,$If_6.call(this)}catch(e){return f(e)}}.bind(this),f)}function $If_6(){return $If_5.call(this)}}function $If_5(){return $If_4.call(this)}}function $If_4(){return s(l)}}))}function cleanupCanvasMemory(e){e.width=0,e.height=0}function isAutoOrientationInBrowser(){return new Promise((function(e,t){let r,i,o,a,s;return void 0!==isAutoOrientationInBrowser.cachedResult?e(isAutoOrientationInBrowser.cachedResult):(r=\"data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==\",getFilefromDataUrl(\"data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==\",\"test.jpg\",Date.now()).then((function(r){try{return i=r,drawFileInCanvas(i).then((function(r){try{return o=r[1],canvasToFile(o,i.type,i.name,i.lastModified).then((function(r){try{return a=r,cleanupCanvasMemory(o),drawFileInCanvas(a).then((function(r){try{return s=r[0],isAutoOrientationInBrowser.cachedResult=1===s.width&&2===s.height,e(isAutoOrientationInBrowser.cachedResult)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t)}catch(e){return t(e)}}),t))}))}function getExifOrientation(e){return new Promise(((t,r)=>{const i=new CustomFileReader;i.onload=e=>{const r=new DataView(e.target.result);if(65496!=r.getUint16(0,!1))return t(-2);const i=r.byteLength;let o=2;for(;o<i;){if(r.getUint16(o+2,!1)<=8)return t(-1);const e=r.getUint16(o,!1);if(o+=2,65505==e){if(1165519206!=r.getUint32(o+=2,!1))return t(-1);const e=18761==r.getUint16(o+=6,!1);o+=r.getUint32(o+4,e);const i=r.getUint16(o,e);o+=2;for(let a=0;a<i;a++)if(274==r.getUint16(o+12*a,e))return t(r.getUint16(o+12*a+8,e))}else{if(65280!=(65280&e))break;o+=r.getUint16(o,!1)}}return t(-1)},i.onerror=e=>r(e),i.readAsArrayBuffer(e)}))}function handleMaxWidthOrHeight(e,t){const{width:r}=e,{height:i}=e,{maxWidthOrHeight:o}=t;let a,s=e;return isFinite(o)&&(r>o||i>o)&&([s,a]=getNewCanvasAndCtx(r,i),r>i?(s.width=o,s.height=i/r*o):(s.width=r/i*o,s.height=o),a.drawImage(e,0,0,s.width,s.height),cleanupCanvasMemory(e)),s}function followExifOrientation(e,t){const{width:r}=e,{height:i}=e,[o,a]=getNewCanvasAndCtx(r,i);switch(t>4&&t<9?(o.width=i,o.height=r):(o.width=r,o.height=i),t){case 2:a.transform(-1,0,0,1,r,0);break;case 3:a.transform(-1,0,0,-1,r,i);break;case 4:a.transform(1,0,0,-1,0,i);break;case 5:a.transform(0,1,1,0,0,0);break;case 6:a.transform(0,1,-1,0,i,0);break;case 7:a.transform(0,-1,-1,0,i,r);break;case 8:a.transform(0,-1,1,0,0,r)}return a.drawImage(e,0,0,r,i),cleanupCanvasMemory(e),o}function compress(e,t,r=0){return new Promise((function(i,o){let a,s,f,l,c,u,h,d,A,g,p,m,w,v,b,y,E,F,_,B;function incProgress(e=5){if(t.signal&&t.signal.aborted)throw t.signal.reason;a+=e,t.onProgress(Math.min(a,100))}function setProgress(e){if(t.signal&&t.signal.aborted)throw t.signal.reason;a=Math.min(Math.max(e,a),100),t.onProgress(a)}return a=r,s=t.maxIteration||10,f=1024*t.maxSizeMB*1024,incProgress(),drawFileInCanvas(e,t).then(function(r){try{return[,l]=r,incProgress(),c=handleMaxWidthOrHeight(l,t),incProgress(),new Promise((function(r,i){var o;if(!(o=t.exifOrientation))return getExifOrientation(e).then(function(e){try{return o=e,$If_2.call(this)}catch(e){return i(e)}}.bind(this),i);function $If_2(){return r(o)}return $If_2.call(this)})).then(function(r){try{return u=r,incProgress(),isAutoOrientationInBrowser().then(function(r){try{return h=r?c:followExifOrientation(c,u),incProgress(),d=t.initialQuality||1,A=t.fileType||e.type,canvasToFile(h,A,e.name,e.lastModified,d).then(function(r){try{{if(g=r,incProgress(),p=g.size>f,m=g.size>e.size,!p&&!m)return setProgress(100),i(g);var a;function $Loop_3(){if(s--&&(b>f||b>w)){let t,r;return t=B?.95*_.width:_.width,r=B?.95*_.height:_.height,[E,F]=getNewCanvasAndCtx(t,r),F.drawImage(_,0,0,t,r),d*=\"image/png\"===A?.85:.95,canvasToFile(E,A,e.name,e.lastModified,d).then((function(e){try{return y=e,cleanupCanvasMemory(_),_=E,b=y.size,setProgress(Math.min(99,Math.floor((v-b)/(v-f)*100))),$Loop_3}catch(e){return o(e)}}),o)}return[1]}return w=e.size,v=g.size,b=v,_=h,B=!t.alwaysKeepResolution&&p,(a=function(e){for(;e;){if(e.then)return void e.then(a,o);try{if(e.pop){if(e.length)return e.pop()?$Loop_3_exit.call(this):e;e=$Loop_3}else e=e.call(this)}catch(e){return o(e)}}}.bind(this))($Loop_3);function $Loop_3_exit(){return cleanupCanvasMemory(_),cleanupCanvasMemory(E),cleanupCanvasMemory(c),cleanupCanvasMemory(h),cleanupCanvasMemory(l),setProgress(100),i(y)}}}catch(u){return o(u)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}catch(e){return o(e)}}.bind(this),o)}))}const l=\"\\nlet scriptImported = false\\nself.addEventListener('message', async (e) => {\\n const { file, id, imageCompressionLibUrl, options } = e.data\\n options.onProgress = (progress) => self.postMessage({ progress, id })\\n try {\\n if (!scriptImported) {\\n // console.log('[worker] importScripts', imageCompressionLibUrl)\\n self.importScripts(imageCompressionLibUrl)\\n scriptImported = true\\n }\\n // console.log('[worker] self', self)\\n const compressedFile = await imageCompression(file, options)\\n self.postMessage({ file: compressedFile, id })\\n } catch (e) {\\n // console.error('[worker] error', e)\\n self.postMessage({ error: e.message + '\\\\n' + e.stack, id })\\n }\\n})\\n\";let c;function compressOnWebWorker(e,t){return new Promise(((r,i)=>{c||(c=function createWorkerScriptURL(e){const t=[];return\"function\"==typeof e?t.push(`(${e})()`):t.push(e),URL.createObjectURL(new Blob(t))}(l));const o=new Worker(c);o.addEventListener(\"message\",(function handler(e){if(t.signal&&t.signal.aborted)o.terminate();else if(void 0===e.data.progress){if(e.data.error)return i(new Error(e.data.error)),void o.terminate();r(e.data.file),o.terminate()}else t.onProgress(e.data.progress)})),o.addEventListener(\"error\",i),t.signal&&t.signal.addEventListener(\"abort\",(()=>{i(t.signal.reason),o.terminate()})),o.postMessage({file:e,imageCompressionLibUrl:t.libURL,options:{...t,onProgress:void 0,signal:void 0}})}))}function imageCompression(e,t){return new Promise((function(r,i){let o,a,s,f,l,c;if(o={...t},s=0,({onProgress:f}=o),o.maxSizeMB=o.maxSizeMB||Number.POSITIVE_INFINITY,l=\"boolean\"!=typeof o.useWebWorker||o.useWebWorker,delete o.useWebWorker,o.onProgress=e=>{s=e,\"function\"==typeof f&&f(s)},!(e instanceof Blob||e instanceof CustomFile))return i(new Error(\"The file given is not an instance of Blob or File\"));if(!/^image/.test(e.type))return i(new Error(\"The file given is not an image\"));if(c=\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,!l||\"function\"!=typeof Worker||c)return compress(e,o).then(function(e){try{return a=e,$If_4.call(this)}catch(e){return i(e)}}.bind(this),i);var u=function(){try{return $If_4.call(this)}catch(e){return i(e)}}.bind(this),$Try_1_Catch=function(t){try{return compress(e,o).then((function(e){try{return a=e,u()}catch(e){return i(e)}}),i)}catch(e){return i(e)}};try{return o.libURL=o.libURL||\"https://cdn.jsdelivr.net/npm/[email protected]/dist/browser-image-compression.js\",compressOnWebWorker(e,o).then((function(e){try{return a=e,u()}catch(e){return $Try_1_Catch()}}),$Try_1_Catch)}catch(e){$Try_1_Catch()}function $If_4(){try{a.name=e.name,a.lastModified=e.lastModified}catch(e){}try{o.preserveExif&&\"image/jpeg\"===e.type&&(!o.fileType||o.fileType&&o.fileType===e.type)&&(a=copyExifWithoutOrientation(e,a))}catch(e){}return r(a)}}))}imageCompression.getDataUrlFromFile=getDataUrlFromFile,imageCompression.getFilefromDataUrl=getFilefromDataUrl,imageCompression.loadImage=loadImage,imageCompression.drawImageInCanvas=drawImageInCanvas,imageCompression.drawFileInCanvas=drawFileInCanvas,imageCompression.canvasToFile=canvasToFile,imageCompression.getExifOrientation=getExifOrientation,imageCompression.handleMaxWidthOrHeight=handleMaxWidthOrHeight,imageCompression.followExifOrientation=followExifOrientation,imageCompression.cleanupCanvasMemory=cleanupCanvasMemory,imageCompression.isAutoOrientationInBrowser=isAutoOrientationInBrowser,imageCompression.approximateBelowMaximumCanvasSizeOfBrowser=approximateBelowMaximumCanvasSizeOfBrowser,imageCompression.copyExifWithoutOrientation=copyExifWithoutOrientation,imageCompression.getBrowserName=getBrowserName,imageCompression.version=\"2.0.2\";\n//# sourceMappingURL=browser-image-compression.mjs.map\n\n\n//# sourceURL=webpack:///./node_modules/browser-image-compression/dist/browser-image-compression.mjs?"); 90 91 /***/ }), 92 93 /***/ "./node_modules/wasm-feature-detect/dist/esm/index.js": 94 /*!************************************************************!*\ 95 !*** ./node_modules/wasm-feature-detect/dist/esm/index.js ***! 96 \************************************************************/ 97 /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { 98 99 eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"bigInt\": () => (/* binding */ bigInt),\n/* harmony export */ \"bulkMemory\": () => (/* binding */ bulkMemory),\n/* harmony export */ \"exceptions\": () => (/* binding */ exceptions),\n/* harmony export */ \"extendedConst\": () => (/* binding */ extendedConst),\n/* harmony export */ \"gc\": () => (/* binding */ gc),\n/* harmony export */ \"memory64\": () => (/* binding */ memory64),\n/* harmony export */ \"multiValue\": () => (/* binding */ multiValue),\n/* harmony export */ \"mutableGlobals\": () => (/* binding */ mutableGlobals),\n/* harmony export */ \"referenceTypes\": () => (/* binding */ referenceTypes),\n/* harmony export */ \"relaxedSimd\": () => (/* binding */ relaxedSimd),\n/* harmony export */ \"saturatedFloatToInt\": () => (/* binding */ saturatedFloatToInt),\n/* harmony export */ \"signExtensions\": () => (/* binding */ signExtensions),\n/* harmony export */ \"simd\": () => (/* binding */ simd),\n/* harmony export */ \"streamingCompilation\": () => (/* binding */ streamingCompilation),\n/* harmony export */ \"tailCall\": () => (/* binding */ tailCall),\n/* harmony export */ \"threads\": () => (/* binding */ threads)\n/* harmony export */ });\nconst bigInt=()=>(async e=>{try{return(await WebAssembly.instantiate(e)).instance.exports.b(BigInt(0))===BigInt(0)}catch(e){return!1}})(new Uint8Array([0,97,115,109,1,0,0,0,1,6,1,96,1,126,1,126,3,2,1,0,7,5,1,1,98,0,0,10,6,1,4,0,32,0,11])),bulkMemory=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,3,1,0,1,10,14,1,12,0,65,0,65,0,65,0,252,10,0,0,11])),exceptions=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,6,64,25,11,11])),extendedConst=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,5,3,1,0,1,11,9,1,0,65,1,65,2,106,11,0])),gc=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,10,2,95,1,125,0,96,0,1,107,0,3,2,1,1,10,12,1,10,0,67,0,0,0,0,251,7,0,11])),memory64=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,5,3,1,4,1])),multiValue=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,6,1,96,0,2,127,127,3,2,1,0,10,8,1,6,0,65,0,65,0,11])),mutableGlobals=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,2,8,1,1,97,1,98,3,127,1,6,6,1,127,1,65,0,11,7,5,1,1,97,3,1])),referenceTypes=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,7,1,5,0,208,112,26,11])),relaxedSimd=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,15,1,13,0,65,1,253,15,65,2,253,15,253,128,2,11])),saturatedFloatToInt=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,12,1,10,0,67,0,0,0,0,252,0,26,11])),signExtensions=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,8,1,6,0,65,0,192,26,11])),simd=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11])),streamingCompilation=()=>(async()=>\"compileStreaming\"in WebAssembly)(),tailCall=async()=>WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,6,1,4,0,18,0,11])),threads=()=>(async e=>{try{return\"undefined\"!=typeof MessageChannel&&(new MessageChannel).port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(e)}catch(e){return!1}})(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]));\n\n\n//# sourceURL=webpack:///./node_modules/wasm-feature-detect/dist/esm/index.js?"); 50 100 51 101 /***/ }) … … 93 143 /******/ })(); 94 144 /******/ 145 /******/ /* webpack/runtime/ensure chunk */ 146 /******/ (() => { 147 /******/ __webpack_require__.f = {}; 148 /******/ // This file contains only the entry chunk. 149 /******/ // The chunk loading function for additional chunks 150 /******/ __webpack_require__.e = (chunkId) => { 151 /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { 152 /******/ __webpack_require__.f[key](chunkId, promises); 153 /******/ return promises; 154 /******/ }, [])); 155 /******/ }; 156 /******/ })(); 157 /******/ 95 158 /******/ /* webpack/runtime/get javascript chunk filename */ 96 159 /******/ (() => { … … 117 180 /******/ (() => { 118 181 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 182 /******/ })(); 183 /******/ 184 /******/ /* webpack/runtime/load script */ 185 /******/ (() => { 186 /******/ var inProgress = {}; 187 /******/ // data-webpack is not used as build has no uniqueName 188 /******/ // loadScript function to load a script via script tag 189 /******/ __webpack_require__.l = (url, done, key, chunkId) => { 190 /******/ if(inProgress[url]) { inProgress[url].push(done); return; } 191 /******/ var script, needAttach; 192 /******/ if(key !== undefined) { 193 /******/ var scripts = document.getElementsByTagName("script"); 194 /******/ for(var i = 0; i < scripts.length; i++) { 195 /******/ var s = scripts[i]; 196 /******/ if(s.getAttribute("src") == url) { script = s; break; } 197 /******/ } 198 /******/ } 199 /******/ if(!script) { 200 /******/ needAttach = true; 201 /******/ script = document.createElement('script'); 202 /******/ 203 /******/ script.charset = 'utf-8'; 204 /******/ script.timeout = 120; 205 /******/ if (__webpack_require__.nc) { 206 /******/ script.setAttribute("nonce", __webpack_require__.nc); 207 /******/ } 208 /******/ 209 /******/ script.src = url; 210 /******/ } 211 /******/ inProgress[url] = [done]; 212 /******/ var onScriptComplete = (prev, event) => { 213 /******/ // avoid mem leaks in IE. 214 /******/ script.onerror = script.onload = null; 215 /******/ clearTimeout(timeout); 216 /******/ var doneFns = inProgress[url]; 217 /******/ delete inProgress[url]; 218 /******/ script.parentNode && script.parentNode.removeChild(script); 219 /******/ doneFns && doneFns.forEach((fn) => (fn(event))); 220 /******/ if(prev) return prev(event); 221 /******/ } 222 /******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); 223 /******/ script.onerror = onScriptComplete.bind(null, script.onerror); 224 /******/ script.onload = onScriptComplete.bind(null, script.onload); 225 /******/ needAttach && document.head.appendChild(script); 226 /******/ }; 119 227 /******/ })(); 120 228 /******/ … … 161 269 /******/ }; 162 270 /******/ 163 /******/ // no chunk on demand loading 271 /******/ __webpack_require__.f.j = (chunkId, promises) => { 272 /******/ // JSONP chunk loading for javascript 273 /******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined; 274 /******/ if(installedChunkData !== 0) { // 0 means "already installed". 275 /******/ 276 /******/ // a Promise means "currently loading". 277 /******/ if(installedChunkData) { 278 /******/ promises.push(installedChunkData[2]); 279 /******/ } else { 280 /******/ if(true) { // all chunks have JS 281 /******/ // setup Promise in chunk cache 282 /******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject])); 283 /******/ promises.push(installedChunkData[2] = promise); 284 /******/ 285 /******/ // start chunk loading 286 /******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId); 287 /******/ // create error before stack unwound to get useful stacktrace later 288 /******/ var error = new Error(); 289 /******/ var loadingEnded = (event) => { 290 /******/ if(__webpack_require__.o(installedChunks, chunkId)) { 291 /******/ installedChunkData = installedChunks[chunkId]; 292 /******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined; 293 /******/ if(installedChunkData) { 294 /******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); 295 /******/ var realSrc = event && event.target && event.target.src; 296 /******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'; 297 /******/ error.name = 'ChunkLoadError'; 298 /******/ error.type = errorType; 299 /******/ error.request = realSrc; 300 /******/ installedChunkData[1](error); 301 /******/ } 302 /******/ } 303 /******/ }; 304 /******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId); 305 /******/ } else installedChunks[chunkId] = 0; 306 /******/ } 307 /******/ } 308 /******/ }; 164 309 /******/ 165 310 /******/ // no prefetching … … 173 318 /******/ // no on chunks loaded 174 319 /******/ 175 /******/ // no jsonp function 320 /******/ // install a JSONP callback for chunk loading 321 /******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { 322 /******/ var [chunkIds, moreModules, runtime] = data; 323 /******/ // add "moreModules" to the modules object, 324 /******/ // then flag all "chunkIds" as loaded and fire callback 325 /******/ var moduleId, chunkId, i = 0; 326 /******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { 327 /******/ for(moduleId in moreModules) { 328 /******/ if(__webpack_require__.o(moreModules, moduleId)) { 329 /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; 330 /******/ } 331 /******/ } 332 /******/ if(runtime) var result = runtime(__webpack_require__); 333 /******/ } 334 /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); 335 /******/ for(;i < chunkIds.length; i++) { 336 /******/ chunkId = chunkIds[i]; 337 /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { 338 /******/ installedChunks[chunkId][0](); 339 /******/ } 340 /******/ installedChunks[chunkId] = 0; 341 /******/ } 342 /******/ 343 /******/ } 344 /******/ 345 /******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || []; 346 /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); 347 /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); 176 348 /******/ })(); 177 349 /******/ -
squeeze/trunk/assets/templates/path-list-item.html
r3238524 r3345284 1 <input type="text" class="squeeze-path-list__item" value="{{folder}}" readonly /> 1 <div class="squeeze-path-list__item"> 2 <input name="squeeze-path-list__item[]" type="text" class="squeeze-path-list__input" 3 value="{{folder}}" readonly /> 4 <button name="squeeze_remove_path_button" class="squeeze-path-list__remove" type="button"> 5 <svg class="squeeze-icon"> 6 <use xlink:href="#close-round-icon"></use> 7 </svg> 8 </button> 9 </div> -
squeeze/trunk/inc/handlers.php
r3311866 r3345284 53 53 } 54 54 $base64 = sanitize_text_field( wp_unslash( $_POST["base64"] ) ); 55 $sizes = ( isset( $_POST["base64Sizes"] ) ? $_POST["base64Sizes"] : array() );55 $sizes = ( isset( $_POST["base64Sizes"] ) ? (array) $_POST["base64Sizes"] : array() ); 56 56 // DO NOT SANITIZE because it's an array 57 57 $base64_webp = ( isset( $_POST["base64Webp"] ) ? sanitize_text_field( wp_unslash( $_POST["base64Webp"] ) ) : '' ); 58 $sizes_webp = ( isset( $_POST["base64SizesWebp"] ) ? $_POST["base64SizesWebp"] : array() );58 $sizes_webp = ( isset( $_POST["base64SizesWebp"] ) ? (array) $_POST["base64SizesWebp"] : array() ); 59 59 $file_format = ( isset( $_POST["format"] ) ? sanitize_text_field( wp_unslash( $_POST["format"] ) ) : '' ); 60 60 $filename = ( isset( $_POST["filename"] ) ? sanitize_text_field( wp_unslash( $_POST["filename"] ) ) : '' ); 61 61 $extension = pathinfo( $filename, PATHINFO_EXTENSION ); 62 62 $image_formats = self::$SqueezeHelpers->get_image_formats(); 63 $original_file = ( isset( $_FILES['originalFile'] ) ? $_FILES['originalFile'] : null ); 63 64 if ( !in_array( $extension, $image_formats ) || empty( $file_format ) ) { 64 65 wp_send_json_error( '❌ ' . esc_html__( 'Invalid image format', 'squeeze' ) ); … … 74 75 } 75 76 $is_backup_original = self::$SqueezeHelpers->get_option( 'backup_original' ); 77 $is_direct_webp = self::$SqueezeHelpers->get_option( 'direct_webp' ); 76 78 // Upload path. 77 79 $upload_path = self::$SqueezeHelpers->get_upload_path( $attach_id, $filename, $url ); 78 80 $decoded = self::$SqueezeHelpers->decode_base64_image( $base64, $file_format ); 81 $webp_file_path = ''; 82 $old_metadata = wp_get_attachment_metadata( $attach_id ); 83 $old_filename = $filename; 84 // in case the original file is not webp and we should convert it to webp 85 // we need to generate a new filename for the webp file 86 // and update its url 87 if ( $file_format === 'webp' && $extension !== 'webp' && $is_direct_webp && $process !== 'path' ) { 88 $file = get_attached_file( $attach_id ); 89 // get the _wp_attached_file meta value which looks like "2023/10/image.jpg" 90 $path_info = pathinfo( $file ); 91 $dirname = $path_info['dirname']; 92 //Get a unique filename in that folder 93 $unique_filename = wp_unique_filename( $dirname, sanitize_file_name( preg_replace( '/\\.[^.]+$/', '.webp', $filename ) ) ); 94 $webp_file_path = trailingslashit( $dirname ) . $unique_filename; 95 // looks like "E:\Extra-Time\test/wp-content/uploads/2023/10/image.webp" 96 $filename = basename( $unique_filename ); 97 $url = str_replace( ABSPATH, home_url( '/' ), $webp_file_path ); 98 // convert file path to URL 99 //wp_send_json_error($filename . ' ' . $url . ' ' . $webp_file_path); 100 } 101 if ( $original_file ) { 102 $sizes['original']['original_size'] = $original_file['size']; 103 } else { 104 $sizes['original']['original_size'] = wp_filesize( $upload_path . $filename ); 105 } 106 $sizes['original']['compressed_size'] = strlen( $decoded ); 107 // check if compressed_size is greater than original_size 108 if ( $sizes['original']['compressed_size'] > $sizes['original']['original_size'] ) { 109 wp_send_json_error( '❌ ' . esc_html__( 'Compressed image size is greater than original size', 'squeeze' ) ); 110 } 79 111 if ( $is_backup_original && $process !== 'path' ) { 80 112 // do not backup for non library images 81 113 // backup original 82 $backup_original_image = self::$SqueezeHelpers->backup_original_image( $upload_path, $filename ); 114 if ( $original_file ) { 115 $backup_original_image = self::$SqueezeHelpers->backup_original_image( $upload_path, $filename, $original_file['tmp_name'] ); 116 } else { 117 $backup_original_image = self::$SqueezeHelpers->backup_original_image( $upload_path, $filename ); 118 } 83 119 if ( is_wp_error( $backup_original_image ) ) { 84 120 wp_send_json_error( $backup_original_image->get_error_message() ); 85 121 } 86 122 } 87 $sizes['original']['original_size'] = wp_filesize( $upload_path . $filename );88 $sizes['original']['compressed_size'] = strlen( $decoded );89 123 // Save the image in the uploads directory. 90 124 $upload_image = self::$SqueezeHelpers->upload_image( $upload_path, $filename, $decoded ); … … 97 131 wp_send_json_error( $upload_webp->get_error_message() ); 98 132 } 99 self::$SqueezeHelpers->upload_webp_thumbs( $upload_path, $sizes_webp );133 $upload_webp_thumbs = self::$SqueezeHelpers->upload_webp_thumbs( $upload_path, $sizes_webp ); 100 134 // skip handling errors for webp thumbs, because they are not always required 101 135 } 102 136 // upload thumbnails 103 137 if ( $process !== 'path' ) { 104 $sizes = self::$SqueezeHelpers->upload_image_thumbs( $upload_path, $sizes, $file_format ); 138 if ( $file_format === 'webp' && $extension !== 'webp' && $is_direct_webp ) { 139 update_attached_file( $attach_id, $webp_file_path ); 140 // update the _wp_attached_file meta value to the new webp file path 141 wp_update_post( [ 142 'ID' => $attach_id, 143 'post_mime_type' => 'image/webp', 144 ] ); 145 $metadata = wp_generate_attachment_metadata( $attach_id, $webp_file_path ); 146 wp_update_attachment_metadata( $attach_id, $metadata ); 147 } 148 $sizes = self::$SqueezeHelpers->upload_image_thumbs( 149 $upload_path, 150 $sizes, 151 $file_format, 152 $filename 153 ); 154 //wp_send_json_error( print_r($sizes, true) ); 105 155 if ( is_wp_error( $sizes ) ) { 106 156 wp_send_json_error( $sizes->get_error_message() ); 157 } 158 if ( $file_format === 'webp' && $extension !== 'webp' && $is_direct_webp ) { 159 // remove webp images from the squeeze-webp directory 160 $this->delete_webp_images( $attach_id, $old_metadata ); 161 // remove original JPG/PNG file if it exists 162 foreach ( $old_metadata['sizes'] as $size_name => $size_data ) { 163 $old_size_filename = $size_data['file']; 164 wp_delete_file( $upload_path . $old_size_filename ); 165 } 166 $old_scaled_filename = basename( $old_metadata['file'] ); 167 wp_delete_file( $upload_path . $old_scaled_filename ); 168 $old_original_path = $upload_path . $old_filename; 169 wp_delete_file( $old_original_path ); 170 if ( $is_backup_original ) { 171 // delete old backup file 172 $backup_filename = self::$SqueezeHelpers->create_backup_filename( $old_filename ); 173 $old_backup_path = $upload_path . $backup_filename; 174 wp_delete_file( $old_backup_path ); 175 } 107 176 } 108 177 update_post_meta( $attach_id, "squeeze_is_compressed", true ); … … 114 183 'uncompressed_images' => $uncompressed_images, 115 184 ) ); 116 wp_send_json_success( $response_msg ); 117 /*wp_send_json_success(array( 118 'message' => $response_msg, 119 'sizes' => $sizes, 120 ));*/ 185 //wp_send_json_error( print_r($sizes, true) ); 186 //wp_send_json_success($response_msg . print_r($sizes['scaled']['url'], true) . ' | ' . $filename . ' | ' . pathinfo($filename, PATHINFO_FILENAME) ); 187 //wp_send_json_success($response_msg); 188 wp_send_json_success( array( 189 'message' => $response_msg, 190 'sizes' => $sizes, 191 'filename' => $filename, 192 'url' => $url, 193 ) ); 121 194 } else { 122 195 wp_send_json_success( '✅ ' . esc_html__( 'Squeezed successfully', 'squeeze' ) ); … … 134 207 if ( $can_restore ) { 135 208 $is_restore_attachment = self::$SqueezeHelpers->restore_attachment( $attach_id ); 136 if ( $is_restore_attachment) {209 if ( !is_wp_error( $is_restore_attachment ) ) { 137 210 wp_send_json_success( '✅ ' . esc_html__( 'Restored successfully', 'squeeze' ) ); 138 211 } else { … … 245 318 } 246 319 247 public function delete_webp_images( $attach_id ) {320 public function delete_webp_images( $attach_id, $old_metadata = null ) { 248 321 $original_img_path = wp_get_original_image_path( (int) $attach_id ); 249 $attachment_data = wp_get_attachment_metadata( $attach_id);322 $attachment_data = ( $old_metadata ? $old_metadata : wp_get_attachment_metadata( $attach_id ) ); 250 323 $delete_webp_images = self::$SqueezeHelpers->delete_webp_images( $original_img_path, $attachment_data ); 251 324 return $delete_webp_images; … … 502 575 return $content; 503 576 } 577 $content_folder = basename( WP_CONTENT_DIR ); 504 578 // Regular expression to find JPG and PNG images in src and srcset attributes. 505 $pattern = '/(\\/\\/.*?\\/ wp-content\\/)([^"\\s]+\\.(jpg|jpeg|png))(\\?[^"\\s]*)?/i';579 $pattern = '/(\\/\\/.*?\\/' . preg_quote( $content_folder, '/' ) . '\\/)([^"\\s]+\\.(jpg|jpeg|png))(\\?[^"\\s]*)?/i'; 506 580 // Callback function to replace the URLs. 507 581 $callback = function ( $matches ) { … … 556 630 $filesize = wp_filesize( $attachment_path ); 557 631 $filesize_human = size_format( $filesize ); 632 $image_info = getimagesize( $attachment_path ); 633 $image_width = $image_info[0]; 634 $image_height = $image_info[1]; 558 635 $response['filesizeInBytes'] = $filesize; 559 636 $response['filesizeHumanReadable'] = $filesize_human; 637 $response['width'] = $image_width; 638 $response['height'] = $image_height; 560 639 } 561 640 return $response; … … 572 651 $attachment_path = get_attached_file( $attachment_id ); 573 652 $filesize = wp_filesize( $attachment_path ); 653 $image_info = getimagesize( $attachment_path ); 654 $image_width = $image_info[0]; 655 $image_height = $image_info[1]; 574 656 $data['filesize'] = $filesize; 657 $data['width'] = $image_width; 658 $data['height'] = $image_height; 575 659 } 576 660 return $data; -
squeeze/trunk/inc/helpers.php
r3311866 r3345284 24 24 } 25 25 26 public function backup_original_image($upload_path,$filename) {26 public function create_backup_filename($filename) { 27 27 $backup_filename = preg_replace("/(\.(?!.*\.))/", '.bak.', $filename); 28 return $backup_filename; 29 } 30 31 public function backup_original_image($upload_path, $filename, $original_file = null) { 32 if ( ! function_exists( 'WP_Filesystem' ) ) { 33 require_once ABSPATH . 'wp-admin/includes/file.php'; 34 } 35 36 global $wp_filesystem; 37 38 // Initialize the filesystem (this populates $wp_filesystem) 39 WP_Filesystem(); 40 41 if ( ! $wp_filesystem || ! method_exists( $wp_filesystem, 'copy' ) ) { 42 return new \WP_Error( 'squeeze_filesystem_api_error', 'Filesystem API is not available or failed to initialize.' ); 43 } 44 45 $backup_filename = $this->create_backup_filename($filename); 28 46 if (!file_exists($upload_path . $backup_filename)) { 29 47 try { 30 $upload_backup_file = copy($upload_path . $filename, $upload_path . $backup_filename); 48 if (!$original_file) { 49 $upload_backup_file = $wp_filesystem->copy($upload_path . $filename, $upload_path . $backup_filename, true); 50 } else { 51 $upload_backup_file = move_uploaded_file($original_file, $upload_path . $backup_filename); 52 } 31 53 } catch (\Exception $e) { 32 54 return new \WP_Error('squeeze_backup_original_image_failed', '❌ '.esc_html__('Backup original image failed', 'squeeze') . ': '. $upload_path . $backup_filename); … … 43 65 } 44 66 45 public function upload_image($upload_path, $filename, $decoded_image) { 67 public function upload_image($upload_path, $filename, $decoded_image, $is_file = false) { 68 if ( ! function_exists( 'WP_Filesystem' ) ) { 69 require_once ABSPATH . 'wp-admin/includes/file.php'; 70 } 71 46 72 global $wp_filesystem; 47 if (empty($wp_filesystem)) { 48 require_once(ABSPATH . '/wp-admin/includes/file.php'); 49 WP_Filesystem(); 50 } 51 $upload_file = $wp_filesystem->put_contents($upload_path . $filename, $decoded_image); 73 74 // Initialize the filesystem (this populates $wp_filesystem) 75 WP_Filesystem(); 76 77 if ( ! $wp_filesystem || ! method_exists( $wp_filesystem, 'copy' ) ) { 78 return new \WP_Error('squeeze_filesystem_api_error', 'Filesystem API is not available or failed to initialize.'); 79 } 80 81 if ($is_file) { 82 $upload_file = move_uploaded_file($decoded_image, $upload_path . $filename); 83 } else { 84 $upload_file = $wp_filesystem->put_contents($upload_path . $filename, $decoded_image); 85 } 52 86 if (!$upload_file) { 53 87 return new \WP_Error('squeeze_upload_image_failed', '❌ '.esc_html__('Upload image failed', 'squeeze') . ': <br>upload_path: ' . $upload_path . '<br>filename: ' . $filename); … … 57 91 } 58 92 59 public function upload_image_thumbs($upload_path, $sizes, $file_format ) {93 public function upload_image_thumbs($upload_path, $sizes, $file_format, $filename = '') { 60 94 if (!is_array($sizes) || empty($sizes)) { 61 95 return new \WP_Error('squeeze_upload_image_thumbs_failed', '❌ '.esc_html__('No image data found', 'squeeze')); 62 96 } 97 98 if ( ! function_exists( 'WP_Filesystem' ) ) { 99 require_once ABSPATH . 'wp-admin/includes/file.php'; 100 } 101 63 102 global $wp_filesystem; 64 if (empty($wp_filesystem)) { 65 require_once(ABSPATH . '/wp-admin/includes/file.php'); 66 WP_Filesystem(); 67 } 103 104 // Initialize the filesystem (this populates $wp_filesystem) 105 WP_Filesystem(); 106 107 if ( ! $wp_filesystem || ! method_exists( $wp_filesystem, 'copy' ) ) { 108 return new \WP_Error('squeeze_filesystem_api_error', 'Filesystem API is not available or failed to initialize.'); 109 } 110 111 $is_direct_webp = $this->get_option('direct_webp'); 68 112 foreach ($sizes as $size_name => $size_data) { 69 113 if ($size_name === 'original') { 70 114 continue; 71 115 } 116 $new_size_url = ''; 117 if ($file_format === 'webp' && $is_direct_webp && $filename) { 118 //$size_data['url'] = preg_replace('/\.[^.]+$/', '.webp', $size_data['url']); 119 120 // remove extension from filename if it exists 121 //$origin_filename = $filename; 122 $new_filename = pathinfo($filename, PATHINFO_FILENAME); // DO NOT appennd to the $filename, causes bug with complex filenames 123 124 125 // replace the filename in the URL before the last dash 126 // e.g. 'http://localhost/test/wp-content/uploads/2025/08/image-thumbxsize.jpg' becomes 127 // 'http://localhost/test/wp-content/uploads/2025/08/$new_filename-thumbxsize.webp' 128 129 // 1. Match and capture path, base filename, suffix, and extension 130 //if (preg_match('/^(.*\/)(.+)-([^-\/]+)\.((?:jpe?g|png))$/i', $size_data['url'], $m)) { 131 if (preg_match('#^(?P<path>.*/wp-content/uploads/.*/)(?P<base>[^/]+?)(?P<suffix>-(?:\d+x\d+|scaled|rotated))?\.(?P<ext>jpe?g|png)$#i', $size_data['url'], $m)) { 132 // $m[1] = the full path including trailing slash 133 // $m[2] = the base filename (before the dash) 134 // $m[3] = the suffix (between dash and extension) 135 // $m[4] = the original extension 136 137 $path = $m[1]; 138 //$new_filename = $m[2]; // <-- this is your variable 139 $suffix = $m[3]; 140 141 // 2. Rebuild URL with .webp 142 $new_size_url = "{$path}{$new_filename}{$suffix}.webp"; 143 } 144 } 72 145 $size_base64 = sanitize_text_field($size_data['base64']); 73 146 $size_decoded = $this->decode_base64_image($size_base64, $file_format); 74 $size_filename = basename(sanitize_url($ size_data['url']));147 $size_filename = basename(sanitize_url($new_size_url ? $new_size_url : $size_data['url'])); 75 148 if ($size_name === 'full') { 76 149 $size_name = 'scaled'; … … 88 161 } 89 162 90 public function upload_webp($upload_path, $base64_webp, $filename ) {163 public function upload_webp($upload_path, $base64_webp, $filename, $is_file = false) { 91 164 if (!$base64_webp) { 92 165 return new \WP_Error('squeeze_upload_webp_failed', '❌ '.esc_html__('No WebP data found', 'squeeze')); … … 97 170 wp_mkdir_p($upload_webp_path); 98 171 } 99 $decoded_webp = $ this->decode_base64_image($base64_webp, 'webp');172 $decoded_webp = $is_file ? $base64_webp : $this->decode_base64_image($base64_webp, 'webp'); 100 173 $filename_webp = $filename.'.webp'; 101 $upload_file_webp = $this->upload_image($upload_webp_path, $filename_webp, $decoded_webp );174 $upload_file_webp = $this->upload_image($upload_webp_path, $filename_webp, $decoded_webp, $is_file); 102 175 103 176 return $upload_file_webp; … … 127 200 128 201 public function convert_image_path_to_webp_path($image_path) { 129 $webp_path = preg_replace('/wp-content[\/\\\\]/', 'wp-content/squeeze-webp/', $image_path, 1); 130 return str_replace(['/', '\\'], '/', $webp_path); 202 //$webp_path = preg_replace('/wp-content[\/\\\\]/', 'wp-content/squeeze-webp/', $image_path, 1); 203 //return str_replace(['/', '\\'], '/', $webp_path); 204 205 // Grab your actual content folder name (e.g. "wp-content" or custom) 206 $content_folder = basename( WP_CONTENT_DIR ); 207 208 // Build a regex to match that folder plus a slash or backslash 209 $pattern = sprintf( 210 '#%s[\\/\\\\]#', 211 preg_quote( $content_folder, '#' ) 212 ); 213 // Replace with "{folder}/squeeze-webp/" 214 $replacement = $content_folder . '/squeeze-webp/'; 215 216 // Do the one-time replacement… 217 $webp_path = preg_replace( $pattern, $replacement, $image_path, 1 ); 218 219 // Normalize backslashes to forward slashes and return 220 return str_replace( '\\', '/', $webp_path ); 131 221 } 132 222 … … 140 230 141 231 public function restore_attachment($attach_id, $is_bulk = false) { 232 if ( ! function_exists( 'WP_Filesystem' ) ) { 233 require_once ABSPATH . 'wp-admin/includes/file.php'; 234 } 235 236 global $wp_filesystem; 237 238 // Initialize the filesystem (this populates $wp_filesystem) 239 WP_Filesystem(); 240 241 if ( ! $wp_filesystem || ! method_exists( $wp_filesystem, 'copy' ) ) { 242 if ($is_bulk) { 243 wp_die( 'Filesystem API is not available or failed to initialize.' ); 244 } else { 245 return new \WP_Error('squeeze_filesystem_api_error', 'Filesystem API is not available or failed to initialize.'); 246 } 247 } 248 142 249 $original_img_path = wp_get_original_image_path($attach_id); 143 250 $backup_img_path = preg_replace("/(\.(?!.*\.))/", '.bak.', $original_img_path); … … 153 260 } 154 261 155 $backup_img = copy($backup_img_path, $original_img_path);262 $backup_img = $wp_filesystem->copy($backup_img_path, $original_img_path, true); 156 263 if (!$backup_img) { 157 264 $error_message = '❌ ' . esc_html__('Restore original image failed', 'squeeze'); … … 229 336 } 230 337 338 //$table = print_r($sizes, true); 231 339 $table = '<div class="squeeze-comparison-table">'; 232 340 $table .= '<table class="wp-list-table widefat striped">'; … … 235 343 236 344 foreach ($sizes as $size_name => $size_data) { 237 $size_filename = basename(sanitize_url($size_data['url'])); 345 /*if (!isset($size_data['url'])) { 346 continue; 347 }*/ 348 //$size_filename = basename(sanitize_url($size_data['url'])); 238 349 $original_size = $size_data['original_size']; 239 350 $compressed_size = $size_data['compressed_size']; … … 435 546 'auto_webp' => false, // needs to be false by default, because user has to save settings first in order to flush rewrite rules 436 547 'webp_replace_urls' => false, 548 'direct_webp' => false, 437 549 'cdn_url' => '', 438 550 'backup_original' => true, … … 451 563 return in_array($option, array_keys($options_defaults)) ? $options_defaults[ $option ] : false; 452 564 } 565 566 public function get_thumb_sizes() { 567 $sizes = wp_get_registered_image_subsizes(); 568 if ( !empty( $sizes ) && is_array( $sizes ) ) { 569 // Add the scaled image size option if it fits the image dimensions 570 $big_image_size_threshold = apply_filters('big_image_size_threshold', 2560); 571 if ( $big_image_size_threshold ) { 572 $sizes['full'] = array( 573 'width' => $big_image_size_threshold, 574 'height' => $big_image_size_threshold, 575 'crop' => false, 576 ); 577 } 578 } 579 return $sizes; 580 } 581 582 public function is_rest_enabled() { 583 // Check if REST API is enabled 584 if ( !function_exists( 'rest_get_server' ) || !rest_get_server() ) { 585 return false; 586 } 587 588 return (bool) apply_filters( 'rest_enabled', true ); 589 } 453 590 } -
squeeze/trunk/inc/settings.php
r3311866 r3345284 48 48 ); 49 49 add_action( 'admin_footer', [$this, 'svg_sprite_output'] ); 50 add_action( 'admin_notices', [$this, 'incompatibility_notices'] ); 50 51 add_action( 'edit_form_after_title', [$this, 'add_preview_button_placeholder'], 10 ); 51 52 } … … 91 92 $directory_path = ( get_transient( 'squeeze_bulk_path' ) ? get_transient( 'squeeze_bulk_path' ) : array('/wp-content/uploads/') ); 92 93 $directory_path_json = wp_json_encode( $directory_path ); 94 $is_direct_webp = self::$SqueezeHelpers->get_option( 'direct_webp' ); 93 95 ?> 94 96 <div class="wrap"> … … 110 112 </div> 111 113 <div class="squeeze-box-content"> 114 <?php 115 if ( $is_direct_webp ) { 116 ?> 117 <div class="squeeze-box-content__row"> 118 <div class="squeeze-box-content__col" style="flex: 1;"> 119 <div class="squeeze-banner squeeze-banner--warning"> 120 <svg class="squeeze-icon"> 121 <use xlink:href="#exclamation-triangle-line-icon"></use> 122 </svg> 123 <div class="squeeze-banner__content"> 124 <p><?php 125 esc_html_e( 'Warning! You have enabled Direct WebP image conversion option.', 'squeeze' ); 126 ?></p> 127 <p><?php 128 esc_html_e( 'All existing JPG/PNG images will be converted to WebP format. Make sure to update your existing image URLs accordingly.', 'squeeze' ); 129 ?></p> 130 </div> 131 </div> 132 </div> 133 </div> 134 <?php 135 } 136 ?> 112 137 <div class="squeeze-box-content__row"> 113 138 <div class="squeeze-box-content__col"> … … 178 203 ?></p> 179 204 <p><?php 180 esc_html_e( 'Please backup your images manually before optimising them.', 'squeeze' );205 esc_html_e( 'Please backup your images manually before squeezing them.', 'squeeze' ); 181 206 ?></p> 182 207 </div> … … 197 222 foreach ( $directory_path as $path ) { 198 223 ?> 199 <input type="text" class="squeeze-path-list__item" value="<?php 224 <div class="squeeze-path-list__item"> 225 <input name="squeeze-path-list__item[]" type="text" class="squeeze-path-list__input" value="<?php 200 226 echo esc_attr( $path ); 201 227 ?>" readonly /> 228 <button name="squeeze_remove_path_button" class="squeeze-path-list__remove" type="button"> 229 <svg class="squeeze-icon"> 230 <use xlink:href="#close-round-icon"></use> 231 </svg> 232 </button> 233 </div> 202 234 <?php 203 235 } … … 330 362 } 331 363 } 332 // check if webp-express/webp-express.php plugin is active and show a notice 333 if ( is_plugin_active( 'webp-express/webp-express.php' ) ) { 334 add_settings_error( 335 'squeeze_notices', 336 'squeeze_notices', 337 __( 'The WebP Express plugin is active. Please deactivate in order to use WebP serving from Squeeze.', 'squeeze' ), 338 'warning' 339 ); 340 } 341 // check if image-converter-webp/image-converter-webp.php plugin is active and show a notice 342 if ( is_plugin_active( 'image-converter-webp/image-converter-webp.php' ) ) { 343 add_settings_error( 344 'squeeze_notices', 345 'squeeze_notices', 346 __( 'The Image Converter for WebP plugin is active. Please deactivate in order to use WebP serving from Squeeze.', 'squeeze' ), 347 'warning' 348 ); 349 } 364 /*if (!self::$SqueezeHelpers->is_rest_enabled()) { 365 add_settings_error( 366 'squeeze_notices', 367 'squeeze_notices', 368 __('The REST API is not enabled on your site. Please enable it in order to use Squeeze plugin.', 'squeeze'), 369 'error' 370 ); 371 }*/ 350 372 ?> 351 373 <div class="wrap"> … … 379 401 esc_html_e( 'Upgrade', 'squeeze' ); 380 402 ?></a> 403 <?php 404 ?> 381 405 <?php 382 406 ?> … … 571 595 <h3 style="text-align: center;"> 572 596 <?php 573 echo sprintf( __( 'To upgrade to the Premium version, <a href="%s" target="_blank">click here</a>.', ' device-wrapper' ), esc_url( self::CHECKOUT_URL ) );597 echo sprintf( __( 'To upgrade to the Premium version, <a href="%s" target="_blank">click here</a>.', 'squeeze' ), esc_url( self::CHECKOUT_URL ) ); 574 598 ?> ↗ 575 599 </h3> … … 577 601 </div> 578 602 </section> 603 <?php 604 ?> 605 579 606 <?php 580 607 ?> … … 644 671 ); 645 672 add_settings_field( 673 'squeeze_setting_direct_webp', 674 __( 'Direct WebP Conversion', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Convert all uploaded images to WEBP format and replace the originals. The original JPEG/PNG files are not stored on the server, which reduces disk usage.', 'squeeze' ) ), 675 [$this, 'options_callback'], 676 'squeeze_options', 677 'squeeze_basic_settings', 678 array( 679 'label_for' => 'direct_webp', 680 'class' => 'squeeze_setting_direct_webp', 681 'type' => 'checkbox', 682 'has_example' => true, 683 ) 684 ); 685 add_settings_field( 646 686 'squeeze_setting_auto_webp', 647 __( 'Generate WEBP', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( ' Generate and serve WEBP images for all uploaded images. The original image URL remains the same, instead the image will be served in a WEBP format.', 'squeeze' ) ),687 __( 'Generate WEBP', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'Instead of the original image URL, the image will be served in WEBP format. WEBP images are stored in a separate directory: wp-content/squeeze-webp.', 'squeeze' ) . ' ' . __( 'This is the old method, in case you already have images being converted using this approach. Otherwise, it is recommended that you use the direct WEBP conversion method above.', 'squeeze' ) ), 648 688 [$this, 'options_callback'], 649 689 'squeeze_options', 650 690 'squeeze_basic_settings', 651 691 array( 652 'label_for' => 'auto_webp', 653 'class' => 'squeeze_setting_auto_webp', 654 'type' => 'checkbox', 692 'label_for' => 'auto_webp', 693 'class' => 'squeeze_setting_auto_webp', 694 'type' => 'checkbox', 695 'has_example' => true, 655 696 ) 656 697 ); 657 698 add_settings_field( 658 699 'squeeze_setting_webp_replace_urls', 659 __( 'Replace images URLs', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'If the method above does not work, check this option. It replaces original URLs of images with therelated WEBP images.', 'squeeze' ) ),700 __( 'Replace images URLs', 'squeeze' ) . self::$SqueezeHelpers->get_hint( __( 'If the method above does not work, try this option. This method replaces the original URLs of the images with related WEBP images.', 'squeeze' ) ), 660 701 [$this, 'options_callback'], 661 702 'squeeze_options', 662 703 'squeeze_basic_settings', 663 704 array( 664 'label_for' => 'webp_replace_urls', 665 'class' => 'squeeze_setting_webp_replace_urls', 666 'type' => 'checkbox', 667 'hidden' => ( $auto_webp ? '' : true ), 705 'label_for' => 'webp_replace_urls', 706 'class' => 'squeeze_setting_webp_replace_urls', 707 'type' => 'checkbox', 708 'has_example' => true, 709 'hidden' => ( $auto_webp ? '' : true ), 668 710 ) 669 711 ); … … 1095 1137 $input['auto_webp'] = ( isset( $input['auto_webp'] ) ? boolval( $input['auto_webp'] ) : '0' ); 1096 1138 $input['webp_replace_urls'] = ( isset( $input['webp_replace_urls'] ) && $input['auto_webp'] ? boolval( $input['webp_replace_urls'] ) : '0' ); 1139 $input['direct_webp'] = ( isset( $input['direct_webp'] ) ? boolval( $input['direct_webp'] ) : '0' ); 1097 1140 $input['cdn_url'] = ( isset( $input['cdn_url'] ) && $input['auto_webp'] ? $input['cdn_url'] : '' ); 1098 1141 $input['backup_original'] = ( isset( $input['backup_original'] ) ? boolval( $input['backup_original'] ) : '0' ); … … 1138 1181 $options = get_option( 'squeeze_options' ); 1139 1182 $is_hidden = ( isset( $args['hidden'] ) && $args['hidden'] ? 'hidden' : '' ); 1183 $has_example = ( isset( $args['has_example'] ) && $args['has_example'] ? true : false ); 1140 1184 $extra_classes = []; 1141 1185 if ( $is_hidden ) { … … 1244 1288 break; 1245 1289 } 1290 if ( $has_example ) { 1291 $value = ( isset( $options[$label_for] ) ? (bool) $options[$label_for] : $default ); 1292 echo '<div class="squeeze-settings-example squeeze-settings-example--' . $label_for . (( $value ? ' enabled' : '' )) . '">'; 1293 switch ( $label_for ) { 1294 case 'direct_webp': 1295 ?> 1296 <span class="squeeze-hint"><?php 1297 echo __( "Example:", 'squeeze' ); 1298 ?></span> 1299 <div class="squeeze-box squeeze-box--fieldset"> 1300 <div class="squeeze-box-content"> 1301 <p><strong><?php 1302 echo __( 'Before', 'squeeze' ); 1303 ?></strong></p> 1304 <p><span><?php 1305 echo __( 'image.jpg', 'squeeze' ); 1306 ?></span> <span><?php 1307 echo __( '500 KB', 'squeeze' ); 1308 ?></span></p> 1309 <p><span><?php 1310 echo __( 'image-100x100.jpg', 'squeeze' ); 1311 ?></span> <span><?php 1312 echo __( '98 KB', 'squeeze' ); 1313 ?></span></p> 1314 <p><span><?php 1315 echo __( 'image-300x300.jpg', 'squeeze' ); 1316 ?></span> <span><?php 1317 echo __( '230 KB', 'squeeze' ); 1318 ?></span></p> 1319 </div> 1320 <div class="squeeze-box-content"> 1321 <p><strong><?php 1322 echo __( 'After', 'squeeze' ); 1323 ?></strong></p> 1324 <p><span class="striked"><?php 1325 echo __( 'image.jpg', 'squeeze' ); 1326 ?></span> <span><?php 1327 echo __( '500 KB', 'squeeze' ); 1328 ?></span></p> 1329 <p><span class="striked"><?php 1330 echo __( 'image-100x100.jpg', 'squeeze' ); 1331 ?></span> <span><?php 1332 echo __( '98 KB', 'squeeze' ); 1333 ?></span></p> 1334 <p><span class="striked"><?php 1335 echo __( 'image-300x300.jpg', 'squeeze' ); 1336 ?></span> <span><?php 1337 echo __( '230 KB', 'squeeze' ); 1338 ?></span></p> 1339 <p><span class="greened"><?php 1340 echo __( 'image.webp', 'squeeze' ); 1341 ?></span> <span><?php 1342 echo __( '50 KB', 'squeeze' ); 1343 ?></span></p> 1344 <p><span class="greened"><?php 1345 echo __( 'image-100x100.webp', 'squeeze' ); 1346 ?></span> <span><?php 1347 echo __( '5 KB', 'squeeze' ); 1348 ?></span></p> 1349 <p><span class="greened"><?php 1350 echo __( 'image-300x300.webp', 'squeeze' ); 1351 ?></span> <span><?php 1352 echo __( '20 KB', 'squeeze' ); 1353 ?></span></p> 1354 </div> 1355 </div> 1356 <?php 1357 break; 1358 case 'auto_webp': 1359 ?> 1360 <span class="squeeze-hint"><?php 1361 echo __( "Example:", 'squeeze' ); 1362 ?></span> 1363 <div class="squeeze-box squeeze-box--fieldset"> 1364 <div class="squeeze-box-content"> 1365 <p><strong><?php 1366 echo __( 'Before', 'squeeze' ); 1367 ?></strong></p> 1368 <code><?php 1369 echo __( '/uploads/2025/07/', 'squeeze' ); 1370 ?></code> 1371 <p><span><?php 1372 echo __( 'image.jpg', 'squeeze' ); 1373 ?></span> <span><?php 1374 echo __( '500 KB', 'squeeze' ); 1375 ?></span></p> 1376 <p><span><?php 1377 echo __( 'image-100x100.jpg', 'squeeze' ); 1378 ?></span> <span><?php 1379 echo __( '98 KB', 'squeeze' ); 1380 ?></span></p> 1381 <p><span><?php 1382 echo __( 'image-300x300.jpg', 'squeeze' ); 1383 ?></span> <span><?php 1384 echo __( '230 KB', 'squeeze' ); 1385 ?></span></p> 1386 </div> 1387 <div class="squeeze-box-content"> 1388 <p><strong><?php 1389 echo __( 'After', 'squeeze' ); 1390 ?></strong></p> 1391 <code><?php 1392 echo __( '/uploads/2025/07/', 'squeeze' ); 1393 ?></code> 1394 <p><span class="greened"><?php 1395 echo __( 'image.jpg', 'squeeze' ); 1396 ?></span> <span><?php 1397 echo __( '100 KB', 'squeeze' ); 1398 ?></span></p> 1399 <p><span class="greened"><?php 1400 echo __( 'image-100x100.jpg', 'squeeze' ); 1401 ?></span> <span><?php 1402 echo __( '15 KB', 'squeeze' ); 1403 ?></span></p> 1404 <p><span class="greened"><?php 1405 echo __( 'image-300x300.jpg', 'squeeze' ); 1406 ?></span> <span><?php 1407 echo __( '40 KB', 'squeeze' ); 1408 ?></span></p> 1409 <code><?php 1410 echo __( '/squeeze-webp/uploads/2025/07/', 'squeeze' ); 1411 ?></code> 1412 <p><span class="greened"><?php 1413 echo __( 'image.webp', 'squeeze' ); 1414 ?></span> <span><?php 1415 echo __( '50 KB', 'squeeze' ); 1416 ?></span></p> 1417 <p><span class="greened"><?php 1418 echo __( 'image-100x100.webp', 'squeeze' ); 1419 ?></span> <span><?php 1420 echo __( '5 KB', 'squeeze' ); 1421 ?></span></p> 1422 <p><span class="greened"><?php 1423 echo __( 'image-300x300.webp', 'squeeze' ); 1424 ?></span> <span><?php 1425 echo __( '20 KB', 'squeeze' ); 1426 ?></span></p> 1427 </div> 1428 </div> 1429 <?php 1430 break; 1431 case 'webp_replace_urls': 1432 ?> 1433 <span class="squeeze-hint"><?php 1434 echo __( "Example:", 'squeeze' ); 1435 ?></span> 1436 <div class="squeeze-box squeeze-box--fieldset"> 1437 <div class="squeeze-box-content"> 1438 <img src="<?php 1439 echo esc_url( plugin_dir_url( __FILE__ ) . '../assets/images/replace_urls.jpg' ); 1440 ?>" alt="<?php 1441 echo esc_attr__( 'Example image', 'squeeze' ); 1442 ?>"> 1443 </div> 1444 </div> 1445 <?php 1446 break; 1447 } 1448 echo '</div>'; 1449 } 1246 1450 } 1247 1451 … … 1272 1476 public function setting_upgrade_desc() { 1273 1477 echo '<p>' . esc_html__( 'Upgrade to premium version for more features.', 'squeeze' ) . '</p>'; 1478 } 1479 1480 public function setting_license_desc() { 1274 1481 } 1275 1482 … … 1465 1672 } 1466 1673 1674 public function incompatibility_notices() { 1675 // Bail if we're not in the admin or the screen helper isn't available. 1676 if ( !is_admin() || !function_exists( 'get_current_screen' ) ) { 1677 return; 1678 } 1679 $screen = get_current_screen(); 1680 // List of screen IDs where we want the warning. 1681 $target_screens = array( 1682 'settings_page_squeeze', 1683 // options-general.php?page=squeeze 1684 'media_page_squeeze-bulk', 1685 // upload.php?page=squeeze-bulk 1686 'upload', 1687 // the core Media → Library (list table) 1688 'media', 1689 // the core Media → Add New 1690 'plugins', 1691 ); 1692 if ( !in_array( $screen->id, $target_screens ) ) { 1693 return; 1694 } 1695 // check if webp-express/webp-express.php plugin is active and show a notice 1696 if ( is_plugin_active( 'webp-express/webp-express.php' ) ) { 1697 ?> 1698 <div class="notice notice-warning is-dismissible"> 1699 <p> 1700 <?php 1701 echo __( 'The WebP Express plugin is active. Please deactivate it in order to use correct WebP serving from <strong>Squeeze plugin</strong>.', 'squeeze' ); 1702 ?> 1703 </p> 1704 </div> 1705 <?php 1706 } 1707 // check if image-converter-webp/image-converter-webp.php plugin is active and show a notice 1708 if ( is_plugin_active( 'image-converter-webp/image-converter-webp.php' ) ) { 1709 ?> 1710 <div class="notice notice-warning is-dismissible"> 1711 <p> 1712 <?php 1713 echo __( 'The Image Converter for WebP plugin is active. Please deactivate it in order to use correct WebP serving from <strong>Squeeze plugin</strong>.', 'squeeze' ); 1714 ?> 1715 </p> 1716 </div> 1717 <?php 1718 } 1719 } 1720 1467 1721 } -
squeeze/trunk/languages/squeeze-uk-0282bc9bb3139ae7f3090194c10090b4.json
r3267306 r3345284 1 1 { 2 "translation-revision-date": "2025-0 4-05 21:59+0300",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "assets\/js\/script.js", … … 20 20 "(<a href=\"%s\" target=\"_blank\">\u0442\u0456\u043b\u044c\u043a\u0438 \u043f\u0440\u0435\u043c\u0456\u0443\u043c<\/a>)" 21 21 ], 22 "Bulk squeezing has been paused!": [23 "\u0421\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u043e \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0435!"24 ],25 "Resume bulk squeezing": [26 "\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f"27 ],28 "Pause bulk squeezing": [29 "\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f"30 ],31 "Are you sure you want to leave this page? The squeezing process will be terminated!": [32 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0431\u0443\u0434\u0435 \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0438\u0439!"33 ],34 "Are you sure you want to leave this page? The settings will not be saved!": [35 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456!"36 ],37 "Restore in process...": [38 "\u0412\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0456..."39 ],40 22 "Squeezing...": [ 41 23 "\u0421\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..." 42 24 ], 43 " Start squeezing...": [44 "\u041 f\u043e\u0447\u0438\u043d\u0430\u0454\u043c\u043e \u0441\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..."25 "An error has occured. Check the console for details.": [ 26 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c." 45 27 ], 46 28 "Pausing...": [ … … 50 32 "\u0412\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0438 \u043e\u0431\u0440\u043e\u0431\u043b\u0435\u043d\u0456!" 51 33 ], 52 "An error has occured. Check the console for details.": [53 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c."54 ],55 34 "Please enter a valid path!": [ 56 35 "\u0411\u0443\u0434\u044c\u0442\u0435 \u043b\u0430\u0441\u043a\u0430\u0432\u0456, \u0432\u0432\u0435\u0434\u0456\u0442\u044c \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438\u0439 \u0448\u043b\u044f\u0445 \u0434\u043e \u043f\u0430\u043f\u043a\u0438!" 57 ],58 "Found images on the page:": [59 "\u0417\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456:"60 ],61 "Error:": [62 "\u041f\u043e\u043c\u0438\u043b\u043a\u0430:"63 ],64 "An error has occurred while fetching images from the page. Check the console for details.": [65 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0437\u0456 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438. \u0417\u0432\u0435\u0440\u043d\u0456\u0442\u044c\u0441\u044f \u0434\u043e \u043a\u043e\u043d\u0441\u043e\u043b\u0456 \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c."66 36 ], 67 37 "Loading Preview...": [ -
squeeze/trunk/languages/squeeze-uk-08ec2477f322448a2db534074ac234a4.json
r3267306 r3345284 1 1 { 2 "translation-revision-date": "2025-0 4-05 21:59+0300",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "assets\/js\/4240e511ac61ecfff2d8.js", -
squeeze/trunk/languages/squeeze-uk-24b88c172a2803f6ee0c4956b1a8afb1.json
r3267306 r3345284 1 1 { 2 "translation-revision-date": "2025-0 4-05 21:59+0300",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "assets\/js\/script.bundle.js", … … 41 41 "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043e" 42 42 ], 43 "Squeezing...": [ 44 "\u0421\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..." 45 ], 46 "An error has occured. Check the console for details.": [ 47 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c." 48 ], 49 "Media": [ 50 "\u041c\u0435\u0434\u0456\u0430" 51 ], 52 "Resume bulk squeezing": [ 53 "\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f" 54 ], 55 "Pause bulk squeezing": [ 56 "\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f" 57 ], 58 "Restore in process...": [ 59 "\u0412\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0456..." 60 ], 61 "Pausing...": [ 62 "\u041f\u0430\u0443\u0437\u0430..." 63 ], 64 "All images have been processed!": [ 65 "\u0412\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0438 \u043e\u0431\u0440\u043e\u0431\u043b\u0435\u043d\u0456!" 66 ], 67 "Are you sure you want to leave this page? The squeezing process will be terminated!": [ 68 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0431\u0443\u0434\u0435 \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0438\u0439!" 69 ], 70 "Are you sure you want to leave this page? The settings will not be saved!": [ 71 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456!" 72 ], 43 73 "Bulk squeezing has been paused!": [ 44 74 "\u0421\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u043e \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0435!" 45 75 ], 46 "Media": [ 47 "\u041c\u0435\u0434\u0456\u0430" 76 "No more images found!": [ 77 "\u0411\u0456\u043b\u044c\u0448\u0435 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e!" 78 ], 79 "Start squeezing...": [ 80 "\u041f\u043e\u0447\u0438\u043d\u0430\u0454\u043c\u043e \u0441\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..." 81 ], 82 "Found images on the page:": [ 83 "\u0417\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456:" 84 ], 85 "Error:": [ 86 "\u041f\u043e\u043c\u0438\u043b\u043a\u0430:" 87 ], 88 "An error has occurred while fetching images from the page. Check the console for details.": [ 89 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0437\u0456 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438. \u0417\u0432\u0435\u0440\u043d\u0456\u0442\u044c\u0441\u044f \u0434\u043e \u043a\u043e\u043d\u0441\u043e\u043b\u0456 \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c." 90 ], 91 "File is excluded from compression:": [ 92 "\u0412\u043a\u043b\u0430\u0434\u0435\u043d\u043d\u044f \u0432\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0437\u0456 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f" 93 ], 94 "File compression failed:": [ 95 "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0441\u0442\u0438\u0441\u043d\u0443\u0442\u0438 \u0444\u0430\u0439\u043b:" 48 96 ], 49 97 "Show details": [ … … 59 107 "\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u0438 \u043e\u0431\u0440\u043e\u0431\u0446\u0456 \u0448\u043b\u044f\u0445\u0443 \u0434\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0443!" 60 108 ], 61 "Resume bulk squeezing": [62 "\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f"63 ],64 "Pause bulk squeezing": [65 "\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f"66 ],67 "Are you sure you want to leave this page? The squeezing process will be terminated!": [68 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0431\u0443\u0434\u0435 \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0438\u0439!"69 ],70 "Are you sure you want to leave this page? The settings will not be saved!": [71 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456!"72 ],73 "Restore in process...": [74 "\u0412\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0456..."75 ],76 "Squeezing...": [77 "\u0421\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..."78 ],79 "Start squeezing...": [80 "\u041f\u043e\u0447\u0438\u043d\u0430\u0454\u043c\u043e \u0441\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..."81 ],82 "Pausing...": [83 "\u041f\u0430\u0443\u0437\u0430..."84 ],85 "All images have been processed!": [86 "\u0412\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0438 \u043e\u0431\u0440\u043e\u0431\u043b\u0435\u043d\u0456!"87 ],88 "An error has occured. Check the console for details.": [89 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c."90 ],91 109 "Please enter a valid path!": [ 92 110 "\u0411\u0443\u0434\u044c\u0442\u0435 \u043b\u0430\u0441\u043a\u0430\u0432\u0456, \u0432\u0432\u0435\u0434\u0456\u0442\u044c \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438\u0439 \u0448\u043b\u044f\u0445 \u0434\u043e \u043f\u0430\u043f\u043a\u0438!" 93 ],94 "Found images on the page:": [95 "\u0417\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456:"96 ],97 "Error:": [98 "\u041f\u043e\u043c\u0438\u043b\u043a\u0430:"99 ],100 "An error has occurred while fetching images from the page. Check the console for details.": [101 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0437\u0456 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438. \u0417\u0432\u0435\u0440\u043d\u0456\u0442\u044c\u0441\u044f \u0434\u043e \u043a\u043e\u043d\u0441\u043e\u043b\u0456 \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c."102 111 ], 103 112 "Loading Preview...": [ -
squeeze/trunk/languages/squeeze-uk-8a8cc8d6792f201000247ed42d4140e8.json
r3200178 r3345284 1 1 { 2 "translation-revision-date": "202 4-11-30 13:36+0200",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "copy.js", … … 11 11 "plural-forms": "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);" 12 12 }, 13 "Are you sure you want to leave this page? The compression process will be terminated!": [ 13 "Squeezing...": [ 14 "\u0421\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..." 15 ], 16 "An error has occured. Check the console for details.": [ 17 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c." 18 ], 19 "Media": [ 20 "\u041c\u0435\u0434\u0456\u0430" 21 ], 22 "Resume bulk squeezing": [ 23 "\u0412\u0456\u0434\u043d\u043e\u0432\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f" 24 ], 25 "Pause bulk squeezing": [ 26 "\u041f\u0440\u0438\u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f" 27 ], 28 "Restore in process...": [ 29 "\u0412\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0456..." 30 ], 31 "Pausing...": [ 32 "\u041f\u0430\u0443\u0437\u0430..." 33 ], 34 "All images have been processed!": [ 35 "\u0412\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0438 \u043e\u0431\u0440\u043e\u0431\u043b\u0435\u043d\u0456!" 36 ], 37 "Are you sure you want to leave this page? The squeezing process will be terminated!": [ 14 38 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0431\u0443\u0434\u0435 \u043f\u0435\u0440\u0435\u0440\u0432\u0430\u043d\u0438\u0439!" 15 39 ], … … 17 41 "\u0412\u0438 \u0432\u043f\u0435\u0432\u043d\u0435\u043d\u0456, \u0449\u043e \u0445\u043e\u0447\u0435\u0442\u0435 \u0437\u0430\u043b\u0438\u0448\u0438\u0442\u0438 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0443? \u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442\u044c \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456!" 18 42 ], 19 " An error has occured. Check the console for details.": [20 "\u04 12\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c."43 "Bulk squeezing has been paused!": [ 44 "\u0421\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u043e \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0435!" 21 45 ], 22 " Restore in process...": [23 "\u041 2\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0456..."46 "No more images found!": [ 47 "\u0411\u0456\u043b\u044c\u0448\u0435 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e!" 24 48 ], 25 " Compressing...": [26 "\u04 21\u0442\u0438\u0441\u043a\u0430\u0454\u043c\u043e..."49 "Start squeezing...": [ 50 "\u041f\u043e\u0447\u0438\u043d\u0430\u0454\u043c\u043e \u0441\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..." 27 51 ], 28 " Please enter a valid path!": [29 "\u041 1\u0443\u0434\u044c\u0442\u0435 \u043b\u0430\u0441\u043a\u0430\u0432\u0456, \u0432\u0432\u0435\u0434\u0456\u0442\u044c \u043a\u043e\u0440\u0435\u043a\u0442\u043d\u0438\u0439 \u0448\u043b\u044f\u0445 \u0434\u043e \u043f\u0430\u043f\u043a\u0438!"52 "Found images on the page:": [ 53 "\u0417\u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u0456\u043d\u0446\u0456:" 30 54 ], 31 " Compressed successfully, updating...": [32 "\u04 23\u0441\u043f\u0456\u0448\u043d\u043e \u0441\u0442\u0438\u0441\u043d\u0443\u0442\u043e, \u043e\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044f..."55 "Error:": [ 56 "\u041f\u043e\u043c\u0438\u043b\u043a\u0430:" 33 57 ], 34 "Updated successfully": [ 35 "\u041e\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0443\u0441\u043f\u0456\u0448\u043d\u043e" 36 ], 37 "All images have been compressed!": [ 38 "\u0412\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0438 \u0441\u0442\u0438\u0441\u043d\u0443\u0442\u0456!" 39 ], 40 "All images have been re-compressed again!": [ 41 "\u0412\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0441\u0442\u0438\u0441\u043d\u0443\u0442\u0456!" 58 "An error has occurred while fetching images from the page. Check the console for details.": [ 59 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0456\u0434 \u0447\u0430\u0441 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044c \u0437\u0456 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438. \u0417\u0432\u0435\u0440\u043d\u0456\u0442\u044c\u0441\u044f \u0434\u043e \u043a\u043e\u043d\u0441\u043e\u043b\u0456 \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c." 42 60 ] 43 61 } -
squeeze/trunk/languages/squeeze-uk-b1f8d5e52cbbc262494fff20eec962fd.json
r3267306 r3345284 1 1 { 2 "translation-revision-date": "2025-0 4-05 21:59+0300",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "assets\/js\/squeeze.js", -
squeeze/trunk/languages/squeeze-uk-e9cc8298549e98be96351e6176bc85d5.json
r3267306 r3345284 1 1 { 2 "translation-revision-date": "2025-0 4-05 21:59+0300",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "assets\/js\/helpers.js", … … 20 20 "\u0421\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u0432" 21 21 ], 22 "Media": [ 23 "\u041c\u0435\u0434\u0456\u0430" 24 ], 22 25 "Bulk squeezing has been paused!": [ 23 26 "\u0421\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u043e \u0437\u0443\u043f\u0438\u043d\u0435\u043d\u0435!" 24 ],25 "Media": [26 "\u041c\u0435\u0434\u0456\u0430"27 27 ], 28 28 "Show details": [ -
squeeze/trunk/languages/squeeze-uk-ebfe0cea630778e3fc5018cec6e46aac.json
r3267306 r3345284 1 1 { 2 "translation-revision-date": "2025-0 4-05 21:59+0300",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "assets\/js\/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js", -
squeeze/trunk/languages/squeeze-uk-f98be19bec7bc848ce3ed383c60037c1.json
r3267306 r3345284 1 1 { 2 "translation-revision-date": "2025-0 4-05 21:59+0300",2 "translation-revision-date": "2025-08-10 14:49+0300", 3 3 "generator": "WP-CLI\/2.6.0", 4 4 "source": "assets\/js\/admin.js", … … 11 11 "plural-forms": "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);" 12 12 }, 13 "Bulk Squeeze": [ 14 "\u041c\u0430\u0441\u043e\u0432\u0435 \u0441\u0442\u0438\u0441\u043d\u0435\u043d\u043d\u044f" 15 ], 13 16 "Squeeze: All images": [ 14 17 "Squeeze: \u0423\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f" … … 16 19 "Non Squeezed Images": [ 17 20 "\u041d\u0435 \u0441\u0442\u0438\u0441\u043d\u0443\u0442\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f" 21 ], 22 "Please select at least one image.": [ 23 "\u0411\u0443\u0434\u044c \u043b\u0430\u0441\u043a\u0430, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0445\u043e\u0447\u0430 \u0431 \u043e\u0434\u043d\u0435 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f." 24 ], 25 "Squeezing...": [ 26 "\u0421\u0442\u0438\u0441\u043a\u0430\u043d\u043d\u044f..." 27 ], 28 "All images have been processed.": [ 29 "\u0412\u0441\u0456 \u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0431\u0443\u043b\u0438 \u043e\u0431\u0440\u043e\u0431\u043b\u0435\u043d\u0456\u044e" 30 ], 31 "An error has occured. Check the console for details.": [ 32 "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u043e\u043c\u0438\u043b\u043a\u0430. \u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u043c\u0430\u043d\u043d\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u044c." 18 33 ] 19 34 } -
squeeze/trunk/languages/squeeze-uk.po
r3267306 r3345284 5 5 "Project-Id-Version: Squeeze 1.0\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/squeeze\n" 7 "POT-Creation-Date: 2025-0 4-05T18:53:49+00:00\n"8 "PO-Revision-Date: 2025-0 4-05 21:59+0300\n"7 "POT-Creation-Date: 2025-08-10T11:42:23+00:00\n" 8 "PO-Revision-Date: 2025-08-10 14:49+0300\n" 9 9 "Last-Translator: \n" 10 10 "Language-Team: \n" … … 40 40 msgstr "" 41 41 42 #: freemius.php:12 squeeze.php: 28342 #: freemius.php:12 squeeze.php:369 43 43 msgid "Go Premium" 44 44 msgstr "Хочу Преміум" … … 48 48 msgstr "Вітаємо" 49 49 50 #: inc/handlers.php: 39 inc/handlers.php:173 inc/handlers.php:22351 #: inc/handlers.php: 63550 #: inc/handlers.php:50 inc/handlers.php:266 inc/handlers.php:316 51 #: inc/handlers.php:740 52 52 msgid "You do not have permission to upload files" 53 53 msgstr "У вас немає дозволу на завантаження файлів" 54 54 55 #: inc/handlers.php: 43 inc/helpers.php:6055 #: inc/handlers.php:54 inc/helpers.php:95 56 56 msgid "No image data found" 57 57 msgstr "Медіа дані не знайдено" 58 58 59 #: inc/handlers.php: 56 inc/handlers.php:6059 #: inc/handlers.php:68 60 60 msgid "Invalid image format" 61 61 msgstr "Невірний формат зображення" 62 62 63 #: inc/handlers.php: 69 inc/handlers.php:149 inc/handlers.php:17763 #: inc/handlers.php:77 inc/handlers.php:242 inc/handlers.php:270 64 64 msgid "Attachment not found" 65 65 msgstr "Медіафайл не знайдено" 66 66 67 #: inc/handlers.php:76 inc/handlers.php:190 inc/settings.php:781 68 #: assets/js/script.bundle.js:39 assets/js/squeeze.js:150 67 #: inc/handlers.php:84 inc/handlers.php:283 inc/settings.php:958 68 #: assets/js/admin.bundle.js:49 assets/js/editor.bundle.js:49 69 #: assets/js/parallel.js:66 assets/js/script.bundle.js:49 70 #: assets/js/squeeze.js:200 69 71 msgid "Attachment is excluded from compression" 70 72 msgstr "Вкладення виключено зі стиснення" 71 73 72 #: inc/handlers.php:76 inc/handlers.php:190 inc/settings.php:781 73 #: assets/js/script.bundle.js:39 assets/js/squeeze.js:150 74 #: inc/handlers.php:84 inc/handlers.php:283 inc/settings.php:958 75 #: assets/js/admin.bundle.js:49 assets/js/editor.bundle.js:49 76 #: assets/js/script.bundle.js:49 assets/js/squeeze.js:200 74 77 msgid "found substring: " 75 78 msgstr "знайдено підрядок:" 76 79 77 #: inc/handlers.php:131 inc/handlers.php:139 80 #: inc/handlers.php:130 81 msgid "Compressed image size is greater than original size" 82 msgstr "Розмір стисненого зображення більший за розмір оригіналу" 83 84 #: inc/handlers.php:214 inc/handlers.php:232 78 85 msgid "Squeezed successfully" 79 86 msgstr "Стиснуто успішно" 80 87 81 #: inc/handlers.php: 15988 #: inc/handlers.php:252 82 89 msgid "Restored successfully" 83 90 msgstr "Відновлено успішно" 84 91 85 #: inc/handlers.php: 16192 #: inc/handlers.php:254 86 93 msgid "Attachment not restored" 87 94 msgstr "Медіафайл не відновлено" 88 95 89 #: inc/handlers.php: 22796 #: inc/handlers.php:320 90 97 msgid "Path not found" 91 98 msgstr "Папку не знайдено" 92 99 93 #: inc/handlers.php: 299100 #: inc/handlers.php:392 94 101 msgid "Images were not found in the selected directories" 95 102 msgstr "Зображення не знайдено у вибраних каталогах" 96 103 97 #: inc/handlers.php:328 104 #: inc/handlers.php:425 tests/HandlersTest.php:648 tests/HandlersTest.php:663 105 #: tests/HandlersTest.php:677 98 106 msgid "Restore Original Image" 99 107 msgstr "Відновити оригінальне зображення" 100 108 101 #: inc/handlers.php:329 109 #: inc/handlers.php:426 tests/HandlersTest.php:649 tests/HandlersTest.php:664 110 #: tests/HandlersTest.php:678 102 111 msgid "Squeeze Image" 103 112 msgstr "Стиснути зображення" 104 113 105 #: inc/handlers.php:330 114 #: inc/handlers.php:427 tests/HandlersTest.php:650 tests/HandlersTest.php:665 115 #: tests/HandlersTest.php:679 106 116 msgid "Delete Backup Image" 107 117 msgstr "Видалити резервне зображення" 108 118 109 #: inc/handlers.php:331 119 #: inc/handlers.php:428 tests/HandlersTest.php:651 tests/HandlersTest.php:666 120 #: tests/HandlersTest.php:680 110 121 msgid "Delete WEBP Image" 111 122 msgstr "Видалити WEBP-зображення" 112 123 113 124 #. translators: %d: number of attachments restored 114 #: inc/handlers.php: 392125 #: inc/handlers.php:489 115 126 msgid "%d attachment restored." 116 127 msgid_plural "%d attachments restored." … … 120 131 121 132 #. translators: %d: number of attachments squeezed 122 #: inc/handlers.php: 405133 #: inc/handlers.php:502 123 134 msgid "%d attachment squeezed." 124 135 msgid_plural "%d attachments squeezed." … … 128 139 129 140 #. translators: %d: number of backup images deleted 130 #: inc/handlers.php: 418141 #: inc/handlers.php:515 131 142 msgid "%d backup image deleted." 132 143 msgid_plural "%d backup images deleted." … … 136 147 137 148 #. translators: %d: number of webp images deleted 138 #: inc/handlers.php: 431149 #: inc/handlers.php:528 139 150 msgid "%d WEBP image deleted." 140 151 msgid_plural "%d WEBP images deleted." … … 143 154 msgstr[2] "Резервних зображень видалено." 144 155 145 #: inc/handlers.php: 474156 #: inc/handlers.php:576 146 157 msgid "" 147 158 "Single file upload is not supported for the image compression by Squeeze. " … … 152 163 "стиснення." 153 164 154 #: inc/handlers.php: 641165 #: inc/handlers.php:746 155 166 msgid "Options not found" 156 167 msgstr "Параметри не знайдено" 157 168 158 #: inc/handlers.php: 647169 #: inc/handlers.php:752 159 170 msgid "Options not saved" 160 171 msgstr "Параметри не збережено" 161 172 162 #: inc/handlers.php: 650173 #: inc/handlers.php:755 163 174 msgid "Options saved successfully" 164 175 msgstr "Параметри успішно збережено" 165 176 166 #: inc/helpers.php: 29177 #: inc/helpers.php:54 167 178 msgid "Backup original image failed" 168 179 msgstr "Не вдалося створити резервну копію оригінального зображення" 169 180 170 #: inc/helpers.php: 52 inc/helpers.php:81181 #: inc/helpers.php:87 inc/helpers.php:155 171 182 msgid "Upload image failed" 172 183 msgstr "Не вдалося завантажити зображення" 173 184 174 #: inc/helpers.php: 91 inc/helpers.php:107185 #: inc/helpers.php:165 inc/helpers.php:181 175 186 msgid "No WebP data found" 176 187 msgstr "Дані WebP не знайдено" 177 188 178 #: inc/helpers.php: 145189 #: inc/helpers.php:253 179 190 msgid "Backup image not found" 180 191 msgstr "Резервне зображення не знайдено" 181 192 182 #: inc/helpers.php: 156193 #: inc/helpers.php:264 183 194 msgid "Restore original image failed" 184 195 msgstr "Відновлення оригінального зображення не вдалося" 185 196 186 #: inc/helpers.php: 232197 #: inc/helpers.php:341 187 198 msgid "Size Name" 188 199 msgstr "Розмір" 189 200 190 #: inc/helpers.php: 232201 #: inc/helpers.php:341 191 202 msgid "Original Size" 192 203 msgstr "Початковий" 193 204 194 #: inc/helpers.php: 232205 #: inc/helpers.php:341 195 206 msgid "Squeezed Size" 196 207 msgstr "Стиснутий" 197 208 198 #: inc/helpers.php: 232209 #: inc/helpers.php:341 199 210 msgid "Savings" 200 211 msgstr "Збережено" 201 212 202 #: inc/premium/premium.php:2 1213 #: inc/premium/premium.php:22 203 214 msgid "Page URL not found" 204 215 msgstr "URL-адресу сторінки не знайдено" 205 216 206 #: inc/premium/premium.php:3 7217 #: inc/premium/premium.php:38 207 218 msgid "URL is not from the same domain" 208 219 msgstr "URL-адреса не з того самого домену" 209 220 210 #: inc/premium/premium.php:4 7221 #: inc/premium/premium.php:48 211 222 msgid "Error fetching the page:" 212 223 msgstr "Помилка при завантаженні сторінки:" 213 224 214 #: inc/premium/premium.php: 196 inc/premium/premium.php:200225 #: inc/premium/premium.php:209 inc/premium/premium.php:213 215 226 msgid "No images found on the page" 216 227 msgstr "На сторінці не знайдено жодного зображення" 217 228 218 #: inc/premium/premium.php:2 71 inc/settings.php:37 inc/settings.php:778219 #: inc/settings.php: 789 inc/settings.php:799229 #: inc/premium/premium.php:289 inc/settings.php:38 inc/settings.php:955 230 #: inc/settings.php:966 inc/settings.php:976 tests/SettingsTest.php:535 220 231 msgid "Squeeze" 221 232 msgstr "" 222 233 223 #: inc/premium/premium.php:2 81234 #: inc/premium/premium.php:299 224 235 msgid "Squeeze images from this page" 225 236 msgstr "Стиснути зображення з цієї сторінки" 226 237 227 #: inc/premium/premium.php: 284238 #: inc/premium/premium.php:302 228 239 msgid "Squeeze images from the current page" 229 240 msgstr "Стиснути зображення з поточної сторінки" 230 241 231 #: inc/premium/premium.php: 294 squeeze.php:279 assets/js/script.bundle.js:29232 #: assets/js/script.js: 848242 #: inc/premium/premium.php:312 squeeze.php:364 assets/js/script.bundle.js:39 243 #: assets/js/script.js:532 233 244 msgid "Settings" 234 245 msgstr "Налаштування" 235 246 236 #: inc/premium/premium.php: 297247 #: inc/premium/premium.php:315 237 248 msgid "Squeeze settings" 238 249 msgstr "Налаштування Squeeze" 239 250 240 #: inc/premium/premium.php:3 54 inc/settings.php:959241 #: assets/js/script.bundle.js: 29 assets/js/script.js:701242 #: assets/js/script.js: 756251 #: inc/premium/premium.php:372 inc/settings.php:1136 252 #: assets/js/script.bundle.js:39 assets/js/script.js:414 253 #: assets/js/script.js:440 243 254 msgid "Squeeze Preview" 244 255 msgstr "Попередній перегляд" 245 256 246 #: inc/settings.php:36 257 #: inc/premium/premium.php:380 258 msgid "File name not found" 259 msgstr "Ім'я файлу не знайдено" 260 261 #: inc/settings.php:37 247 262 msgid "Squeeze Settings" 248 263 msgstr "Налаштування Squeeze" 249 264 250 #: inc/settings.php:47 inc/settings.php:48 squeeze.php:280 265 #: inc/settings.php:48 inc/settings.php:49 squeeze.php:365 266 #: assets/js/admin.bundle.js:19 assets/js/admin.js:184 assets/js/admin.js:256 251 267 msgid "Bulk Squeeze" 252 268 msgstr "Масове стиснення" 253 269 254 #: inc/settings.php:9 1270 #: inc/settings.php:94 255 271 msgid "Bulk Media Library Squeeze" 256 272 msgstr "Масове стиснення зображень із меідатеки" 257 273 258 #: inc/settings.php:108 274 #: inc/settings.php:105 275 msgid "Warning! You have enabled Direct WebP image conversion option." 276 msgstr "Увага! Ви увімкнули опцію прямого перетворення зображень WebP." 277 278 #: inc/settings.php:106 279 msgid "" 280 "All existing JPG/PNG images will be converted to WebP format. Make sure to " 281 "update your existing image URLs accordingly." 282 msgstr "" 283 "Всі існуючі зображення у форматі JPG/PNG будуть конвертовані у формат WebP. " 284 "Переконайтеся, що ви оновили URL-адреси існуючих зображень відповідним чином." 285 286 #: inc/settings.php:126 259 287 msgid "Squeezed images: " 260 288 msgstr "Стиснуті зображення:" 261 289 262 #: inc/settings.php:118 assets/js/helpers.js:136 assets/js/script.bundle.js:19 290 #: inc/settings.php:136 assets/js/admin.bundle.js:39 291 #: assets/js/editor.bundle.js:39 assets/js/helpers.js:139 292 #: assets/js/script.bundle.js:29 263 293 msgid "Run Bulk Squeeze" 264 294 msgstr "Масове стиснення" 265 295 266 #: inc/settings.php:124 assets/js/helpers.js:137 assets/js/script.bundle.js:19 296 #: inc/settings.php:142 assets/js/admin.bundle.js:39 297 #: assets/js/editor.bundle.js:39 assets/js/helpers.js:140 298 #: assets/js/script.bundle.js:29 267 299 msgid "Repeat Bulk Squeeze" 268 300 msgstr "Повторити масове стиснення" 269 301 270 #: inc/settings.php:1 32302 #: inc/settings.php:150 271 303 msgid "Directory Squeeze" 272 304 msgstr "Стиснення каталогів" 273 305 274 #: inc/settings.php:1 40306 #: inc/settings.php:158 275 307 msgid "Warning! Backup option is NOT applicable here." 276 308 msgstr "Увага! Опція резервного копіювання тут НЕ застосовується." 277 309 278 #: inc/settings.php:1 41279 msgid "Please backup your images manually before optimising them."310 #: inc/settings.php:159 311 msgid "Please backup your images manually before squeezing them." 280 312 msgstr "" 281 313 "Будь ласка, створіть резервну копію зображень вручну перед оптимізацією." 282 314 283 #: inc/settings.php:1 47315 #: inc/settings.php:165 284 316 msgid "Directory Path:" 285 317 msgstr "Шлях до каталогу:" 286 318 287 #: inc/settings.php:1 61 inc/settings.php:185319 #: inc/settings.php:186 inc/settings.php:210 288 320 msgid "Select Directory" 289 321 msgstr "Вибрати каталог" 290 322 291 #: inc/settings.php:1 65323 #: inc/settings.php:190 292 324 msgid "Select Directory for Squeeze" 293 325 msgstr "Виберіть каталог для стиснення" 294 326 295 #: inc/settings.php: 177327 #: inc/settings.php:202 296 328 msgid "Loading directories..." 297 329 msgstr "Завантаження каталогів..." 298 330 299 #: inc/settings.php:195 assets/js/helpers.js:138 assets/js/script.bundle.js:19 331 #: inc/settings.php:220 assets/js/admin.bundle.js:39 332 #: assets/js/editor.bundle.js:39 assets/js/helpers.js:141 333 #: assets/js/script.bundle.js:29 300 334 msgid "Run Directory Squeeze" 301 335 msgstr "Стиснення каталогів" 302 336 303 #: inc/settings.php:2 08337 #: inc/settings.php:233 304 338 msgid "Single Page Squeeze" 305 339 msgstr "Стиснення зображень зі сторінки" 306 340 307 #: inc/settings.php:2 28341 #: inc/settings.php:253 308 342 msgid "Fetching images..." 309 343 msgstr "Отримання зображень..." 310 344 311 #: inc/settings.php:2 39345 #: inc/settings.php:264 312 346 msgid "Pause Squeezing" 313 347 msgstr "Призупинити стиснення" 314 348 315 #: inc/settings.php:2 55349 #: inc/settings.php:280 316 350 msgid "Processed formats:" 317 351 msgstr "Формати, що обробляються:" 318 352 319 #: inc/settings.php:2 65353 #: inc/settings.php:290 320 354 msgid "Log will be displayed here" 321 355 msgstr "Тут відображатиметься журнал" 322 356 323 #: inc/settings.php: 291357 #: inc/settings.php:318 324 358 msgid "" 325 359 "The Apache mod_rewrite module is not enabled on your server OR your server " … … 329 363 "сервері не запущено Apache." 330 364 331 #: inc/settings.php: 292365 #: inc/settings.php:319 332 366 msgid "" 333 367 "In order to make WebP serving work, you need to check the \"Replace images " … … 337 371 "URL-адреси зображень\" АБО увімкнути модуль mod_rewrite." 338 372 339 #: inc/settings.php:302 340 msgid "" 341 "The WebP Express plugin is active. Please deactivate in order to use WebP " 342 "serving from Squeeze." 343 msgstr "" 344 "Плагін WebP Express активовано. Будь ласка, деактивуйте його, щоб " 345 "використовувати WebP-сервіс від Squeeze." 346 347 #: inc/settings.php:311 348 msgid "" 349 "The Image Converter for WebP plugin is active. Please deactivate in order to " 350 "use WebP serving from Squeeze." 351 msgstr "" 352 "Плагін Image Converter for WebP активовано. Будь ласка, деактивуйте, щоб " 353 "використовувати WebP-сервіс від Squeeze." 354 355 #: inc/settings.php:321 inc/settings.php:342 inc/settings.php:462 373 #: inc/settings.php:339 inc/settings.php:368 inc/settings.php:544 356 374 msgid "Basic Settings" 357 375 msgstr "Основні налаштування" 358 376 359 #: inc/settings.php:3 22 inc/settings.php:355 inc/settings.php:492377 #: inc/settings.php:340 inc/settings.php:381 inc/settings.php:575 360 378 msgid "JPEG Settings" 361 379 msgstr "Налаштування JPEG" 362 380 363 #: inc/settings.php:3 23 inc/settings.php:379 inc/settings.php:521381 #: inc/settings.php:341 inc/settings.php:405 inc/settings.php:605 364 382 msgid "PNG Settings" 365 383 msgstr "Налаштування PNG" 366 384 367 #: inc/settings.php:3 24 inc/settings.php:392 inc/settings.php:526385 #: inc/settings.php:342 inc/settings.php:418 inc/settings.php:609 368 386 msgid "WEBP Settings" 369 387 msgstr "Налаштування WEBP" 370 388 371 #: inc/settings.php:3 25 inc/settings.php:405 inc/settings.php:533389 #: inc/settings.php:343 inc/settings.php:431 inc/settings.php:616 372 390 msgid "AVIF Settings" 373 391 msgstr "Налаштування AVIF" 374 392 375 #: inc/settings.php:327 inc/settings.php:419 393 #: inc/settings.php:344 inc/settings.php:444 squeeze.php:366 394 msgid "Documentation" 395 msgstr "Документація" 396 397 #: inc/settings.php:346 inc/settings.php:471 376 398 msgid "Upgrade" 377 msgstr "" 378 379 #: inc/settings.php:366 399 msgstr "Преміум тут" 400 401 #: inc/settings.php:352 402 msgid "Your License" 403 msgstr "Ваша ліцензія" 404 405 #: inc/settings.php:392 380 406 msgid "JPEG Advanced Settings" 381 407 msgstr "Розширені налаштування JPEG" 382 408 383 #: inc/settings.php:426 409 #: inc/settings.php:445 410 msgid "Documentation for Squeeze plugin." 411 msgstr "Документація для плагіна Squeeze." 412 413 #: inc/settings.php:455 414 msgid "" 415 "For more information, please visit the <a href=\"%s\" target=\"_blank" 416 "\">official documentation website</a>." 417 msgstr "" 418 "Для отримання додаткової інформації, будь ласка, відвідайте <a href=\"%s\" " 419 "target=\"_blank\">офіційний сайт</a>." 420 421 #: inc/settings.php:478 384 422 msgid "Image Comparison" 385 423 msgstr "Зображення ДО-ПІСЛЯ" 386 424 387 #: inc/settings.php:4 26425 #: inc/settings.php:478 388 426 msgid "Compare original and Squeezed image directly in the Media Library." 389 427 msgstr "Порівняйте оригінал і стиснене зображення безпосередньо в медіатеці." 390 428 391 #: inc/settings.php:4 27429 #: inc/settings.php:479 392 430 msgid "Resize Original Image" 393 431 msgstr "Змінити розмір оригінального зображення" 394 432 395 #: inc/settings.php:4 27433 #: inc/settings.php:479 396 434 msgid "Set maximum width and height for the original image." 397 435 msgstr "Встановіть максимальну ширину та висоту для вихідного зображення." 398 436 399 #: inc/settings.php:4 28437 #: inc/settings.php:480 400 438 msgid "Bulk Squeeze from a Page" 401 439 msgstr "Масове вилучення зі сторінки" 402 440 403 #: inc/settings.php:4 28441 #: inc/settings.php:480 404 442 msgid "Compress all images from a specific page." 405 443 msgstr "Стиснути всі зображення з певної сторінки." 406 444 407 #: inc/settings.php:4 29445 #: inc/settings.php:481 408 446 msgid "Image Exclusion" 409 447 msgstr "Виключення зображення" 410 448 411 #: inc/settings.php:4 29449 #: inc/settings.php:481 412 450 msgid "Exclude specific images from bulk compression." 413 451 msgstr "Виключити певні зображення з масового стиснення." 414 452 415 #: inc/settings.php:447 453 #: inc/settings.php:498 454 msgid "" 455 "To upgrade to the Premium version, <a href=\"%s\" target=\"_blank\">click " 456 "here</a>." 457 msgstr "" 458 "Щоб перейти на Преміум-версію, <a href=\"%s\" target=\"_blank\">натисніть " 459 "тут</a>." 460 461 #: inc/settings.php:516 462 msgid "Your license hasn't been activated" 463 msgstr "Ваша ліцензія не активована" 464 465 #: inc/settings.php:521 466 msgid "" 467 "After you entered your license key, you will receive a confirmation email. " 468 "Pleae click on the confirmation button in that email to complete the opt in." 469 msgstr "" 470 "Після того, як ви введете ліцензійний ключ, ви отримаєте лист з " 471 "підтвердженням. Будь ласка, натисніть на кнопку підтвердження в цьому листі, " 472 "щоб завершити реєстрацію." 473 474 #: inc/settings.php:529 416 475 msgid "Save Changes" 417 476 msgstr "Зберегти зміни" 418 477 419 #: inc/settings.php: 448478 #: inc/settings.php:530 420 479 msgid "Restore defaults" 421 480 msgstr "Відновлення налаштувань за замовчуванням" 422 481 423 #: inc/settings.php: 464482 #: inc/settings.php:546 424 483 msgid "Squeeze on upload" 425 484 msgstr "Стискати при завантаженні" 426 485 427 #: inc/settings.php: 465486 #: inc/settings.php:547 428 487 msgid "Backup original image" 429 488 msgstr "Створити резервну копію оригінального зображення" 430 489 431 #: inc/settings.php: 467490 #: inc/settings.php:549 432 491 msgid "Image formats" 433 492 msgstr "Формати зображення" 434 493 435 #: inc/settings.php: 467494 #: inc/settings.php:549 436 495 msgid "Select which image formats you want to be squeezed." 437 496 msgstr "Оберіть які формати зображень ви хочете стискати." 438 497 439 #: inc/settings.php:469 440 msgid "Generate WEBP" 441 msgstr "Згенерувати WEBP" 442 443 #: inc/settings.php:469 444 msgid "" 445 "Generate and serve WEBP images for all uploaded images. The original image " 446 "URL remains the same, instead the image will be served in a WEBP format." 447 msgstr "" 448 "Створювати і подавати WEBP-зображення для всіх завантажених зображень. URL-" 449 "адреса оригінального зображення залишається незмінною, натомість зображення " 450 "буде подано у форматі WEBP." 451 452 #: inc/settings.php:470 453 msgid "Replace images URLs" 454 msgstr "Замінити URL-адреси зображень" 455 456 #: inc/settings.php:470 457 msgid "" 458 "If the method above does not work, check this option. It replaces original " 459 "URLs of images with the related WEBP images." 460 msgstr "" 461 "Якщо наведений вище метод не працює, увімкніть цю опцію. Це замінить " 462 "оригінальні URL-адреси зображень на відповідні WEBP-зображення." 463 464 #: inc/settings.php:474 498 #: inc/settings.php:551 499 msgid "Direct WebP Conversion" 500 msgstr "Пряме перетворення WebP" 501 502 #: inc/settings.php:551 503 msgid "" 504 "Convert all uploaded images to WEBP format and replace the originals. The " 505 "original JPEG/PNG files are not stored on the server, which reduces disk " 506 "usage." 507 msgstr "" 508 "Конвертувати всі завантажені зображення у формат WEBP і замінити оригінали. " 509 "Оригінальні файли JPEG/PNG не зберігаються на сервері, що зменшує " 510 "використання диска." 511 512 #: inc/settings.php:552 513 msgid "Generate WEBP <br>(legacy method)" 514 msgstr "Згенерувати WEBP <br>(застарілий метод)" 515 516 #: inc/settings.php:552 517 msgid "" 518 "Instead of the original image URL, the image will be served in WEBP format. " 519 "WEBP images are stored in a separate directory: wp-content/squeeze-webp." 520 msgstr "" 521 "Замість оригінальної URL-адреси зображення буде подано у форматі WEBP. WEBP-" 522 "зображення зберігаються в окремому каталозі: wp-content/squeeze-webp." 523 524 #: inc/settings.php:552 525 msgid "" 526 "This is the old method, in case you already have images being converted " 527 "using this approach. Otherwise, it is recommended that you use the direct " 528 "WEBP conversion method above." 529 msgstr "" 530 "Це старий метод, на випадок, якщо у вас вже є зображення, перетворені за " 531 "допомогою цього підходу. В іншому випадку рекомендується використовувати " 532 "метод прямого перетворення WEBP, описаний вище." 533 534 #: inc/settings.php:553 535 msgid "Replace images URLs <br>(legacy method)" 536 msgstr "Замінити URL-адреси зображень <br>(застарілий метод)" 537 538 #: inc/settings.php:553 539 msgid "" 540 "If the method above does not work, try this option. This method replaces the " 541 "original URLs of the images with related WEBP images." 542 msgstr "" 543 "Якщо наведений вище метод не працює, спробуйте цей варіант. Цей метод " 544 "замінює оригінальні URL-адреси зображень на відповідні WEBP-зображення." 545 546 #: inc/settings.php:557 465 547 msgid "CDN URL" 466 msgstr " "467 468 #: inc/settings.php: 474548 msgstr "URL-адреса CDN" 549 550 #: inc/settings.php:557 469 551 msgid "If your site is using CDN, please enter the URL of your CDN here." 470 552 msgstr "" … … 472 554 "CDN." 473 555 474 #: inc/settings.php: 477556 #: inc/settings.php:560 475 557 msgid "Squeeze thumbnails" 476 558 msgstr "Стиснути мініатюри" 477 559 478 #: inc/settings.php: 477560 #: inc/settings.php:560 479 561 msgid "" 480 562 "Choose which image thumbnail sizes you want to squeeze along with the " … … 484 566 "оригінальним зображенням." 485 567 486 #: inc/settings.php: 480 inc/settings.php:484568 #: inc/settings.php:563 inc/settings.php:567 487 569 msgid "Max. image width" 488 570 msgstr "Максимальна ширина зображення" 489 571 490 #: inc/settings.php: 480 inc/settings.php:484572 #: inc/settings.php:563 inc/settings.php:567 491 573 msgid "" 492 574 "Limit a width of an original image. Leave this field empty if you do not " … … 496 578 "не хочете обрізати зображення по ширині." 497 579 498 #: inc/settings.php: 481 inc/settings.php:485580 #: inc/settings.php:564 inc/settings.php:568 499 581 msgid "Max. image height" 500 582 msgstr "Максимальна висота зображення" 501 583 502 #: inc/settings.php: 481 inc/settings.php:485584 #: inc/settings.php:564 inc/settings.php:568 503 585 msgid "" 504 586 "Limit a height of an original image. Leave this field empty if you do not " … … 508 590 "не хочете обрізати зображення по висоті." 509 591 510 #: inc/settings.php: 482 inc/settings.php:486592 #: inc/settings.php:565 inc/settings.php:569 511 593 msgid "Excluded images" 512 594 msgstr "Виключені зображення" 513 595 514 #: inc/settings.php: 482 inc/settings.php:486596 #: inc/settings.php:565 inc/settings.php:569 515 597 msgid "" 516 598 "Enter a list of images that you want to exclude from squeezing. Both full " … … 520 602 "використовувати як повні URL-адреси, так і часткові рядки. Один URL на рядок." 521 603 522 #: inc/settings.php: 489604 #: inc/settings.php:572 523 605 msgid "Squeeze timeout" 524 606 msgstr "Тайм-аут стискання" 525 607 526 #: inc/settings.php: 489608 #: inc/settings.php:572 527 609 msgid "" 528 610 "Time limit for squeezing an image. If you get an error during image " … … 532 614 "стискання зображення, спробуйте збільшити це значення." 533 615 534 #: inc/settings.php:494 inc/settings.php:529 inc/settings.php:535 616 #: inc/settings.php:577 inc/settings.php:607 inc/settings.php:612 617 #: inc/settings.php:618 535 618 msgid "Quality" 536 619 msgstr "Якість" 537 620 538 #: inc/settings.php: 495621 #: inc/settings.php:578 539 622 msgid "Smoothing" 540 623 msgstr "Згладжування" 541 624 542 #: inc/settings.php: 496625 #: inc/settings.php:579 543 626 msgid "Pointless spec compliance" 544 627 msgstr "" 545 628 546 #: inc/settings.php:497 547 msgid "Arithmetic" 548 msgstr "" 549 550 #: inc/settings.php:498 629 #: inc/settings.php:582 551 630 msgid "Progressive rendering" 552 631 msgstr "" 553 632 554 #: inc/settings.php: 499633 #: inc/settings.php:583 555 634 msgid "Optimize Huffman table" 556 635 msgstr "" 557 636 558 #: inc/settings.php:5 00637 #: inc/settings.php:584 559 638 msgid "Channels" 560 639 msgstr "" 561 640 562 #: inc/settings.php:5 01641 #: inc/settings.php:585 563 642 msgid "Quantization" 564 643 msgstr "" 565 644 566 #: inc/settings.php:5 12645 #: inc/settings.php:596 567 646 msgid "Trellis multipass" 568 647 msgstr "" 569 648 570 #: inc/settings.php:5 13649 #: inc/settings.php:597 571 650 msgid "Optimize zero block runs" 572 651 msgstr "" 573 652 574 #: inc/settings.php:5 14653 #: inc/settings.php:598 575 654 msgid "Optimize after trellis quantization" 576 655 msgstr "" 577 656 578 #: inc/settings.php:5 15657 #: inc/settings.php:599 579 658 msgid "Trellis quantization passes" 580 659 msgstr "" 581 660 582 #: inc/settings.php: 516661 #: inc/settings.php:600 583 662 msgid "Auto subsample chroma" 584 663 msgstr "" 585 664 586 #: inc/settings.php: 517665 #: inc/settings.php:601 587 666 msgid "Subsample chroma by" 588 667 msgstr "" 589 668 590 #: inc/settings.php: 518669 #: inc/settings.php:602 591 670 msgid "Separate chroma quality" 592 671 msgstr "" 593 672 594 #: inc/settings.php: 519673 #: inc/settings.php:603 595 674 msgid "Chroma quality" 596 675 msgstr "" 597 676 598 #: inc/settings.php: 523 inc/settings.php:528677 #: inc/settings.php:611 599 678 msgid "Effort" 600 679 msgstr "" 601 680 602 #: inc/settings.php:524 603 msgid "Interlace" 604 msgstr "" 605 606 #: inc/settings.php:530 681 #: inc/settings.php:613 607 682 msgid "Lossless" 608 683 msgstr "" 609 684 610 #: inc/settings.php: 531685 #: inc/settings.php:614 611 686 msgid "Near lossless" 612 687 msgstr "" 613 688 614 #: inc/settings.php: 579689 #: inc/settings.php:664 615 690 msgid "Settings have been updated." 616 691 msgstr "Налаштування було оновлено." 617 692 618 #: inc/settings.php:712 619 msgid "" 620 "This feature is available only in the <a href=\"%s\" target=\"_blank" 621 "\">premium version</a>." 693 #: inc/settings.php:802 694 msgid "" 695 "This feature is available only in the <a href=\"%s\">premium version</a>." 622 696 msgstr "" 623 697 "Ця функція доступна лише в <a href=\"%s\" target=\"_blank\">преміум-версії</" 624 698 "a>." 625 699 626 #: inc/settings.php:721 700 #: inc/settings.php:816 inc/settings.php:839 inc/settings.php:865 701 msgid "Example:" 702 msgstr "Приклад:" 703 704 #: inc/settings.php:819 inc/settings.php:842 705 msgid "Before" 706 msgstr "До" 707 708 #: inc/settings.php:820 inc/settings.php:826 inc/settings.php:844 709 #: inc/settings.php:851 710 msgid "image.jpg" 711 msgstr "" 712 713 #: inc/settings.php:820 inc/settings.php:826 inc/settings.php:844 714 msgid "500 KB" 715 msgstr "" 716 717 #: inc/settings.php:821 inc/settings.php:827 inc/settings.php:845 718 #: inc/settings.php:852 719 msgid "image-100x100.jpg" 720 msgstr "" 721 722 #: inc/settings.php:821 inc/settings.php:827 inc/settings.php:845 723 msgid "98 KB" 724 msgstr "" 725 726 #: inc/settings.php:822 inc/settings.php:828 inc/settings.php:846 727 #: inc/settings.php:853 728 msgid "image-300x300.jpg" 729 msgstr "" 730 731 #: inc/settings.php:822 inc/settings.php:828 inc/settings.php:846 732 msgid "230 KB" 733 msgstr "" 734 735 #: inc/settings.php:825 inc/settings.php:849 736 msgid "After" 737 msgstr "Після" 738 739 #: inc/settings.php:829 inc/settings.php:855 740 msgid "image.webp" 741 msgstr "" 742 743 #: inc/settings.php:829 inc/settings.php:855 744 msgid "50 KB" 745 msgstr "" 746 747 #: inc/settings.php:830 inc/settings.php:856 748 msgid "image-100x100.webp" 749 msgstr "" 750 751 #: inc/settings.php:830 inc/settings.php:856 752 msgid "5 KB" 753 msgstr "" 754 755 #: inc/settings.php:831 inc/settings.php:857 756 msgid "image-300x300.webp" 757 msgstr "" 758 759 #: inc/settings.php:831 inc/settings.php:857 760 msgid "20 KB" 761 msgstr "" 762 763 #: inc/settings.php:843 inc/settings.php:850 764 msgid "/uploads/2025/07/" 765 msgstr "" 766 767 #: inc/settings.php:851 768 msgid "100 KB" 769 msgstr "" 770 771 #: inc/settings.php:852 772 msgid "15 KB" 773 msgstr "" 774 775 #: inc/settings.php:853 776 msgid "40 KB" 777 msgstr "" 778 779 #: inc/settings.php:854 780 msgid "/squeeze-webp/uploads/2025/07/" 781 msgstr "" 782 783 #: inc/settings.php:868 784 msgid "Example image" 785 msgstr "Приклад зображення" 786 787 #: inc/settings.php:880 627 788 msgid "Basic squeezing settings." 628 789 msgstr "Основні налаштування стискання зображень." 629 790 630 #: inc/settings.php: 724791 #: inc/settings.php:883 631 792 msgid "Squeezing settings for JPEG images." 632 793 msgstr "Налаштування для JPEG зображень." 633 794 634 #: inc/settings.php: 727795 #: inc/settings.php:886 635 796 msgid "More precise settings for experienced users." 636 797 msgstr "Більш точні налаштування стиснення для досвідчених користувачів." 637 798 638 #: inc/settings.php: 730799 #: inc/settings.php:889 639 800 msgid "Squeezing settings for PNG images." 640 801 msgstr "Налаштування для PNG зображень." 641 802 642 #: inc/settings.php: 733803 #: inc/settings.php:892 643 804 msgid "Squeezing settings for WebP images." 644 805 msgstr "Налаштування для WebP зображень." 645 806 646 #: inc/settings.php: 736807 #: inc/settings.php:895 647 808 msgid "Squeezing settings for Avif images." 648 809 msgstr "Налаштування для Avif зображень." 649 810 650 #: inc/settings.php: 739811 #: inc/settings.php:898 651 812 msgid "Upgrade to premium version for more features." 652 813 msgstr "Оновіть до преміум-версії, щоб отримати більше функцій." 653 814 654 #: inc/settings.php:748 815 #: inc/settings.php:902 816 msgid "" 817 "To activate your license and manage your account details (e.g. to receive " 818 "security & feature updates notifications), please enter your license key." 819 msgstr "" 820 "Щоб активувати ліцензію та керувати даними свого облікового запису " 821 "(наприклад, отримувати сповіщення про оновлення безпеки та функцій), введіть " 822 "свій ліцензійний ключ." 823 824 #: inc/settings.php:914 825 msgid "Opt In & Connect" 826 msgstr "Зареєструватися та підключитися" 827 828 #: inc/settings.php:925 655 829 msgid "Settings have been restored." 656 830 msgstr "Налаштування відновлено." 657 831 658 #: inc/settings.php: 750832 #: inc/settings.php:927 659 833 msgid "Settings have not been restored." 660 834 msgstr "Налаштування не було відновлено." 661 835 662 #: inc/settings.php: 758836 #: inc/settings.php:935 663 837 msgid "Rewrite rules have been flushed." 664 838 msgstr "Налаштування посилань було оновлено." 665 839 666 #: inc/settings.php: 784840 #: inc/settings.php:961 667 841 msgid "Squeezed" 668 842 msgstr "Стиснутий" 669 843 670 #: inc/settings.php: 785844 #: inc/settings.php:962 671 845 msgid "Restore original" 672 846 msgstr "Відновити оригінальне зображення" 673 847 674 #: inc/settings.php: 786848 #: inc/settings.php:963 675 849 msgid "Squeeze again" 676 850 msgstr "Стиснути знову" 677 851 678 #: inc/settings.php: 788852 #: inc/settings.php:965 679 853 msgid "Not squeezed" 680 854 msgstr "Не стиснутий" 681 855 682 #: inc/settings.php: 869 assets/js/admin.js:161856 #: inc/settings.php:1046 assets/js/admin.bundle.js:19 assets/js/admin.js:163 683 857 msgid "Squeeze: All images" 684 858 msgstr "Squeeze: Усі зображення" 685 859 686 #: inc/settings.php: 870 assets/js/admin.js:169860 #: inc/settings.php:1047 assets/js/admin.bundle.js:19 assets/js/admin.js:171 687 861 msgid "Non Squeezed Images" 688 862 msgstr "Не стиснуті зображення" 689 863 690 #: inc/settings.php: 961 assets/js/script.bundle.js:29 assets/js/script.js:707864 #: inc/settings.php:1138 assets/js/script.bundle.js:39 assets/js/script.js:420 691 865 msgid "(<a href=\"%s\" target=\"_blank\">premium only</a>)" 692 866 msgstr "(<a href=\"%s\" target=\"_blank\">тільки преміум</a>)" 693 867 694 #: assets/js/4240e511ac61ecfff2d8.js:299 868 #: inc/settings.php:1171 869 msgid "" 870 "The WebP Express plugin is active. Please deactivate it in order to use " 871 "correct WebP serving from <strong>Squeeze plugin</strong>." 872 msgstr "" 873 "Плагін WebP Express активний. Будь ласка, вимкніть його, щоб використовувати " 874 "коректне конвертування WebP зображень з <strong>плагіна Squeeze</strong>." 875 876 #: inc/settings.php:1183 877 msgid "" 878 "The Image Converter for WebP plugin is active. Please deactivate it in order " 879 "to use correct WebP serving from <strong>Squeeze plugin</strong>." 880 msgstr "" 881 "Плагін Image Converter for WebP активний. Будь ласка, вимкніть його, щоб " 882 "використовувати коректне конвертування WebP зображень з <strong>плагіна " 883 "Squeeze</strong>." 884 885 #: squeeze.php:186 886 msgid "" 887 "Confirmation email was sent! Please check your inbox to complete the Squeeze " 888 "Premium setup." 889 msgstr "" 890 "Підтвердження відправлено на електронну пошту! Будь ласка, перевірте свою " 891 "поштову скриньку, щоб завершити налаштування Squeeze Premium." 892 893 #: assets/js/4240e511ac61ecfff2d8.js:299 assets/js/admin.bundle.js:49 695 894 #: assets/js/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js:19 696 #: assets/js/script.bundle.js:39 assets/js/squeeze.js:51 895 #: assets/js/editor.bundle.js:49 assets/js/script.bundle.js:49 896 #: assets/js/squeeze.js:65 assets/js/squeeze.js:494 697 897 msgid "Request timed out." 698 898 msgstr "Час очікування запиту минув." 699 899 700 #: assets/js/4240e511ac61ecfff2d8.js:487 900 #: assets/js/4240e511ac61ecfff2d8.js:487 assets/js/admin.bundle.js:49 701 901 #: assets/js/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js:19 702 #: assets/js/script.bundle.js:39 assets/js/squeeze.js:198 902 #: assets/js/editor.bundle.js:49 assets/js/script.bundle.js:49 903 #: assets/js/squeeze.js:248 703 904 msgid "Skipped" 704 905 msgstr "Пропущено" 705 906 706 #: assets/js/helpers.js:107 assets/js/script.bundle.js:19 707 #: assets/js/script.bundle.js:29 assets/js/script.js:50 907 #: assets/js/admin.bundle.js:19 assets/js/admin.js:223 908 msgid "Please select at least one image." 909 msgstr "Будь ласка, виберіть хоча б одне зображення." 910 911 #: assets/js/admin.bundle.js:19 assets/js/admin.bundle.js:29 912 #: assets/js/admin.js:239 assets/js/editor.bundle.js:29 913 #: assets/js/handlers.js:212 assets/js/handlers.js:619 assets/js/handlers 914 #: copy.js:162 copy.js:513 assets/js/script.bundle.js:19 915 #: assets/js/script.bundle.js:39 assets/js/script.js:160 916 #: assets/js/script.js:166 917 msgid "Squeezing..." 918 msgstr "Стискання..." 919 920 #: assets/js/admin.bundle.js:19 assets/js/admin.js:246 921 msgid "All images have been processed." 922 msgstr "Всі зображення були обробленію" 923 924 #: assets/js/admin.bundle.js:19 assets/js/admin.bundle.js:29 925 #: assets/js/admin.js:251 assets/js/editor.bundle.js:29 926 #: assets/js/handlers.js:200 assets/js/handlers.js:420 927 #: assets/js/handlers.js:466 assets/js/handlers copy.js:150 copy.js:431 928 #: copy.js:477 assets/js/script.bundle.js:19 assets/js/script.bundle.js:39 929 #: assets/js/script.js:83 assets/js/script.js:182 930 msgid "An error has occured. Check the console for details." 931 msgstr "Виникла помилка. Перевірте консоль для отримання подробиць." 932 933 #: assets/js/admin.bundle.js:29 assets/js/admin.bundle.js:39 934 #: assets/js/editor.bundle.js:29 assets/js/editor.bundle.js:39 935 #: assets/js/handlers.js:48 assets/js/handlers copy.js:290 936 #: assets/js/helpers.js:110 assets/js/script.bundle.js:19 937 #: assets/js/script.bundle.js:29 938 msgid "Media" 939 msgstr "Медіа" 940 941 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 942 #: assets/js/handlers.js:73 assets/js/handlers.js:275 assets/js/handlers 943 #: copy.js:23 copy.js:225 assets/js/script.bundle.js:19 944 msgid "Resume bulk squeezing" 945 msgstr "Відновити стиснення" 946 947 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 948 #: assets/js/handlers.js:73 assets/js/handlers copy.js:23 949 #: assets/js/script.bundle.js:19 950 msgid "Pause bulk squeezing" 951 msgstr "Призупинити стиснення" 952 953 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 954 #: assets/js/handlers.js:145 assets/js/handlers copy.js:95 955 #: assets/js/script.bundle.js:19 956 msgid "Restore in process..." 957 msgstr "Відновлення в процесі..." 958 959 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 960 #: assets/js/handlers.js:180 assets/js/handlers.js:447 assets/js/handlers 961 #: copy.js:128 copy.js:458 assets/js/script.bundle.js:19 962 #: assets/js/script.bundle.js:39 assets/js/script.js:63 963 msgid "Pausing..." 964 msgstr "Пауза..." 965 966 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 967 #: assets/js/handlers.js:191 assets/js/handlers.js:458 assets/js/handlers 968 #: copy.js:141 copy.js:469 assets/js/script.bundle.js:19 969 #: assets/js/script.bundle.js:39 assets/js/script.js:74 970 msgid "All images have been processed!" 971 msgstr "Всі зображення були оброблені!" 972 973 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 974 #: assets/js/handlers.js:262 assets/js/handlers copy.js:212 975 #: assets/js/script.bundle.js:19 976 msgid "" 977 "Are you sure you want to leave this page? The squeezing process will be " 978 "terminated!" 979 msgstr "" 980 "Ви впевнені, що хочете залишити сторінку? Процесс стиснення зображень буде " 981 "перерваний!" 982 983 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 984 #: assets/js/handlers.js:265 assets/js/handlers copy.js:215 985 #: assets/js/script.bundle.js:19 986 msgid "" 987 "Are you sure you want to leave this page? The settings will not be saved!" 988 msgstr "" 989 "Ви впевнені, що хочете залишити сторінку? Налаштування не будуть збережені!" 990 991 #: assets/js/admin.bundle.js:29 assets/js/admin.bundle.js:39 992 #: assets/js/editor.bundle.js:29 assets/js/editor.bundle.js:39 993 #: assets/js/handlers.js:271 assets/js/handlers copy.js:221 994 #: assets/js/helpers.js:110 assets/js/script.bundle.js:19 995 #: assets/js/script.bundle.js:29 708 996 msgid "Bulk squeezing has been paused!" 709 997 msgstr "Стиснення було зупинене!" 710 998 711 #: assets/js/helpers.js:107 assets/js/script.bundle.js:19 712 msgid "Media" 713 msgstr "Медіа" 714 715 #: assets/js/helpers.js:116 assets/js/helpers.js:120 999 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 1000 #: assets/js/handlers.js:306 assets/js/handlers.js:313 assets/js/handlers 1001 #: copy.js:312 copy.js:320 assets/js/script.bundle.js:19 1002 msgid "No more images found!" 1003 msgstr "Більше зображень не знайдено!" 1004 1005 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 1006 #: assets/js/handlers.js:320 assets/js/handlers copy.js:331 1007 #: assets/js/parallel.js:35 assets/js/script.bundle.js:19 1008 msgid "Start squeezing..." 1009 msgstr "Починаємо стискання..." 1010 1011 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 1012 #: assets/js/handlers.js:407 assets/js/handlers copy.js:420 716 1013 #: assets/js/script.bundle.js:19 1014 msgid "Found images on the page:" 1015 msgstr "Знайдено зображень на сторінці:" 1016 1017 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 1018 #: assets/js/handlers.js:416 assets/js/handlers copy.js:427 1019 #: assets/js/script.bundle.js:19 1020 msgid "Error:" 1021 msgstr "Помилка:" 1022 1023 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 1024 #: assets/js/handlers.js:423 assets/js/handlers.js:426 assets/js/handlers 1025 #: copy.js:434 copy.js:437 assets/js/script.bundle.js:19 1026 msgid "" 1027 "An error has occurred while fetching images from the page. Check the console " 1028 "for details." 1029 msgstr "" 1030 "Виникла помилка під час завантаження зображень зі сторінки. Зверніться до " 1031 "консолі для отримання подробиць." 1032 1033 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 1034 #: assets/js/handlers.js:638 assets/js/script.bundle.js:19 1035 msgid "File is excluded from compression:" 1036 msgstr "Вкладення виключено зі стиснення" 1037 1038 #: assets/js/admin.bundle.js:29 assets/js/editor.bundle.js:29 1039 #: assets/js/handlers.js:647 assets/js/script.bundle.js:19 1040 msgid "File compression failed:" 1041 msgstr "Не вдалося стиснути файл:" 1042 1043 #: assets/js/admin.bundle.js:39 assets/js/editor.bundle.js:39 1044 #: assets/js/helpers.js:119 assets/js/helpers.js:123 1045 #: assets/js/script.bundle.js:29 717 1046 msgid "Show details" 718 1047 msgstr "Показати деталі" 719 1048 720 #: assets/js/helpers.js:120 assets/js/script.bundle.js:19 1049 #: assets/js/admin.bundle.js:39 assets/js/editor.bundle.js:39 1050 #: assets/js/helpers.js:123 assets/js/script.bundle.js:29 721 1051 msgid "Hide details" 722 1052 msgstr "Сховати деталі" 723 1053 724 #: assets/js/helpers.js:183 assets/js/script.bundle.js:19 1054 #: assets/js/admin.bundle.js:39 assets/js/editor.bundle.js:39 1055 #: assets/js/helpers.js:190 assets/js/script.bundle.js:29 725 1056 msgid "No directories found!" 726 1057 msgstr "Каталоги не знайдено!" 727 1058 728 #: assets/js/helpers.js:244 assets/js/script.bundle.js:19 1059 #: assets/js/admin.bundle.js:39 assets/js/editor.bundle.js:39 1060 #: assets/js/helpers.js:266 assets/js/script.bundle.js:29 729 1061 msgid "Error parsing path input!" 730 1062 msgstr "Помилка при обробці шляху до каталогу!" 731 1063 732 #: assets/js/script.bundle.js:29 assets/js/script.js:54 assets/js/script.js:61 733 msgid "Resume bulk squeezing" 734 msgstr "Відновити стиснення" 735 736 #: assets/js/script.bundle.js:29 assets/js/script.js:61 737 msgid "Pause bulk squeezing" 738 msgstr "Призупинити стиснення" 739 740 #: assets/js/script.bundle.js:29 assets/js/script.js:83 741 msgid "" 742 "Are you sure you want to leave this page? The squeezing process will be " 743 "terminated!" 744 msgstr "" 745 "Ви впевнені, що хочете залишити сторінку? Процесс стиснення зображень буде " 746 "перерваний!" 747 748 #: assets/js/script.bundle.js:29 assets/js/script.js:86 749 msgid "" 750 "Are you sure you want to leave this page? The settings will not be saved!" 751 msgstr "" 752 "Ви впевнені, що хочете залишити сторінку? Налаштування не будуть збережені!" 753 754 #: assets/js/script.bundle.js:29 assets/js/script.js:134 755 msgid "Restore in process..." 756 msgstr "Відновлення в процесі..." 757 758 #: assets/js/script.bundle.js:29 assets/js/script.js:156 759 #: assets/js/script.js:433 assets/js/script.js:439 assets/js/script.js:630 760 msgid "Squeezing..." 761 msgstr "Стискання..." 762 763 #: assets/js/script.bundle.js:29 assets/js/script.js:186 764 msgid "Start squeezing..." 765 msgstr "Починаємо стискання..." 766 767 #: assets/js/script.bundle.js:29 assets/js/script.js:273 768 #: assets/js/script.js:340 assets/js/script.js:522 769 msgid "Pausing..." 770 msgstr "Пауза..." 771 772 #: assets/js/script.bundle.js:29 assets/js/script.js:284 773 #: assets/js/script.js:351 assets/js/script.js:533 774 msgid "All images have been processed!" 775 msgstr "Всі зображення були оброблені!" 776 777 #: assets/js/script.bundle.js:29 assets/js/script.js:293 778 #: assets/js/script.js:360 assets/js/script.js:455 assets/js/script.js:495 779 #: assets/js/script.js:541 780 msgid "An error has occured. Check the console for details." 781 msgstr "Виникла помилка. Перевірте консоль для отримання подробиць." 782 783 #: assets/js/script.bundle.js:29 assets/js/script.js:316 1064 #: assets/js/editor.bundle.js:19 assets/js/editor.js:80 1065 #: assets/js/editor__old.js:131 1066 msgid "Squeezing image…" 1067 msgstr "Стискаємо зображення..." 1068 1069 #: assets/js/editor.bundle.js:19 assets/js/editor.js:125 1070 #: assets/js/editor__old.js:30 1071 msgid "Error fetching attachment: %s" 1072 msgstr "Помилка при завантаженні вкладення: %s" 1073 1074 #: assets/js/editor.bundle.js:19 assets/js/editor.js:158 1075 #: assets/js/editor__old.js:60 1076 msgid "Error uploading image: %s" 1077 msgstr "Помилка при завантаженні зображення: %s" 1078 1079 #: assets/js/editor.bundle.js:19 assets/js/editor.js:279 1080 msgid "Squeezing the image..." 1081 msgstr "Стискаємо зображення..." 1082 1083 #: assets/js/editor.bundle.js:19 assets/js/editor.js:342 1084 #: assets/js/editor.js:358 1085 msgid "Error squeezing the image: %s" 1086 msgstr "Помилка при стисканні зображення: %s" 1087 1088 #: assets/js/script.bundle.js:39 assets/js/script.js:37 784 1089 msgid "Please enter a valid path!" 785 1090 msgstr "Будьте ласкаві, введіть коректний шлях до папки!" 786 1091 787 #: assets/js/script.bundle.js:29 assets/js/script.js:484 788 msgid "Found images on the page:" 789 msgstr "Знайдено зображень на сторінці:" 790 791 #: assets/js/script.bundle.js:29 assets/js/script.js:491 792 msgid "Error:" 793 msgstr "Помилка:" 794 795 #: assets/js/script.bundle.js:29 assets/js/script.js:498 796 #: assets/js/script.js:501 797 msgid "" 798 "An error has occurred while fetching images from the page. Check the console " 799 "for details." 800 msgstr "" 801 "Виникла помилка під час завантаження зображень зі сторінки. Зверніться до " 802 "консолі для отримання подробиць." 803 804 #: assets/js/script.bundle.js:29 assets/js/script.js:756 1092 #: assets/js/script.bundle.js:39 assets/js/script.js:440 805 1093 msgid "Loading Preview..." 806 1094 msgstr "Завантаження попереднього перегляду..." 807 1095 808 #: assets/js/script.bundle.js: 29 assets/js/script.js:849809 #: assets/js/script.js: 8921096 #: assets/js/script.bundle.js:39 assets/js/script.js:533 1097 #: assets/js/script.js:576 810 1098 msgid "Collapse" 811 1099 msgstr "Сховати" 812 1100 813 #: assets/js/script.bundle.js: 29 assets/js/script.js:8501101 #: assets/js/script.bundle.js:39 assets/js/script.js:534 814 1102 msgid "Apply" 815 1103 msgstr "Застосувати" 816 1104 817 #: assets/js/script.bundle.js: 29 assets/js/script.js:8651105 #: assets/js/script.bundle.js:39 assets/js/script.js:549 818 1106 msgid "" 819 1107 "An error occurred while rendering the preview. Check the console for details." … … 822 1110 "консолі для отримання подробиць." 823 1111 824 #: assets/js/script.bundle.js: 29 assets/js/script.js:8951112 #: assets/js/script.bundle.js:39 assets/js/script.js:579 825 1113 msgid "Expand" 826 1114 msgstr "Показати" 827 1115 1116 #~ msgid "Generate WEBP" 1117 #~ msgstr "Згенерувати WEBP" 1118 1119 #~ msgid "" 1120 #~ "Generate and serve WEBP images for all uploaded images. The original " 1121 #~ "image URL remains the same, instead the image will be served in a WEBP " 1122 #~ "format." 1123 #~ msgstr "" 1124 #~ "Створювати і подавати WEBP-зображення для всіх завантажених зображень. " 1125 #~ "URL-адреса оригінального зображення залишається незмінною, натомість " 1126 #~ "зображення буде подано у форматі WEBP." 1127 828 1128 #~ msgid "Upload WEBP image failed" 829 1129 #~ msgstr "Не вдалося завантажити WEBP зображення" … … 834 1134 #~ msgid "Attachment not updated" 835 1135 #~ msgstr "Медіафайл не оновлено" 836 837 #~ msgid "Image is excluded from compression"838 #~ msgstr "Вкладення виключено зі стиснення"839 1136 840 1137 #~ msgid "Replace original URLs of images with the related WEBP images." -
squeeze/trunk/languages/squeeze.pot
r3267306 r3345284 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: Squeeze – Image Optimization & Compression, WebP Conversion 1. 6.3\n"5 "Project-Id-Version: Squeeze – Image Optimization & Compression, WebP Conversion 1.7.0\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/squeeze\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 10 10 "Content-Type: text/plain; charset=UTF-8\n" 11 11 "Content-Transfer-Encoding: 8bit\n" 12 "POT-Creation-Date: 2025-0 4-05T18:53:49+00:00\n"12 "POT-Creation-Date: 2025-08-10T11:42:23+00:00\n" 13 13 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 14 "X-Generator: WP-CLI 2.6.0\n" … … 32 32 33 33 #: freemius.php:12 34 #: squeeze.php: 28334 #: squeeze.php:369 35 35 msgid "Go Premium" 36 36 msgstr "" … … 41 41 msgstr "" 42 42 43 #: inc/handlers.php: 3944 #: inc/handlers.php: 17345 #: inc/handlers.php: 22346 #: inc/handlers.php: 63543 #: inc/handlers.php:50 44 #: inc/handlers.php:266 45 #: inc/handlers.php:316 46 #: inc/handlers.php:740 47 47 msgid "You do not have permission to upload files" 48 48 msgstr "" 49 49 50 #: inc/handlers.php: 4351 #: inc/helpers.php: 6050 #: inc/handlers.php:54 51 #: inc/helpers.php:95 52 52 msgid "No image data found" 53 53 msgstr "" 54 54 55 #: inc/handlers.php:56 56 #: inc/handlers.php:60 55 #: inc/handlers.php:68 57 56 msgid "Invalid image format" 58 57 msgstr "" 59 58 60 #: inc/handlers.php: 6961 #: inc/handlers.php: 14962 #: inc/handlers.php: 17759 #: inc/handlers.php:77 60 #: inc/handlers.php:242 61 #: inc/handlers.php:270 63 62 msgid "Attachment not found" 64 63 msgstr "" 65 64 66 #: inc/handlers.php:76 67 #: inc/handlers.php:190 68 #: inc/settings.php:781 69 #: assets/js/script.bundle.js:39 70 #: assets/js/squeeze.js:150 65 #: inc/handlers.php:84 66 #: inc/handlers.php:283 67 #: inc/settings.php:958 68 #: assets/js/admin.bundle.js:49 69 #: assets/js/editor.bundle.js:49 70 #: assets/js/parallel.js:66 71 #: assets/js/script.bundle.js:49 72 #: assets/js/squeeze.js:200 71 73 msgid "Attachment is excluded from compression" 72 74 msgstr "" 73 75 74 #: inc/handlers.php:76 75 #: inc/handlers.php:190 76 #: inc/settings.php:781 77 #: assets/js/script.bundle.js:39 78 #: assets/js/squeeze.js:150 76 #: inc/handlers.php:84 77 #: inc/handlers.php:283 78 #: inc/settings.php:958 79 #: assets/js/admin.bundle.js:49 80 #: assets/js/editor.bundle.js:49 81 #: assets/js/script.bundle.js:49 82 #: assets/js/squeeze.js:200 79 83 msgid "found substring: " 80 84 msgstr "" 81 85 82 #: inc/handlers.php:131 83 #: inc/handlers.php:139 86 #: inc/handlers.php:130 87 msgid "Compressed image size is greater than original size" 88 msgstr "" 89 90 #: inc/handlers.php:214 91 #: inc/handlers.php:232 84 92 msgid "Squeezed successfully" 85 93 msgstr "" 86 94 87 #: inc/handlers.php: 15995 #: inc/handlers.php:252 88 96 msgid "Restored successfully" 89 97 msgstr "" 90 98 91 #: inc/handlers.php: 16199 #: inc/handlers.php:254 92 100 msgid "Attachment not restored" 93 101 msgstr "" 94 102 95 #: inc/handlers.php: 227103 #: inc/handlers.php:320 96 104 msgid "Path not found" 97 105 msgstr "" 98 106 99 #: inc/handlers.php: 299107 #: inc/handlers.php:392 100 108 msgid "Images were not found in the selected directories" 101 109 msgstr "" 102 110 103 #: inc/handlers.php:328 111 #: inc/handlers.php:425 112 #: tests/HandlersTest.php:648 113 #: tests/HandlersTest.php:663 114 #: tests/HandlersTest.php:677 104 115 msgid "Restore Original Image" 105 116 msgstr "" 106 117 107 #: inc/handlers.php:329 118 #: inc/handlers.php:426 119 #: tests/HandlersTest.php:649 120 #: tests/HandlersTest.php:664 121 #: tests/HandlersTest.php:678 108 122 msgid "Squeeze Image" 109 123 msgstr "" 110 124 111 #: inc/handlers.php:330 125 #: inc/handlers.php:427 126 #: tests/HandlersTest.php:650 127 #: tests/HandlersTest.php:665 128 #: tests/HandlersTest.php:679 112 129 msgid "Delete Backup Image" 113 130 msgstr "" 114 131 115 #: inc/handlers.php:331 132 #: inc/handlers.php:428 133 #: tests/HandlersTest.php:651 134 #: tests/HandlersTest.php:666 135 #: tests/HandlersTest.php:680 116 136 msgid "Delete WEBP Image" 117 137 msgstr "" 118 138 119 139 #. translators: %d: number of attachments restored 120 #: inc/handlers.php: 392140 #: inc/handlers.php:489 121 141 msgid "%d attachment restored." 122 142 msgid_plural "%d attachments restored." … … 125 145 126 146 #. translators: %d: number of attachments squeezed 127 #: inc/handlers.php: 405147 #: inc/handlers.php:502 128 148 msgid "%d attachment squeezed." 129 149 msgid_plural "%d attachments squeezed." … … 132 152 133 153 #. translators: %d: number of backup images deleted 134 #: inc/handlers.php: 418154 #: inc/handlers.php:515 135 155 msgid "%d backup image deleted." 136 156 msgid_plural "%d backup images deleted." … … 139 159 140 160 #. translators: %d: number of webp images deleted 141 #: inc/handlers.php: 431161 #: inc/handlers.php:528 142 162 msgid "%d WEBP image deleted." 143 163 msgid_plural "%d WEBP images deleted." … … 145 165 msgstr[1] "" 146 166 147 #: inc/handlers.php: 474167 #: inc/handlers.php:576 148 168 msgid "Single file upload is not supported for the image compression by Squeeze. Please use multi-file uploader or bulk squeeze." 149 169 msgstr "" 150 170 151 #: inc/handlers.php: 641171 #: inc/handlers.php:746 152 172 msgid "Options not found" 153 173 msgstr "" 154 174 155 #: inc/handlers.php: 647175 #: inc/handlers.php:752 156 176 msgid "Options not saved" 157 177 msgstr "" 158 178 159 #: inc/handlers.php: 650179 #: inc/handlers.php:755 160 180 msgid "Options saved successfully" 161 181 msgstr "" 162 182 163 #: inc/helpers.php: 29183 #: inc/helpers.php:54 164 184 msgid "Backup original image failed" 165 185 msgstr "" 166 186 167 #: inc/helpers.php: 52168 #: inc/helpers.php: 81187 #: inc/helpers.php:87 188 #: inc/helpers.php:155 169 189 msgid "Upload image failed" 170 190 msgstr "" 171 191 172 #: inc/helpers.php: 91173 #: inc/helpers.php:1 07192 #: inc/helpers.php:165 193 #: inc/helpers.php:181 174 194 msgid "No WebP data found" 175 195 msgstr "" 176 196 177 #: inc/helpers.php: 145197 #: inc/helpers.php:253 178 198 msgid "Backup image not found" 179 199 msgstr "" 180 200 181 #: inc/helpers.php: 156201 #: inc/helpers.php:264 182 202 msgid "Restore original image failed" 183 203 msgstr "" 184 204 185 #: inc/helpers.php: 232205 #: inc/helpers.php:341 186 206 msgid "Size Name" 187 207 msgstr "" 188 208 189 #: inc/helpers.php: 232209 #: inc/helpers.php:341 190 210 msgid "Original Size" 191 211 msgstr "" 192 212 193 #: inc/helpers.php: 232213 #: inc/helpers.php:341 194 214 msgid "Squeezed Size" 195 215 msgstr "" 196 216 197 #: inc/helpers.php: 232217 #: inc/helpers.php:341 198 218 msgid "Savings" 199 219 msgstr "" 200 220 201 #: inc/premium/premium.php:2 1221 #: inc/premium/premium.php:22 202 222 msgid "Page URL not found" 203 223 msgstr "" 204 224 205 #: inc/premium/premium.php:3 7225 #: inc/premium/premium.php:38 206 226 msgid "URL is not from the same domain" 207 227 msgstr "" 208 228 209 #: inc/premium/premium.php:4 7229 #: inc/premium/premium.php:48 210 230 msgid "Error fetching the page:" 211 231 msgstr "" 212 232 213 #: inc/premium/premium.php: 196214 #: inc/premium/premium.php:2 00233 #: inc/premium/premium.php:209 234 #: inc/premium/premium.php:213 215 235 msgid "No images found on the page" 216 236 msgstr "" 217 237 218 #: inc/premium/premium.php:271 238 #: inc/premium/premium.php:289 239 #: inc/settings.php:38 240 #: inc/settings.php:955 241 #: inc/settings.php:966 242 #: inc/settings.php:976 243 #: tests/SettingsTest.php:535 244 msgid "Squeeze" 245 msgstr "" 246 247 #: inc/premium/premium.php:299 248 msgid "Squeeze images from this page" 249 msgstr "" 250 251 #: inc/premium/premium.php:302 252 msgid "Squeeze images from the current page" 253 msgstr "" 254 255 #: inc/premium/premium.php:312 256 #: squeeze.php:364 257 #: assets/js/script.bundle.js:39 258 #: assets/js/script.js:532 259 msgid "Settings" 260 msgstr "" 261 262 #: inc/premium/premium.php:315 263 msgid "Squeeze settings" 264 msgstr "" 265 266 #: inc/premium/premium.php:372 267 #: inc/settings.php:1136 268 #: assets/js/script.bundle.js:39 269 #: assets/js/script.js:414 270 #: assets/js/script.js:440 271 msgid "Squeeze Preview" 272 msgstr "" 273 274 #: inc/premium/premium.php:380 275 msgid "File name not found" 276 msgstr "" 277 219 278 #: inc/settings.php:37 220 #: inc/settings.php:778 221 #: inc/settings.php:789 222 #: inc/settings.php:799 223 msgid "Squeeze" 224 msgstr "" 225 226 #: inc/premium/premium.php:281 227 msgid "Squeeze images from this page" 228 msgstr "" 229 230 #: inc/premium/premium.php:284 231 msgid "Squeeze images from the current page" 232 msgstr "" 233 234 #: inc/premium/premium.php:294 235 #: squeeze.php:279 279 msgid "Squeeze Settings" 280 msgstr "" 281 282 #: inc/settings.php:48 283 #: inc/settings.php:49 284 #: squeeze.php:365 285 #: assets/js/admin.bundle.js:19 286 #: assets/js/admin.js:184 287 #: assets/js/admin.js:256 288 msgid "Bulk Squeeze" 289 msgstr "" 290 291 #: inc/settings.php:94 292 msgid "Bulk Media Library Squeeze" 293 msgstr "" 294 295 #: inc/settings.php:105 296 msgid "Warning! You have enabled Direct WebP image conversion option." 297 msgstr "" 298 299 #: inc/settings.php:106 300 msgid "All existing JPG/PNG images will be converted to WebP format. Make sure to update your existing image URLs accordingly." 301 msgstr "" 302 303 #: inc/settings.php:126 304 msgid "Squeezed images: " 305 msgstr "" 306 307 #: inc/settings.php:136 308 #: assets/js/admin.bundle.js:39 309 #: assets/js/editor.bundle.js:39 310 #: assets/js/helpers.js:139 236 311 #: assets/js/script.bundle.js:29 237 #: assets/js/script.js:848 238 msgid "Settings" 239 msgstr "" 240 241 #: inc/premium/premium.php:297 242 msgid "Squeeze settings" 243 msgstr "" 244 245 #: inc/premium/premium.php:354 246 #: inc/settings.php:959 312 msgid "Run Bulk Squeeze" 313 msgstr "" 314 315 #: inc/settings.php:142 316 #: assets/js/admin.bundle.js:39 317 #: assets/js/editor.bundle.js:39 318 #: assets/js/helpers.js:140 247 319 #: assets/js/script.bundle.js:29 248 #: assets/js/script.js:701249 #: assets/js/script.js:756250 msgid "Squeeze Preview"251 msgstr ""252 253 #: inc/settings.php:36254 msgid "Squeeze Settings"255 msgstr ""256 257 #: inc/settings.php:47258 #: inc/settings.php:48259 #: squeeze.php:280260 msgid "Bulk Squeeze"261 msgstr ""262 263 #: inc/settings.php:91264 msgid "Bulk Media Library Squeeze"265 msgstr ""266 267 #: inc/settings.php:108268 msgid "Squeezed images: "269 msgstr ""270 271 #: inc/settings.php:118272 #: assets/js/helpers.js:136273 #: assets/js/script.bundle.js:19274 msgid "Run Bulk Squeeze"275 msgstr ""276 277 #: inc/settings.php:124278 #: assets/js/helpers.js:137279 #: assets/js/script.bundle.js:19280 320 msgid "Repeat Bulk Squeeze" 281 321 msgstr "" 282 322 283 #: inc/settings.php:1 32323 #: inc/settings.php:150 284 324 msgid "Directory Squeeze" 285 325 msgstr "" 286 326 287 #: inc/settings.php:1 40327 #: inc/settings.php:158 288 328 msgid "Warning! Backup option is NOT applicable here." 289 329 msgstr "" 290 330 291 #: inc/settings.php:1 41292 msgid "Please backup your images manually before optimising them."293 msgstr "" 294 295 #: inc/settings.php:1 47331 #: inc/settings.php:159 332 msgid "Please backup your images manually before squeezing them." 333 msgstr "" 334 335 #: inc/settings.php:165 296 336 msgid "Directory Path:" 297 337 msgstr "" 298 338 299 #: inc/settings.php:1 61300 #: inc/settings.php: 185339 #: inc/settings.php:186 340 #: inc/settings.php:210 301 341 msgid "Select Directory" 302 342 msgstr "" 303 343 304 #: inc/settings.php:1 65344 #: inc/settings.php:190 305 345 msgid "Select Directory for Squeeze" 306 346 msgstr "" 307 347 308 #: inc/settings.php: 177348 #: inc/settings.php:202 309 349 msgid "Loading directories..." 310 350 msgstr "" 311 351 312 #: inc/settings.php:195 313 #: assets/js/helpers.js:138 314 #: assets/js/script.bundle.js:19 352 #: inc/settings.php:220 353 #: assets/js/admin.bundle.js:39 354 #: assets/js/editor.bundle.js:39 355 #: assets/js/helpers.js:141 356 #: assets/js/script.bundle.js:29 315 357 msgid "Run Directory Squeeze" 316 358 msgstr "" 317 359 318 #: inc/settings.php:2 08360 #: inc/settings.php:233 319 361 msgid "Single Page Squeeze" 320 362 msgstr "" 321 363 322 #: inc/settings.php:2 28364 #: inc/settings.php:253 323 365 msgid "Fetching images..." 324 366 msgstr "" 325 367 326 #: inc/settings.php:2 39368 #: inc/settings.php:264 327 369 msgid "Pause Squeezing" 328 370 msgstr "" 329 371 330 #: inc/settings.php:2 55372 #: inc/settings.php:280 331 373 msgid "Processed formats:" 332 374 msgstr "" 333 375 334 #: inc/settings.php:2 65376 #: inc/settings.php:290 335 377 msgid "Log will be displayed here" 336 378 msgstr "" 337 379 338 #: inc/settings.php: 291380 #: inc/settings.php:318 339 381 msgid "The Apache mod_rewrite module is not enabled on your server OR your server is not running Apache." 340 382 msgstr "" 341 383 342 #: inc/settings.php: 292384 #: inc/settings.php:319 343 385 msgid "In order to make WebP serving work, you need to check the \"Replace images URLs\" option OR enable the mod_rewrite module." 344 386 msgstr "" 345 387 346 #: inc/settings.php:302 347 msgid "The WebP Express plugin is active. Please deactivate in order to use WebP serving from Squeeze." 348 msgstr "" 349 350 #: inc/settings.php:311 351 msgid "The Image Converter for WebP plugin is active. Please deactivate in order to use WebP serving from Squeeze." 352 msgstr "" 353 354 #: inc/settings.php:321 388 #: inc/settings.php:339 389 #: inc/settings.php:368 390 #: inc/settings.php:544 391 msgid "Basic Settings" 392 msgstr "" 393 394 #: inc/settings.php:340 395 #: inc/settings.php:381 396 #: inc/settings.php:575 397 msgid "JPEG Settings" 398 msgstr "" 399 400 #: inc/settings.php:341 401 #: inc/settings.php:405 402 #: inc/settings.php:605 403 msgid "PNG Settings" 404 msgstr "" 405 355 406 #: inc/settings.php:342 356 #: inc/settings.php:462 357 msgid "Basic Settings" 358 msgstr "" 359 360 #: inc/settings.php:322 361 #: inc/settings.php:355 362 #: inc/settings.php:492 363 msgid "JPEG Settings" 364 msgstr "" 365 366 #: inc/settings.php:323 367 #: inc/settings.php:379 407 #: inc/settings.php:418 408 #: inc/settings.php:609 409 msgid "WEBP Settings" 410 msgstr "" 411 412 #: inc/settings.php:343 413 #: inc/settings.php:431 414 #: inc/settings.php:616 415 msgid "AVIF Settings" 416 msgstr "" 417 418 #: inc/settings.php:344 419 #: inc/settings.php:444 420 #: squeeze.php:366 421 msgid "Documentation" 422 msgstr "" 423 424 #: inc/settings.php:346 425 #: inc/settings.php:471 426 msgid "Upgrade" 427 msgstr "" 428 429 #: inc/settings.php:352 430 msgid "Your License" 431 msgstr "" 432 433 #: inc/settings.php:392 434 msgid "JPEG Advanced Settings" 435 msgstr "" 436 437 #: inc/settings.php:445 438 msgid "Documentation for Squeeze plugin." 439 msgstr "" 440 441 #: inc/settings.php:455 442 msgid "For more information, please visit the <a href=\"%s\" target=\"_blank\">official documentation website</a>." 443 msgstr "" 444 445 #: inc/settings.php:478 446 msgid "Image Comparison" 447 msgstr "" 448 449 #: inc/settings.php:478 450 msgid "Compare original and Squeezed image directly in the Media Library." 451 msgstr "" 452 453 #: inc/settings.php:479 454 msgid "Resize Original Image" 455 msgstr "" 456 457 #: inc/settings.php:479 458 msgid "Set maximum width and height for the original image." 459 msgstr "" 460 461 #: inc/settings.php:480 462 msgid "Bulk Squeeze from a Page" 463 msgstr "" 464 465 #: inc/settings.php:480 466 msgid "Compress all images from a specific page." 467 msgstr "" 468 469 #: inc/settings.php:481 470 msgid "Image Exclusion" 471 msgstr "" 472 473 #: inc/settings.php:481 474 msgid "Exclude specific images from bulk compression." 475 msgstr "" 476 477 #: inc/settings.php:498 478 msgid "To upgrade to the Premium version, <a href=\"%s\" target=\"_blank\">click here</a>." 479 msgstr "" 480 481 #: inc/settings.php:516 482 msgid "Your license hasn't been activated" 483 msgstr "" 484 368 485 #: inc/settings.php:521 369 msgid "PNG Settings" 370 msgstr "" 371 372 #: inc/settings.php:324 373 #: inc/settings.php:392 374 #: inc/settings.php:526 375 msgid "WEBP Settings" 376 msgstr "" 377 378 #: inc/settings.php:325 379 #: inc/settings.php:405 380 #: inc/settings.php:533 381 msgid "AVIF Settings" 382 msgstr "" 383 384 #: inc/settings.php:327 385 #: inc/settings.php:419 386 msgid "Upgrade" 387 msgstr "" 388 389 #: inc/settings.php:366 390 msgid "JPEG Advanced Settings" 391 msgstr "" 392 393 #: inc/settings.php:426 394 msgid "Image Comparison" 395 msgstr "" 396 397 #: inc/settings.php:426 398 msgid "Compare original and Squeezed image directly in the Media Library." 399 msgstr "" 400 401 #: inc/settings.php:427 402 msgid "Resize Original Image" 403 msgstr "" 404 405 #: inc/settings.php:427 406 msgid "Set maximum width and height for the original image." 407 msgstr "" 408 409 #: inc/settings.php:428 410 msgid "Bulk Squeeze from a Page" 411 msgstr "" 412 413 #: inc/settings.php:428 414 msgid "Compress all images from a specific page." 415 msgstr "" 416 417 #: inc/settings.php:429 418 msgid "Image Exclusion" 419 msgstr "" 420 421 #: inc/settings.php:429 422 msgid "Exclude specific images from bulk compression." 423 msgstr "" 424 425 #: inc/settings.php:447 486 msgid "After you entered your license key, you will receive a confirmation email. Pleae click on the confirmation button in that email to complete the opt in." 487 msgstr "" 488 489 #: inc/settings.php:529 426 490 msgid "Save Changes" 427 491 msgstr "" 428 492 429 #: inc/settings.php: 448493 #: inc/settings.php:530 430 494 msgid "Restore defaults" 431 495 msgstr "" 432 496 433 #: inc/settings.php: 464497 #: inc/settings.php:546 434 498 msgid "Squeeze on upload" 435 499 msgstr "" 436 500 437 #: inc/settings.php: 465501 #: inc/settings.php:547 438 502 msgid "Backup original image" 439 503 msgstr "" 440 504 441 #: inc/settings.php: 467505 #: inc/settings.php:549 442 506 msgid "Image formats" 443 507 msgstr "" 444 508 445 #: inc/settings.php: 467509 #: inc/settings.php:549 446 510 msgid "Select which image formats you want to be squeezed." 447 511 msgstr "" 448 512 449 #: inc/settings.php:469 450 msgid "Generate WEBP" 451 msgstr "" 452 453 #: inc/settings.php:469 454 msgid "Generate and serve WEBP images for all uploaded images. The original image URL remains the same, instead the image will be served in a WEBP format." 455 msgstr "" 456 457 #: inc/settings.php:470 458 msgid "Replace images URLs" 459 msgstr "" 460 461 #: inc/settings.php:470 462 msgid "If the method above does not work, check this option. It replaces original URLs of images with the related WEBP images." 463 msgstr "" 464 465 #: inc/settings.php:474 513 #: inc/settings.php:551 514 msgid "Direct WebP Conversion" 515 msgstr "" 516 517 #: inc/settings.php:551 518 msgid "Convert all uploaded images to WEBP format and replace the originals. The original JPEG/PNG files are not stored on the server, which reduces disk usage." 519 msgstr "" 520 521 #: inc/settings.php:552 522 msgid "Generate WEBP <br>(legacy method)" 523 msgstr "" 524 525 #: inc/settings.php:552 526 msgid "Instead of the original image URL, the image will be served in WEBP format. WEBP images are stored in a separate directory: wp-content/squeeze-webp." 527 msgstr "" 528 529 #: inc/settings.php:552 530 msgid "This is the old method, in case you already have images being converted using this approach. Otherwise, it is recommended that you use the direct WEBP conversion method above." 531 msgstr "" 532 533 #: inc/settings.php:553 534 msgid "Replace images URLs <br>(legacy method)" 535 msgstr "" 536 537 #: inc/settings.php:553 538 msgid "If the method above does not work, try this option. This method replaces the original URLs of the images with related WEBP images." 539 msgstr "" 540 541 #: inc/settings.php:557 466 542 msgid "CDN URL" 467 543 msgstr "" 468 544 469 #: inc/settings.php: 474545 #: inc/settings.php:557 470 546 msgid "If your site is using CDN, please enter the URL of your CDN here." 471 547 msgstr "" 472 548 473 #: inc/settings.php: 477549 #: inc/settings.php:560 474 550 msgid "Squeeze thumbnails" 475 551 msgstr "" 476 552 477 #: inc/settings.php: 477553 #: inc/settings.php:560 478 554 msgid "Choose which image thumbnail sizes you want to squeeze along with the original image." 479 555 msgstr "" 480 556 481 #: inc/settings.php: 480482 #: inc/settings.php: 484557 #: inc/settings.php:563 558 #: inc/settings.php:567 483 559 msgid "Max. image width" 484 560 msgstr "" 485 561 486 #: inc/settings.php: 480487 #: inc/settings.php: 484562 #: inc/settings.php:563 563 #: inc/settings.php:567 488 564 msgid "Limit a width of an original image. Leave this field empty if you do not want to crop the image by width." 489 565 msgstr "" 490 566 491 #: inc/settings.php: 481492 #: inc/settings.php: 485567 #: inc/settings.php:564 568 #: inc/settings.php:568 493 569 msgid "Max. image height" 494 570 msgstr "" 495 571 496 #: inc/settings.php: 481497 #: inc/settings.php: 485572 #: inc/settings.php:564 573 #: inc/settings.php:568 498 574 msgid "Limit a height of an original image. Leave this field empty if you do not want to crop the image by height." 499 575 msgstr "" 500 576 501 #: inc/settings.php: 482502 #: inc/settings.php: 486577 #: inc/settings.php:565 578 #: inc/settings.php:569 503 579 msgid "Excluded images" 504 580 msgstr "" 505 581 506 #: inc/settings.php: 482507 #: inc/settings.php: 486582 #: inc/settings.php:565 583 #: inc/settings.php:569 508 584 msgid "Enter a list of images that you want to exclude from squeezing. Both full URLs and partial strings can be used. One URL per line." 509 585 msgstr "" 510 586 511 #: inc/settings.php: 489587 #: inc/settings.php:572 512 588 msgid "Squeeze timeout" 513 589 msgstr "" 514 590 515 #: inc/settings.php: 489591 #: inc/settings.php:572 516 592 msgid "Time limit for squeezing an image. If you get an error during image squeezing, try to increase this value." 517 593 msgstr "" 518 594 519 #: inc/settings.php:494 520 #: inc/settings.php:529 521 #: inc/settings.php:535 595 #: inc/settings.php:577 596 #: inc/settings.php:607 597 #: inc/settings.php:612 598 #: inc/settings.php:618 522 599 msgid "Quality" 523 600 msgstr "" 524 601 525 #: inc/settings.php: 495602 #: inc/settings.php:578 526 603 msgid "Smoothing" 527 604 msgstr "" 528 605 529 #: inc/settings.php: 496606 #: inc/settings.php:579 530 607 msgid "Pointless spec compliance" 531 608 msgstr "" 532 609 533 #: inc/settings.php:497 534 msgid "Arithmetic" 535 msgstr "" 536 537 #: inc/settings.php:498 610 #: inc/settings.php:582 538 611 msgid "Progressive rendering" 539 612 msgstr "" 540 613 541 #: inc/settings.php: 499614 #: inc/settings.php:583 542 615 msgid "Optimize Huffman table" 543 616 msgstr "" 544 617 545 #: inc/settings.php:5 00618 #: inc/settings.php:584 546 619 msgid "Channels" 547 620 msgstr "" 548 621 549 #: inc/settings.php:5 01622 #: inc/settings.php:585 550 623 msgid "Quantization" 551 624 msgstr "" 552 625 553 #: inc/settings.php:5 12626 #: inc/settings.php:596 554 627 msgid "Trellis multipass" 555 628 msgstr "" 556 629 557 #: inc/settings.php:5 13630 #: inc/settings.php:597 558 631 msgid "Optimize zero block runs" 559 632 msgstr "" 560 633 561 #: inc/settings.php:5 14634 #: inc/settings.php:598 562 635 msgid "Optimize after trellis quantization" 563 636 msgstr "" 564 637 565 #: inc/settings.php:5 15638 #: inc/settings.php:599 566 639 msgid "Trellis quantization passes" 567 640 msgstr "" 568 641 569 #: inc/settings.php: 516642 #: inc/settings.php:600 570 643 msgid "Auto subsample chroma" 571 644 msgstr "" 572 645 573 #: inc/settings.php: 517646 #: inc/settings.php:601 574 647 msgid "Subsample chroma by" 575 648 msgstr "" 576 649 577 #: inc/settings.php: 518650 #: inc/settings.php:602 578 651 msgid "Separate chroma quality" 579 652 msgstr "" 580 653 581 #: inc/settings.php: 519654 #: inc/settings.php:603 582 655 msgid "Chroma quality" 583 656 msgstr "" 584 657 585 #: inc/settings.php:523 586 #: inc/settings.php:528 658 #: inc/settings.php:611 587 659 msgid "Effort" 588 660 msgstr "" 589 661 590 #: inc/settings.php:524 591 msgid "Interlace" 592 msgstr "" 593 594 #: inc/settings.php:530 662 #: inc/settings.php:613 595 663 msgid "Lossless" 596 664 msgstr "" 597 665 598 #: inc/settings.php: 531666 #: inc/settings.php:614 599 667 msgid "Near lossless" 600 668 msgstr "" 601 669 602 #: inc/settings.php: 579670 #: inc/settings.php:664 603 671 msgid "Settings have been updated." 604 672 msgstr "" 605 673 606 #: inc/settings.php:712 607 msgid "This feature is available only in the <a href=\"%s\" target=\"_blank\">premium version</a>." 608 msgstr "" 609 610 #: inc/settings.php:721 674 #: inc/settings.php:802 675 msgid "This feature is available only in the <a href=\"%s\">premium version</a>." 676 msgstr "" 677 678 #: inc/settings.php:816 679 #: inc/settings.php:839 680 #: inc/settings.php:865 681 msgid "Example:" 682 msgstr "" 683 684 #: inc/settings.php:819 685 #: inc/settings.php:842 686 msgid "Before" 687 msgstr "" 688 689 #: inc/settings.php:820 690 #: inc/settings.php:826 691 #: inc/settings.php:844 692 #: inc/settings.php:851 693 msgid "image.jpg" 694 msgstr "" 695 696 #: inc/settings.php:820 697 #: inc/settings.php:826 698 #: inc/settings.php:844 699 msgid "500 KB" 700 msgstr "" 701 702 #: inc/settings.php:821 703 #: inc/settings.php:827 704 #: inc/settings.php:845 705 #: inc/settings.php:852 706 msgid "image-100x100.jpg" 707 msgstr "" 708 709 #: inc/settings.php:821 710 #: inc/settings.php:827 711 #: inc/settings.php:845 712 msgid "98 KB" 713 msgstr "" 714 715 #: inc/settings.php:822 716 #: inc/settings.php:828 717 #: inc/settings.php:846 718 #: inc/settings.php:853 719 msgid "image-300x300.jpg" 720 msgstr "" 721 722 #: inc/settings.php:822 723 #: inc/settings.php:828 724 #: inc/settings.php:846 725 msgid "230 KB" 726 msgstr "" 727 728 #: inc/settings.php:825 729 #: inc/settings.php:849 730 msgid "After" 731 msgstr "" 732 733 #: inc/settings.php:829 734 #: inc/settings.php:855 735 msgid "image.webp" 736 msgstr "" 737 738 #: inc/settings.php:829 739 #: inc/settings.php:855 740 msgid "50 KB" 741 msgstr "" 742 743 #: inc/settings.php:830 744 #: inc/settings.php:856 745 msgid "image-100x100.webp" 746 msgstr "" 747 748 #: inc/settings.php:830 749 #: inc/settings.php:856 750 msgid "5 KB" 751 msgstr "" 752 753 #: inc/settings.php:831 754 #: inc/settings.php:857 755 msgid "image-300x300.webp" 756 msgstr "" 757 758 #: inc/settings.php:831 759 #: inc/settings.php:857 760 msgid "20 KB" 761 msgstr "" 762 763 #: inc/settings.php:843 764 #: inc/settings.php:850 765 msgid "/uploads/2025/07/" 766 msgstr "" 767 768 #: inc/settings.php:851 769 msgid "100 KB" 770 msgstr "" 771 772 #: inc/settings.php:852 773 msgid "15 KB" 774 msgstr "" 775 776 #: inc/settings.php:853 777 msgid "40 KB" 778 msgstr "" 779 780 #: inc/settings.php:854 781 msgid "/squeeze-webp/uploads/2025/07/" 782 msgstr "" 783 784 #: inc/settings.php:868 785 msgid "Example image" 786 msgstr "" 787 788 #: inc/settings.php:880 611 789 msgid "Basic squeezing settings." 612 790 msgstr "" 613 791 614 #: inc/settings.php: 724792 #: inc/settings.php:883 615 793 msgid "Squeezing settings for JPEG images." 616 794 msgstr "" 617 795 618 #: inc/settings.php: 727796 #: inc/settings.php:886 619 797 msgid "More precise settings for experienced users." 620 798 msgstr "" 621 799 622 #: inc/settings.php: 730800 #: inc/settings.php:889 623 801 msgid "Squeezing settings for PNG images." 624 802 msgstr "" 625 803 626 #: inc/settings.php: 733804 #: inc/settings.php:892 627 805 msgid "Squeezing settings for WebP images." 628 806 msgstr "" 629 807 630 #: inc/settings.php: 736808 #: inc/settings.php:895 631 809 msgid "Squeezing settings for Avif images." 632 810 msgstr "" 633 811 634 #: inc/settings.php: 739812 #: inc/settings.php:898 635 813 msgid "Upgrade to premium version for more features." 636 814 msgstr "" 637 815 638 #: inc/settings.php:748 816 #: inc/settings.php:902 817 msgid "To activate your license and manage your account details (e.g. to receive security & feature updates notifications), please enter your license key." 818 msgstr "" 819 820 #: inc/settings.php:914 821 msgid "Opt In & Connect" 822 msgstr "" 823 824 #: inc/settings.php:925 639 825 msgid "Settings have been restored." 640 826 msgstr "" 641 827 642 #: inc/settings.php: 750828 #: inc/settings.php:927 643 829 msgid "Settings have not been restored." 644 830 msgstr "" 645 831 646 #: inc/settings.php: 758832 #: inc/settings.php:935 647 833 msgid "Rewrite rules have been flushed." 648 834 msgstr "" 649 835 650 #: inc/settings.php: 784836 #: inc/settings.php:961 651 837 msgid "Squeezed" 652 838 msgstr "" 653 839 654 #: inc/settings.php: 785840 #: inc/settings.php:962 655 841 msgid "Restore original" 656 842 msgstr "" 657 843 658 #: inc/settings.php: 786844 #: inc/settings.php:963 659 845 msgid "Squeeze again" 660 846 msgstr "" 661 847 662 #: inc/settings.php: 788848 #: inc/settings.php:965 663 849 msgid "Not squeezed" 664 850 msgstr "" 665 851 666 #: inc/settings.php:869 667 #: assets/js/admin.js:161 852 #: inc/settings.php:1046 853 #: assets/js/admin.bundle.js:19 854 #: assets/js/admin.js:163 668 855 msgid "Squeeze: All images" 669 856 msgstr "" 670 857 671 #: inc/settings.php:870 672 #: assets/js/admin.js:169 858 #: inc/settings.php:1047 859 #: assets/js/admin.bundle.js:19 860 #: assets/js/admin.js:171 673 861 msgid "Non Squeezed Images" 674 862 msgstr "" 675 863 676 #: inc/settings.php:961 864 #: inc/settings.php:1138 865 #: assets/js/script.bundle.js:39 866 #: assets/js/script.js:420 867 msgid "(<a href=\"%s\" target=\"_blank\">premium only</a>)" 868 msgstr "" 869 870 #: inc/settings.php:1171 871 msgid "The WebP Express plugin is active. Please deactivate it in order to use correct WebP serving from <strong>Squeeze plugin</strong>." 872 msgstr "" 873 874 #: inc/settings.php:1183 875 msgid "The Image Converter for WebP plugin is active. Please deactivate it in order to use correct WebP serving from <strong>Squeeze plugin</strong>." 876 msgstr "" 877 878 #: squeeze.php:186 879 msgid "Confirmation email was sent! Please check your inbox to complete the Squeeze Premium setup." 880 msgstr "" 881 882 #: assets/js/4240e511ac61ecfff2d8.js:299 883 #: assets/js/admin.bundle.js:49 884 #: assets/js/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js:19 885 #: assets/js/editor.bundle.js:49 886 #: assets/js/script.bundle.js:49 887 #: assets/js/squeeze.js:65 888 #: assets/js/squeeze.js:494 889 msgid "Request timed out." 890 msgstr "" 891 892 #: assets/js/4240e511ac61ecfff2d8.js:487 893 #: assets/js/admin.bundle.js:49 894 #: assets/js/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js:19 895 #: assets/js/editor.bundle.js:49 896 #: assets/js/script.bundle.js:49 897 #: assets/js/squeeze.js:248 898 msgid "Skipped" 899 msgstr "" 900 901 #: assets/js/admin.bundle.js:19 902 #: assets/js/admin.js:223 903 msgid "Please select at least one image." 904 msgstr "" 905 906 #: assets/js/admin.bundle.js:19 907 #: assets/js/admin.bundle.js:29 908 #: assets/js/admin.js:239 909 #: assets/js/editor.bundle.js:29 910 #: assets/js/handlers.js:212 911 #: assets/js/handlers.js:619 912 #: assets/js/handlers copy.js:162 913 #: assets/js/handlers copy.js:513 914 #: assets/js/script.bundle.js:19 915 #: assets/js/script.bundle.js:39 916 #: assets/js/script.js:160 917 #: assets/js/script.js:166 918 msgid "Squeezing..." 919 msgstr "" 920 921 #: assets/js/admin.bundle.js:19 922 #: assets/js/admin.js:246 923 msgid "All images have been processed." 924 msgstr "" 925 926 #: assets/js/admin.bundle.js:19 927 #: assets/js/admin.bundle.js:29 928 #: assets/js/admin.js:251 929 #: assets/js/editor.bundle.js:29 930 #: assets/js/handlers.js:200 931 #: assets/js/handlers.js:420 932 #: assets/js/handlers.js:466 933 #: assets/js/handlers copy.js:150 934 #: assets/js/handlers copy.js:431 935 #: assets/js/handlers copy.js:477 936 #: assets/js/script.bundle.js:19 937 #: assets/js/script.bundle.js:39 938 #: assets/js/script.js:83 939 #: assets/js/script.js:182 940 msgid "An error has occured. Check the console for details." 941 msgstr "" 942 943 #: assets/js/admin.bundle.js:29 944 #: assets/js/admin.bundle.js:39 945 #: assets/js/editor.bundle.js:29 946 #: assets/js/editor.bundle.js:39 947 #: assets/js/handlers.js:48 948 #: assets/js/handlers copy.js:290 949 #: assets/js/helpers.js:110 950 #: assets/js/script.bundle.js:19 677 951 #: assets/js/script.bundle.js:29 678 #: assets/js/script.js:707 679 msgid "(<a href=\"%s\" target=\"_blank\">premium only</a>)" 680 msgstr "" 681 682 #: assets/js/4240e511ac61ecfff2d8.js:299 683 #: assets/js/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js:19 684 #: assets/js/script.bundle.js:39 685 #: assets/js/squeeze.js:51 686 msgid "Request timed out." 687 msgstr "" 688 689 #: assets/js/4240e511ac61ecfff2d8.js:487 690 #: assets/js/assets_js_squeeze_js-assets_js_worker_js.script.bundle.js:19 691 #: assets/js/script.bundle.js:39 692 #: assets/js/squeeze.js:198 693 msgid "Skipped" 694 msgstr "" 695 696 #: assets/js/helpers.js:107 952 msgid "Media" 953 msgstr "" 954 955 #: assets/js/admin.bundle.js:29 956 #: assets/js/editor.bundle.js:29 957 #: assets/js/handlers.js:73 958 #: assets/js/handlers.js:275 959 #: assets/js/handlers copy.js:23 960 #: assets/js/handlers copy.js:225 961 #: assets/js/script.bundle.js:19 962 msgid "Resume bulk squeezing" 963 msgstr "" 964 965 #: assets/js/admin.bundle.js:29 966 #: assets/js/editor.bundle.js:29 967 #: assets/js/handlers.js:73 968 #: assets/js/handlers copy.js:23 969 #: assets/js/script.bundle.js:19 970 msgid "Pause bulk squeezing" 971 msgstr "" 972 973 #: assets/js/admin.bundle.js:29 974 #: assets/js/editor.bundle.js:29 975 #: assets/js/handlers.js:145 976 #: assets/js/handlers copy.js:95 977 #: assets/js/script.bundle.js:19 978 msgid "Restore in process..." 979 msgstr "" 980 981 #: assets/js/admin.bundle.js:29 982 #: assets/js/editor.bundle.js:29 983 #: assets/js/handlers.js:180 984 #: assets/js/handlers.js:447 985 #: assets/js/handlers copy.js:128 986 #: assets/js/handlers copy.js:458 987 #: assets/js/script.bundle.js:19 988 #: assets/js/script.bundle.js:39 989 #: assets/js/script.js:63 990 msgid "Pausing..." 991 msgstr "" 992 993 #: assets/js/admin.bundle.js:29 994 #: assets/js/editor.bundle.js:29 995 #: assets/js/handlers.js:191 996 #: assets/js/handlers.js:458 997 #: assets/js/handlers copy.js:141 998 #: assets/js/handlers copy.js:469 999 #: assets/js/script.bundle.js:19 1000 #: assets/js/script.bundle.js:39 1001 #: assets/js/script.js:74 1002 msgid "All images have been processed!" 1003 msgstr "" 1004 1005 #: assets/js/admin.bundle.js:29 1006 #: assets/js/editor.bundle.js:29 1007 #: assets/js/handlers.js:262 1008 #: assets/js/handlers copy.js:212 1009 #: assets/js/script.bundle.js:19 1010 msgid "Are you sure you want to leave this page? The squeezing process will be terminated!" 1011 msgstr "" 1012 1013 #: assets/js/admin.bundle.js:29 1014 #: assets/js/editor.bundle.js:29 1015 #: assets/js/handlers.js:265 1016 #: assets/js/handlers copy.js:215 1017 #: assets/js/script.bundle.js:19 1018 msgid "Are you sure you want to leave this page? The settings will not be saved!" 1019 msgstr "" 1020 1021 #: assets/js/admin.bundle.js:29 1022 #: assets/js/admin.bundle.js:39 1023 #: assets/js/editor.bundle.js:29 1024 #: assets/js/editor.bundle.js:39 1025 #: assets/js/handlers.js:271 1026 #: assets/js/handlers copy.js:221 1027 #: assets/js/helpers.js:110 697 1028 #: assets/js/script.bundle.js:19 698 1029 #: assets/js/script.bundle.js:29 699 #: assets/js/script.js:50700 1030 msgid "Bulk squeezing has been paused!" 701 1031 msgstr "" 702 1032 703 #: assets/js/helpers.js:107 704 #: assets/js/script.bundle.js:19 705 msgid "Media" 706 msgstr "" 707 708 #: assets/js/helpers.js:116 709 #: assets/js/helpers.js:120 710 #: assets/js/script.bundle.js:19 1033 #: assets/js/admin.bundle.js:29 1034 #: assets/js/editor.bundle.js:29 1035 #: assets/js/handlers.js:306 1036 #: assets/js/handlers.js:313 1037 #: assets/js/handlers copy.js:312 1038 #: assets/js/handlers copy.js:320 1039 #: assets/js/script.bundle.js:19 1040 msgid "No more images found!" 1041 msgstr "" 1042 1043 #: assets/js/admin.bundle.js:29 1044 #: assets/js/editor.bundle.js:29 1045 #: assets/js/handlers.js:320 1046 #: assets/js/handlers copy.js:331 1047 #: assets/js/parallel.js:35 1048 #: assets/js/script.bundle.js:19 1049 msgid "Start squeezing..." 1050 msgstr "" 1051 1052 #: assets/js/admin.bundle.js:29 1053 #: assets/js/editor.bundle.js:29 1054 #: assets/js/handlers.js:407 1055 #: assets/js/handlers copy.js:420 1056 #: assets/js/script.bundle.js:19 1057 msgid "Found images on the page:" 1058 msgstr "" 1059 1060 #: assets/js/admin.bundle.js:29 1061 #: assets/js/editor.bundle.js:29 1062 #: assets/js/handlers.js:416 1063 #: assets/js/handlers copy.js:427 1064 #: assets/js/script.bundle.js:19 1065 msgid "Error:" 1066 msgstr "" 1067 1068 #: assets/js/admin.bundle.js:29 1069 #: assets/js/editor.bundle.js:29 1070 #: assets/js/handlers.js:423 1071 #: assets/js/handlers.js:426 1072 #: assets/js/handlers copy.js:434 1073 #: assets/js/handlers copy.js:437 1074 #: assets/js/script.bundle.js:19 1075 msgid "An error has occurred while fetching images from the page. Check the console for details." 1076 msgstr "" 1077 1078 #: assets/js/admin.bundle.js:29 1079 #: assets/js/editor.bundle.js:29 1080 #: assets/js/handlers.js:638 1081 #: assets/js/script.bundle.js:19 1082 msgid "File is excluded from compression:" 1083 msgstr "" 1084 1085 #: assets/js/admin.bundle.js:29 1086 #: assets/js/editor.bundle.js:29 1087 #: assets/js/handlers.js:647 1088 #: assets/js/script.bundle.js:19 1089 msgid "File compression failed:" 1090 msgstr "" 1091 1092 #: assets/js/admin.bundle.js:39 1093 #: assets/js/editor.bundle.js:39 1094 #: assets/js/helpers.js:119 1095 #: assets/js/helpers.js:123 1096 #: assets/js/script.bundle.js:29 711 1097 msgid "Show details" 712 1098 msgstr "" 713 1099 714 #: assets/js/helpers.js:120 715 #: assets/js/script.bundle.js:19 1100 #: assets/js/admin.bundle.js:39 1101 #: assets/js/editor.bundle.js:39 1102 #: assets/js/helpers.js:123 1103 #: assets/js/script.bundle.js:29 716 1104 msgid "Hide details" 717 1105 msgstr "" 718 1106 719 #: assets/js/helpers.js:183 720 #: assets/js/script.bundle.js:19 1107 #: assets/js/admin.bundle.js:39 1108 #: assets/js/editor.bundle.js:39 1109 #: assets/js/helpers.js:190 1110 #: assets/js/script.bundle.js:29 721 1111 msgid "No directories found!" 722 1112 msgstr "" 723 1113 724 #: assets/js/helpers.js:244 725 #: assets/js/script.bundle.js:19 1114 #: assets/js/admin.bundle.js:39 1115 #: assets/js/editor.bundle.js:39 1116 #: assets/js/helpers.js:266 1117 #: assets/js/script.bundle.js:29 726 1118 msgid "Error parsing path input!" 727 1119 msgstr "" 728 1120 729 #: assets/js/script.bundle.js:29 730 #: assets/js/script.js:54 731 #: assets/js/script.js:61 732 msgid "Resume bulk squeezing" 733 msgstr "" 734 735 #: assets/js/script.bundle.js:29 736 #: assets/js/script.js:61 737 msgid "Pause bulk squeezing" 738 msgstr "" 739 740 #: assets/js/script.bundle.js:29 741 #: assets/js/script.js:83 742 msgid "Are you sure you want to leave this page? The squeezing process will be terminated!" 743 msgstr "" 744 745 #: assets/js/script.bundle.js:29 746 #: assets/js/script.js:86 747 msgid "Are you sure you want to leave this page? The settings will not be saved!" 748 msgstr "" 749 750 #: assets/js/script.bundle.js:29 751 #: assets/js/script.js:134 752 msgid "Restore in process..." 753 msgstr "" 754 755 #: assets/js/script.bundle.js:29 756 #: assets/js/script.js:156 757 #: assets/js/script.js:433 758 #: assets/js/script.js:439 759 #: assets/js/script.js:630 760 msgid "Squeezing..." 761 msgstr "" 762 763 #: assets/js/script.bundle.js:29 764 #: assets/js/script.js:186 765 msgid "Start squeezing..." 766 msgstr "" 767 768 #: assets/js/script.bundle.js:29 769 #: assets/js/script.js:273 770 #: assets/js/script.js:340 771 #: assets/js/script.js:522 772 msgid "Pausing..." 773 msgstr "" 774 775 #: assets/js/script.bundle.js:29 776 #: assets/js/script.js:284 777 #: assets/js/script.js:351 1121 #: assets/js/editor.bundle.js:19 1122 #: assets/js/editor.js:80 1123 #: assets/js/editor__old.js:131 1124 msgid "Squeezing image…" 1125 msgstr "" 1126 1127 #: assets/js/editor.bundle.js:19 1128 #: assets/js/editor.js:125 1129 #: assets/js/editor__old.js:30 1130 msgid "Error fetching attachment: %s" 1131 msgstr "" 1132 1133 #: assets/js/editor.bundle.js:19 1134 #: assets/js/editor.js:158 1135 #: assets/js/editor__old.js:60 1136 msgid "Error uploading image: %s" 1137 msgstr "" 1138 1139 #: assets/js/editor.bundle.js:19 1140 #: assets/js/editor.js:279 1141 msgid "Squeezing the image..." 1142 msgstr "" 1143 1144 #: assets/js/editor.bundle.js:19 1145 #: assets/js/editor.js:342 1146 #: assets/js/editor.js:358 1147 msgid "Error squeezing the image: %s" 1148 msgstr "" 1149 1150 #: assets/js/script.bundle.js:39 1151 #: assets/js/script.js:37 1152 msgid "Please enter a valid path!" 1153 msgstr "" 1154 1155 #: assets/js/script.bundle.js:39 1156 #: assets/js/script.js:440 1157 msgid "Loading Preview..." 1158 msgstr "" 1159 1160 #: assets/js/script.bundle.js:39 778 1161 #: assets/js/script.js:533 779 msgid "All images have been processed!" 780 msgstr "" 781 782 #: assets/js/script.bundle.js:29 783 #: assets/js/script.js:293 784 #: assets/js/script.js:360 785 #: assets/js/script.js:455 786 #: assets/js/script.js:495 787 #: assets/js/script.js:541 788 msgid "An error has occured. Check the console for details." 789 msgstr "" 790 791 #: assets/js/script.bundle.js:29 792 #: assets/js/script.js:316 793 msgid "Please enter a valid path!" 794 msgstr "" 795 796 #: assets/js/script.bundle.js:29 797 #: assets/js/script.js:484 798 msgid "Found images on the page:" 799 msgstr "" 800 801 #: assets/js/script.bundle.js:29 802 #: assets/js/script.js:491 803 msgid "Error:" 804 msgstr "" 805 806 #: assets/js/script.bundle.js:29 807 #: assets/js/script.js:498 808 #: assets/js/script.js:501 809 msgid "An error has occurred while fetching images from the page. Check the console for details." 810 msgstr "" 811 812 #: assets/js/script.bundle.js:29 813 #: assets/js/script.js:756 814 msgid "Loading Preview..." 815 msgstr "" 816 817 #: assets/js/script.bundle.js:29 818 #: assets/js/script.js:849 819 #: assets/js/script.js:892 1162 #: assets/js/script.js:576 820 1163 msgid "Collapse" 821 1164 msgstr "" 822 1165 823 #: assets/js/script.bundle.js: 29824 #: assets/js/script.js: 8501166 #: assets/js/script.bundle.js:39 1167 #: assets/js/script.js:534 825 1168 msgid "Apply" 826 1169 msgstr "" 827 1170 828 #: assets/js/script.bundle.js: 29829 #: assets/js/script.js: 8651171 #: assets/js/script.bundle.js:39 1172 #: assets/js/script.js:549 830 1173 msgid "An error occurred while rendering the preview. Check the console for details." 831 1174 msgstr "" 832 1175 833 #: assets/js/script.bundle.js: 29834 #: assets/js/script.js: 8951176 #: assets/js/script.bundle.js:39 1177 #: assets/js/script.js:579 835 1178 msgid "Expand" 836 1179 msgstr "" -
squeeze/trunk/readme.txt
r3311866 r3345284 1 === Squeeze – Image Optimization & Compression, W ebP Conversion ===1 === Squeeze – Image Optimization & Compression, WEBP Conversion === 2 2 Contributors: barb0ss 3 3 Tags: image compression, convert webp, image optimization, compress images, optimize images … … 5 5 Tested up to: 6.8 6 6 Requires PHP: 7.3 7 Stable tag: 1. 6.77 Stable tag: 1.7.0 8 8 License: GPLv3 9 9 License URI: https://www.gnu.org/licenses/gpl-3.0.html … … 12 12 13 13 == Description == 14 Squeeze plugin optimizes and compresses images on your website directly in your browser. It also converts your images to the modern WebP format. 15 No extra server used, no limits for images compression. 16 17 [Visit Squeeze official website.](https://pluginarium.com/squeeze/) 18 19 == 🎉 Special Offer: Get 6 months of Premium for FREE! 🎉 == 20 I’ve got something exciting for you! The first 20 people to fill out the form on the site will **get Squeeze Premium absolutely FREE** for 6 months. 21 22 No credit card or phone number required, I promise! Just your email and the website address where you'll be installing the Premium version. 23 24 I'm eager to make Squeeze even better, and I need your help. By testing the plugin and sharing your feedback, complaints, and suggestions, you'll play a crucial role in its improvement. 25 26 Don't miss this opportunity to enhance your website's performance and contribute to the development of a powerful tool. Fill out the form now and secure your spot! 27 28 **[Get the Premium version for FREE here!](https://pluginarium.com/squeeze/get-squeeze-premium-for-free/)** 29 30 == How does the Squeeze plugin work? == 31 Squeeze plugin compresses images directly from your WordPress Media Library or during the image upload process. All the work is handled directly inside your browser using advanced compression algorithms. That means there’s no third party service for compression images. Thus, you can be sure with the privacy of your images, ensuring data privacy and faster processing. 32 33 [Full documentation is here.](https://pluginarium.com/squeeze/squeeze-documentation/) 34 35 == Key Features == 36 * **Performance Boost:** Reduces image sizes to improve website loading speed and overall user experience. 14 Squeeze plugin optimizes and compresses images on your website directly in your browser. 15 It also converts your images to the modern WEBP format, saving your server's disk storage. 16 No third-party server used, no limits for images compression. 17 18 [Squeeze official website](https://pluginarium.com/squeeze/) | [Plugin's documentation](https://pluginarium.com/squeeze/squeeze-documentation/) 19 20 == 🌟 New Features in version 1.7 🌟 == 21 * **Direct WEBP Conversion:** Converts JPG/PNG images to the WEBP format directly, replacing the original images. This will save your disk storage rapidly! 22 **It is recommended to use it for the newly uploaded images only! See the *«How are WEBP images served?»* question in the FAQ section down below.** 23 * **Squeeze images before upload:** Compresses newly added images before they are uploaded to the server. It lowers upload times and less wasted bandwidth on your server. 24 25 == ✨ Key Features ✨ == 26 * **Increase Page Speed:** Reduces image sizes to improve website loading speed and overall user experience. 37 27 * **WEBP Conversion and Serving:** Convert images to the modern and efficient WEBP format and serve them seamlessly. The plugin adds .htaccess rules to serve WEBP images for supported browsers without changing URLs. Alternatively, enable the "Replace Image URLs" option to explicitly use WEBP versions on all pages. 38 28 * **Client-Side Image Squeezing:** Compress images directly in the browser without sending files to external servers 39 29 * **Upload Optimization:** Compresses images on-the-fly during the upload process, ensuring optimized images are added to your media library. 30 * **Gutenberg and GenerateBlocks Support:** Squeeze images directly on upload in Gutenberg or GenerateBlocks builder. 40 31 * **Bulk Compression:** Allows you to compress multiple images at once from your WordPress Media Library. 41 * **Custom Path Compression:** Select a folder on your site and compress all the images within that folder.32 * **Custom Directory Compression:** Select a directory on your site and compress all the images within it. 42 33 * **Selective Compression:** Choose which images to compress based on your preferences and requirements. 43 34 * **Custom Squeezing Settings:** Adjust compression parameters such as quality level to suit your specific needs. 44 35 * **Backup Option:** Creates a backup file to restore a compressed image to the original image. 45 * **Wide Format Support:** Squeezes images in popular formats, including JPEG, PNG, AVIF, and W ebP.46 47 == Premium Features==48 * **Image Comparison:** Compare original and Squeezed image directly in the Media Library.36 * **Wide Format Support:** Squeezes images in popular formats, including JPEG, PNG, AVIF, and WEBP. 37 38 == ⚜️ Premium Features ⚜️ == 39 * **Image Comparison:** Compare original and Squeezed images directly in the Media Library. 49 40 * **Resize Original Image:** Set maximum width and height for the original image. 50 41 * **Bulk Squeeze from a Page:** Compress all images from a specific page. … … 56 47 **[Explore the Premium version here.](https://pluginarium.com/squeeze/#premium)** 57 48 49 == How does the Squeeze plugin work? == 50 Squeeze plugin compresses images directly from your WordPress Media Library or during the image upload process. All the work is handled directly inside your browser using advanced compression algorithms. That means there’s no third party service for compression images. Thus, you can be sure with the privacy of your images, ensuring data privacy and faster processing. 51 52 [Plugin's documentation is available here.](https://pluginarium.com/squeeze/squeeze-documentation/) 53 58 54 == Installation == 59 55 1. Download the plugin ZIP file from the WordPress Plugin Directory, or install the plugin via the WordPress plugin installer. 60 56 2. Extract the ZIP file (if downloaded from WordPress Plugin Directory). 61 3. Upload the plugin folderto the wp-content/plugins/ directory of your WordPress installation.57 3. Upload the plugin directory to the wp-content/plugins/ directory of your WordPress installation. 62 58 4. Activate the Squeeze plugin from the WordPress plugins dashboard. 63 59 … … 86 82 = Can this plugin convert images to the WEBP format? = 87 83 88 Yes! The Squeeze plugin supports converting images to the WEBP format during the compression process. WEBP is a modern image format that provides superior compression while maintaining high quality, resulting in faster loading times and reduced bandwidth usage. To enable this feature, simply check the "Generate WEBP" option under the Basic Settings tab to output images in WEBP format.84 Yes! The Squeeze plugin supports converting images to the WEBP format during the compression process. WEBP is a modern image format that provides superior compression while maintaining high quality, resulting in faster loading times and reduced bandwidth usage. To enable this feature, check the "Direct WEBP Conversion" option under the Basic Settings tab to convert images in WEBP format. 89 85 90 86 = How are WEBP images served? = 91 87 92 By default, the Squeeze plugin adds rules to your .htaccess file to serve WEBP images automatically. This means that when a browser supports the WEBP format, the corresponding WEBP version of an image will be served without changing the original image's URL. This allows seamless integration without disrupting your website's existing structure. 93 If you enable the "Replace Images URLs" option in the plugin settings, the plugin will directly replace all image URLs on your pages with their corresponding WEBP versions. This can be useful for ensuring that WEBP images are explicitly used everywhere on your site. 94 The generated WEBP images are stored in the wp-content/squeeze-webp folder within your WordPress installation. 88 Squeeze plugin converts your JPG/PNG images into WEBP format replacing the original images. 89 To enable this feature, check the "Direct WEBP Conversion" option under the Basic Settings tab to convert images in WEBP format. 90 91 **ATTENTION! It is highly recommended to use the "Direct WEBP Conversion" feature only to the newly uploaded images. 92 Otherwise, your existing JPG/PNG images may be broken on your site's frontend because of non-existed URLs.** 93 94 That means if you have an image in JPG format like `image.jpg`, after conversion to WEBP format it becomes `image.webp`. 95 The existing image on your site's page with URL like `//yoursite.com/wp-content/uploads/2025/08/image.jpg` will be broken, because there is no more `image.jpg` file on your server. 96 So you need to update your image manually for such cases (usually just to re-select it from the Media Library when you edit your page). 97 98 Previously, the generated WEBP images were stored in the wp-content/squeeze-webp directory within your WordPress installation. 99 That method is not very optimal, because it creates extra images which reduce your server's storage space. 100 However, if you already used that approach, you can keep it enabled for backwards compatibility. 95 101 96 102 = Which scripts are used for compressing and converting images? … … 99 105 100 106 * MozJPEG: Used for compressing JPEG images. 101 * Browser Image Compression: Used for compressing PNG images. This is not come from the Squoosh.app, as its OxiPNG takes quite a long time to compress images.102 * W ebP: Used for converting and compressing images to the modern WEBP format.107 * Browser Image Compression: Used for compressing PNG images. This does not come from the Squoosh.app, as its OxiPNG takes quite a long time to compress images. 108 * WEBP: Used for converting and compressing images to the modern WEBP format. 103 109 * AVIF: An advanced codec for creating lightweight and high-quality AVIF images. 104 110 … … 115 121 Yes, the plugin provides a bulk compression feature. This saves time and effort compared to compressing images individually. 116 122 117 = Can I compress images NOT from the Media Library, but from a custom folder? =118 119 Yes, you can compress images from any folderwithin your WordPress installation.123 = Can I compress images NOT from the Media Library, but from a custom directory? = 124 125 Yes, you can compress images from any directory within your WordPress installation. 120 126 121 127 = Can I customize the compression settings? = … … 128 134 129 135 == Screenshots == 130 1. Compressed image with theSqueeze Plugin136 1. Compressed image with Squeeze Plugin 131 137 2. Squeeze's Bulk Compression Page 132 138 3. Squeeze's Restore and Recompress Options 133 4. Serving WEBP images instead of JPG and PNG. Even though the URL of the image remains the same, the response is in theWEBP format.134 5. Replacing images URLs with the corresponding WEBP version. If your server does not support .htaccess file or it is not writable, then you can use this option to replace your images URLs and serve WEBP images.139 4. Direct conversion of an image into WEBP format. The original image is being replaced by the compressed image in WEBP format. 140 5. A method of replacing images URLs with the corresponding WEBP versions. 135 141 6. Squeeze's Basic Settings 136 142 7. Squeeze's JPEG compression settings 137 143 8. Squeeze's PNG compression settings 138 9. Squeeze's W ebP compression settings144 9. Squeeze's WEBP compression settings 139 145 10. Squeeze's AVIF compression settings 140 146 11. Squeeze's Bulk actions in the List view of the Media Library 141 147 12. Squeeze's Filter in the Grid view of the Media Library 142 13. Preview image with live Squeezing options (Premium feature) 143 14. Bulk Squeeze from a page (Premium feature) 148 13. Squeeze images directly on upload in Gutenberg or GenerateBlocks builder. 149 14. Preview image with live Squeezing options (Premium feature) 150 15. Bulk Squeeze from a page (Premium feature) 144 151 145 152 == Changelog == 153 = 1.7.0 = 154 * Added direct WEBP conversion option 155 * Compress newly uploaded images immediately, before they being uploaded to the server 156 * Skip uploading the compressed image, if it becomes larger than original after compression 157 * Fixed account tab on the Settings page 158 * Added explanation screenshots for some options on the Settings page 146 159 = 1.6.7 = 147 160 * Added auto-squeezing for the images uploaded via Image block … … 165 178 * Refactored PHP and JS code 166 179 = 1.5.2 = 167 * Fixed webp convertion180 * Fixed WEBP conversion 168 181 * Added option to select image formats 169 182 = 1.5.1 = … … 206 219 * Update settings page layout with tabs 207 220 * Add ability to re-compress images 208 * Add ability to compress images from custom folder221 * Add ability to compress images from custom directory 209 222 = 1.2 = 210 223 * Fix minor bug in Media library … … 215 228 216 229 == Upgrade Notice == 230 = 1.7.0 = 231 * Added direct WEBP conversion option 232 * Compress newly uploaded images immediately, not after they being uploaded to the server 233 * Skip uploading the compressed image, if it becomes larger than original after compression 234 * Fixed account tab on the Settings page 235 * Added explanation screenshots for some options on the Settings page 217 236 = 1.6.5 = 218 237 * Added bulk Squeeze in the Grid mode … … 232 251 * Refactored JS: exploded complex functions, add html templates to separate business logic from layouts 233 252 = 1.5.2 = 234 * Fixed webp convertion253 * Fixed WEBP conversion 235 254 * Added option to select image formats 236 255 = 1.5.1 = … … 267 286 * Update settings page layout with tabs 268 287 * Add ability to re-compress images 269 * Add ability to compress images from custom folder288 * Add ability to compress images from custom directory 270 289 = 1.2 = 271 290 * Fix minor bug in Media library -
squeeze/trunk/squeeze.php
r3311866 r3345284 6 6 * Author URI: https://pluginarium.com 7 7 * Author: Bogdan Bendziukov 8 * Version: 1. 6.78 * Version: 1.7.0 9 9 * 10 10 * Text Domain: squeeze … … 22 22 exit; 23 23 } 24 24 25 class SqueezeInit { 25 26 /** 26 27 * Plugin version 27 28 */ 28 const VERSION = '1. 6.7';29 const VERSION = '1.7.0'; 29 30 30 31 const CHECKOUT_URL = 'https://checkout.freemius.com/plugin/17217/plan/28703/'; … … 91 92 ); 92 93 add_action( 'enqueue_block_editor_assets', array($this, 'load_editor_assets') ); 94 add_action( 'squeeze_freemius_loaded', array($this, 'load_freemius') ); 93 95 } 94 96 … … 101 103 102 104 public function load_freemius() { 105 } 106 107 public function opt_in_freemius() { 108 } 109 110 public function freemius_admin_notices() { 103 111 } 104 112 … … 162 170 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 163 171 'nonce' => wp_create_nonce( 'squeeze-nonce' ), 172 'restNonce' => wp_create_nonce( 'wp_rest' ), 164 173 'options' => wp_json_encode( $js_options ), 165 174 'templateBase' => self::$PLUGIN_URL . 'assets/templates/',
Note: See TracChangeset
for help on using the changeset viewer.