PluginProbe
Gutenberg / 23.1.1
Gutenberg v23.1.1
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / build / scripts / upload-media / index.js

index.js in Gutenberg 23.1.1, at build/scripts/upload-media/index.js

2,531 lines 76.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 "use strict";
2 var wp;
3 (wp ||= {}).uploadMedia = (() => {
4 var __create = Object.create;
5 var __defProp = Object.defineProperty;
6 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7 var __getOwnPropNames = Object.getOwnPropertyNames;
8 var __getProtoOf = Object.getPrototypeOf;
9 var __hasOwnProp = Object.prototype.hasOwnProperty;
10 var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
11 get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
12 }) : x)(function(x) {
13 if (typeof require !== "undefined") return require.apply(this, arguments);
14 throw Error('Dynamic require of "' + x + '" is not supported');
15 });
16 var __commonJS = (cb, mod) => function __require2() {
17 return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
18 };
19 var __export = (target, all) => {
20 for (var name in all)
21 __defProp(target, name, { get: all[name], enumerable: true });
22 };
23 var __copyProps = (to, from, except, desc) => {
24 if (from && typeof from === "object" || typeof from === "function") {
25 for (let key of __getOwnPropNames(from))
26 if (!__hasOwnProp.call(to, key) && key !== except)
27 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
28 }
29 return to;
30 };
31 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
32 // If the importer is in node compatibility mode or this is not an ESM
33 // file that has been converted to a CommonJS file using a Babel-
34 // compatible transform (i.e. "__esModule" has not been set), then set
35 // "default" to the CommonJS "module.exports" for node compatibility.
36 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
37 mod
38 ));
39 var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
40
41 // package-external:@wordpress/data
42 var require_data = __commonJS({
43 "package-external:@wordpress/data"(exports, module) {
44 module.exports = window.wp.data;
45 }
46 });
47
48 // package-external:@wordpress/url
49 var require_url = __commonJS({
50 "package-external:@wordpress/url"(exports, module) {
51 module.exports = window.wp.url;
52 }
53 });
54
55 // package-external:@wordpress/i18n
56 var require_i18n = __commonJS({
57 "package-external:@wordpress/i18n"(exports, module) {
58 module.exports = window.wp.i18n;
59 }
60 });
61
62 // package-external:@wordpress/blob
63 var require_blob = __commonJS({
64 "package-external:@wordpress/blob"(exports, module) {
65 module.exports = window.wp.blob;
66 }
67 });
68
69 // package-external:@wordpress/private-apis
70 var require_private_apis = __commonJS({
71 "package-external:@wordpress/private-apis"(exports, module) {
72 module.exports = window.wp.privateApis;
73 }
74 });
75
76 // package-external:@wordpress/element
77 var require_element = __commonJS({
78 "package-external:@wordpress/element"(exports, module) {
79 module.exports = window.wp.element;
80 }
81 });
82
83 // package-external:@wordpress/compose
84 var require_compose = __commonJS({
85 "package-external:@wordpress/compose"(exports, module) {
86 module.exports = window.wp.compose;
87 }
88 });
89
90 // vendor-external:react/jsx-runtime
91 var require_jsx_runtime = __commonJS({
92 "vendor-external:react/jsx-runtime"(exports, module) {
93 module.exports = window.ReactJSXRuntime;
94 }
95 });
96
97 // packages/upload-media/build-module/index.mjs
98 var index_exports = {};
99 __export(index_exports, {
100 MediaUploadProvider: () => provider_default,
101 UploadError: () => UploadError,
102 clearFeatureDetectionCache: () => clearFeatureDetectionCache,
103 detectClientSideMediaSupport: () => detectClientSideMediaSupport,
104 isClientSideMediaSupported: () => isClientSideMediaSupported,
105 isHeicCanvasSupported: () => isHeicCanvasSupported,
106 store: () => store
107 });
108
109 // packages/upload-media/build-module/store/index.mjs
110 var import_data = __toESM(require_data(), 1);
111
112 // packages/upload-media/build-module/store/types.mjs
113 var Type = /* @__PURE__ */ ((Type2) => {
114 Type2["Unknown"] = "REDUX_UNKNOWN";
115 Type2["Add"] = "ADD_ITEM";
116 Type2["Prepare"] = "PREPARE_ITEM";
117 Type2["Cancel"] = "CANCEL_ITEM";
118 Type2["Remove"] = "REMOVE_ITEM";
119 Type2["RetryItem"] = "RETRY_ITEM";
120 Type2["PauseItem"] = "PAUSE_ITEM";
121 Type2["ResumeItem"] = "RESUME_ITEM";
122 Type2["PauseQueue"] = "PAUSE_QUEUE";
123 Type2["ResumeQueue"] = "RESUME_QUEUE";
124 Type2["OperationStart"] = "OPERATION_START";
125 Type2["OperationFinish"] = "OPERATION_FINISH";
126 Type2["AddOperations"] = "ADD_OPERATIONS";
127 Type2["CacheBlobUrl"] = "CACHE_BLOB_URL";
128 Type2["RevokeBlobUrls"] = "REVOKE_BLOB_URLS";
129 Type2["UpdateProgress"] = "UPDATE_PROGRESS";
130 Type2["AccumulateSubSize"] = "ACCUMULATE_SUB_SIZE";
131 Type2["UpdateSettings"] = "UPDATE_SETTINGS";
132 return Type2;
133 })(Type || {});
134 var ItemStatus = /* @__PURE__ */ ((ItemStatus2) => {
135 ItemStatus2["Queued"] = "QUEUED";
136 ItemStatus2["Processing"] = "PROCESSING";
137 ItemStatus2["Paused"] = "PAUSED";
138 ItemStatus2["Uploaded"] = "UPLOADED";
139 ItemStatus2["Error"] = "ERROR";
140 return ItemStatus2;
141 })(ItemStatus || {});
142 var OperationType = /* @__PURE__ */ ((OperationType2) => {
143 OperationType2["Prepare"] = "PREPARE";
144 OperationType2["Upload"] = "UPLOAD";
145 OperationType2["ResizeCrop"] = "RESIZE_CROP";
146 OperationType2["Rotate"] = "ROTATE";
147 OperationType2["TranscodeImage"] = "TRANSCODE_IMAGE";
148 OperationType2["ThumbnailGeneration"] = "THUMBNAIL_GENERATION";
149 OperationType2["Finalize"] = "FINALIZE";
150 return OperationType2;
151 })(OperationType || {});
152
153 // packages/upload-media/build-module/store/constants.mjs
154 var STORE_NAME = "core/upload-media";
155 var DEFAULT_MAX_CONCURRENT_UPLOADS = 5;
156 var DEFAULT_MAX_CONCURRENT_IMAGE_PROCESSING = 2;
157 var CLIENT_SIDE_SUPPORTED_MIME_TYPES = [
158 "image/jpeg",
159 "image/png",
160 "image/gif",
161 "image/webp",
162 "image/avif"
163 ];
164 var HEIC_MIME_TYPES = [
165 "image/heic",
166 "image/heif"
167 ];
168
169 // packages/upload-media/build-module/store/reducer.mjs
170 var noop = () => {
171 };
172 var DEFAULT_STATE = {
173 queue: [],
174 queueStatus: "active",
175 blobUrls: {},
176 settings: {
177 mediaUpload: noop,
178 maxConcurrentUploads: DEFAULT_MAX_CONCURRENT_UPLOADS,
179 maxConcurrentImageProcessing: DEFAULT_MAX_CONCURRENT_IMAGE_PROCESSING
180 }
181 };
182 function reducer(state = DEFAULT_STATE, action = { type: Type.Unknown }) {
183 switch (action.type) {
184 case Type.PauseQueue: {
185 return {
186 ...state,
187 queueStatus: "paused"
188 };
189 }
190 case Type.ResumeQueue: {
191 return {
192 ...state,
193 queueStatus: "active"
194 };
195 }
196 case Type.PauseItem:
197 return {
198 ...state,
199 queue: state.queue.map(
200 (item) => item.id === action.id ? {
201 ...item,
202 status: ItemStatus.Paused
203 } : item
204 )
205 };
206 case Type.ResumeItem:
207 return {
208 ...state,
209 queue: state.queue.map(
210 (item) => item.id === action.id ? {
211 ...item,
212 status: ItemStatus.Processing
213 } : item
214 )
215 };
216 case Type.Add:
217 return {
218 ...state,
219 queue: [...state.queue, action.item]
220 };
221 case Type.Cancel:
222 return {
223 ...state,
224 queue: state.queue.map(
225 (item) => item.id === action.id ? {
226 ...item,
227 error: action.error
228 } : item
229 )
230 };
231 case Type.RetryItem:
232 return {
233 ...state,
234 queue: state.queue.map(
235 (item) => item.id === action.id ? {
236 ...item,
237 status: ItemStatus.Processing,
238 error: void 0,
239 retryCount: (item.retryCount ?? 0) + 1
240 } : item
241 )
242 };
243 case Type.Remove:
244 return {
245 ...state,
246 queue: state.queue.filter((item) => item.id !== action.id)
247 };
248 case Type.OperationStart: {
249 return {
250 ...state,
251 queue: state.queue.map(
252 (item) => item.id === action.id ? {
253 ...item,
254 currentOperation: action.operation
255 } : item
256 )
257 };
258 }
259 case Type.AddOperations:
260 return {
261 ...state,
262 queue: state.queue.map((item) => {
263 if (item.id !== action.id) {
264 return item;
265 }
266 return {
267 ...item,
268 operations: [
269 ...item.operations || [],
270 ...action.operations
271 ]
272 };
273 })
274 };
275 case Type.OperationFinish:
276 return {
277 ...state,
278 queue: state.queue.map((item) => {
279 if (item.id !== action.id) {
280 return item;
281 }
282 const operations = item.operations ? item.operations.slice(1) : [];
283 const attachment = item.attachment || action.item.attachment ? {
284 ...item.attachment,
285 ...action.item.attachment
286 } : void 0;
287 return {
288 ...item,
289 currentOperation: void 0,
290 operations,
291 ...action.item,
292 attachment,
293 additionalData: {
294 ...item.additionalData,
295 ...action.item.additionalData
296 }
297 };
298 })
299 };
300 case Type.CacheBlobUrl: {
301 const blobUrls = state.blobUrls[action.id] || [];
302 return {
303 ...state,
304 blobUrls: {
305 ...state.blobUrls,
306 [action.id]: [...blobUrls, action.blobUrl]
307 }
308 };
309 }
310 case Type.RevokeBlobUrls: {
311 const newBlobUrls = { ...state.blobUrls };
312 delete newBlobUrls[action.id];
313 return {
314 ...state,
315 blobUrls: newBlobUrls
316 };
317 }
318 case Type.UpdateProgress:
319 return {
320 ...state,
321 queue: state.queue.map(
322 (item) => item.id === action.id ? {
323 ...item,
324 progress: action.progress
325 } : item
326 )
327 };
328 case Type.AccumulateSubSize:
329 return {
330 ...state,
331 queue: state.queue.map(
332 (item) => item.id === action.id ? {
333 ...item,
334 subSizes: [
335 ...item.subSizes || [],
336 action.subSize
337 ]
338 } : item
339 )
340 };
341 case Type.UpdateSettings: {
342 return {
343 ...state,
344 settings: {
345 ...state.settings,
346 ...action.settings
347 }
348 };
349 }
350 }
351 return state;
352 }
353 var reducer_default = reducer;
354
355 // packages/upload-media/build-module/store/selectors.mjs
356 var selectors_exports = {};
357 __export(selectors_exports, {
358 getItems: () => getItems,
359 getSettings: () => getSettings,
360 isUploading: () => isUploading,
361 isUploadingById: () => isUploadingById,
362 isUploadingByUrl: () => isUploadingByUrl
363 });
364 function getItems(state) {
365 return state.queue;
366 }
367 function isUploading(state) {
368 return state.queue.length >= 1;
369 }
370 function isUploadingByUrl(state, url) {
371 return state.queue.some(
372 (item) => item.attachment?.url === url || item.sourceUrl === url
373 );
374 }
375 function isUploadingById(state, attachmentId) {
376 return state.queue.some(
377 (item) => item.attachment?.id === attachmentId || item.sourceAttachmentId === attachmentId
378 );
379 }
380 function getSettings(state) {
381 return state.settings;
382 }
383
384 // packages/upload-media/build-module/store/private-selectors.mjs
385 var private_selectors_exports = {};
386 __export(private_selectors_exports, {
387 getActiveImageProcessingCount: () => getActiveImageProcessingCount,
388 getActiveUploadCount: () => getActiveUploadCount,
389 getAllItems: () => getAllItems,
390 getBlobUrls: () => getBlobUrls,
391 getFailedItems: () => getFailedItems,
392 getItem: () => getItem,
393 getItemProgress: () => getItemProgress,
394 getPendingImageProcessing: () => getPendingImageProcessing,
395 getPendingUploads: () => getPendingUploads,
396 hasPendingItemsByParentId: () => hasPendingItemsByParentId,
397 isBatchUploaded: () => isBatchUploaded,
398 isPaused: () => isPaused
399 });
400 function getAllItems(state) {
401 return state.queue;
402 }
403 function getItem(state, id) {
404 return state.queue.find((item) => item.id === id);
405 }
406 function isBatchUploaded(state, batchId) {
407 const batchItems = state.queue.filter(
408 (item) => batchId === item.batchId
409 );
410 return batchItems.length === 0;
411 }
412 function isPaused(state) {
413 return state.queueStatus === "paused";
414 }
415 function getBlobUrls(state, id) {
416 return state.blobUrls[id] || [];
417 }
418 function getActiveUploadCount(state) {
419 return state.queue.filter(
420 (item) => item.currentOperation === OperationType.Upload
421 ).length;
422 }
423 function getPendingUploads(state) {
424 return state.queue.filter((item) => {
425 const nextOperation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0];
426 return nextOperation === OperationType.Upload && item.currentOperation !== OperationType.Upload;
427 });
428 }
429 function getActiveImageProcessingCount(state) {
430 return state.queue.filter(
431 (item) => item.currentOperation === OperationType.ResizeCrop || item.currentOperation === OperationType.Rotate
432 ).length;
433 }
434 function getPendingImageProcessing(state) {
435 return state.queue.filter((item) => {
436 const nextOperation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0];
437 return (nextOperation === OperationType.ResizeCrop || nextOperation === OperationType.Rotate) && item.currentOperation !== OperationType.ResizeCrop && item.currentOperation !== OperationType.Rotate;
438 });
439 }
440 function getFailedItems(state) {
441 return state.queue.filter((item) => item.error !== void 0);
442 }
443 function hasPendingItemsByParentId(state, parentId) {
444 return state.queue.some((item) => item.parentId === parentId);
445 }
446 function getItemProgress(state, id) {
447 const item = state.queue.find((i) => i.id === id);
448 return item?.progress;
449 }
450
451 // packages/upload-media/build-module/store/actions.mjs
452 var actions_exports = {};
453 __export(actions_exports, {
454 addItems: () => addItems,
455 cancelItem: () => cancelItem,
456 retryItem: () => retryItem
457 });
458
459 // node_modules/uuid/dist/esm-browser/rng.js
460 var getRandomValues;
461 var rnds8 = new Uint8Array(16);
462 function rng() {
463 if (!getRandomValues) {
464 getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
465 if (!getRandomValues) {
466 throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
467 }
468 }
469 return getRandomValues(rnds8);
470 }
471
472 // node_modules/uuid/dist/esm-browser/stringify.js
473 var byteToHex = [];
474 for (let i = 0; i < 256; ++i) {
475 byteToHex.push((i + 256).toString(16).slice(1));
476 }
477 function unsafeStringify(arr, offset = 0) {
478 return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
479 }
480
481 // node_modules/uuid/dist/esm-browser/native.js
482 var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
483 var native_default = {
484 randomUUID
485 };
486
487 // node_modules/uuid/dist/esm-browser/v4.js
488 function v4(options, buf, offset) {
489 if (native_default.randomUUID && !buf && !options) {
490 return native_default.randomUUID();
491 }
492 options = options || {};
493 const rnds = options.random || (options.rng || rng)();
494 rnds[6] = rnds[6] & 15 | 64;
495 rnds[8] = rnds[8] & 63 | 128;
496 if (buf) {
497 offset = offset || 0;
498 for (let i = 0; i < 16; ++i) {
499 buf[offset + i] = rnds[i];
500 }
501 return buf;
502 }
503 return unsafeStringify(rnds);
504 }
505 var v4_default = v4;
506
507 // packages/upload-media/build-module/image-file.mjs
508 var ImageFile = class extends File {
509 width = 0;
510 height = 0;
511 originalWidth = 0;
512 originalHeight = 0;
513 get wasResized() {
514 return (this.originalWidth || 0) > this.width || (this.originalHeight || 0) > this.height;
515 }
516 constructor(file, width, height, originalWidth, originalHeight) {
517 super([file], file.name, {
518 type: file.type,
519 lastModified: file.lastModified
520 });
521 this.width = width;
522 this.height = height;
523 this.originalWidth = originalWidth;
524 this.originalHeight = originalHeight;
525 }
526 };
527
528 // packages/upload-media/build-module/utils.mjs
529 var import_url = __toESM(require_url(), 1);
530 var import_i18n = __toESM(require_i18n(), 1);
531 function convertBlobToFile(fileOrBlob) {
532 if (fileOrBlob instanceof File) {
533 return fileOrBlob;
534 }
535 if ("name" in fileOrBlob && typeof fileOrBlob.name === "string") {
536 return new File([fileOrBlob], fileOrBlob.name, {
537 type: fileOrBlob.type,
538 lastModified: fileOrBlob.lastModified
539 });
540 }
541 const ext = fileOrBlob.type.split("/")[1];
542 const mediaType = "application/pdf" === fileOrBlob.type ? "document" : fileOrBlob.type.split("/")[0];
543 return new File([fileOrBlob], `${mediaType}.${ext}`, {
544 type: fileOrBlob.type
545 });
546 }
547 function renameFile(file, name) {
548 return new File([file], name, {
549 type: file.type,
550 lastModified: file.lastModified
551 });
552 }
553 function cloneFile(file) {
554 return renameFile(file, file.name);
555 }
556 function getFileBasename(name) {
557 return name.includes(".") ? name.split(".").slice(0, -1).join(".") : name;
558 }
559
560 // packages/upload-media/build-module/store/utils/index.mjs
561 var vipsModulePromise;
562 var vipsModule;
563 function loadVipsModule() {
564 if (!vipsModulePromise) {
565 vipsModulePromise = import("@wordpress/vips/worker").then(
566 (mod) => {
567 vipsModule = mod;
568 return mod;
569 }
570 );
571 }
572 return vipsModulePromise;
573 }
574 async function vipsConvertImageFormat(id, file, type, quality, interlaced) {
575 const { vipsConvertImageFormat: convertImageFormat } = await loadVipsModule();
576 const buffer = await convertImageFormat(
577 id,
578 await file.arrayBuffer(),
579 file.type,
580 type,
581 quality,
582 interlaced
583 );
584 const ext = type.split("/")[1];
585 const fileName = `${getFileBasename(file.name)}.${ext}`;
586 return new File([new Blob([buffer])], fileName, {
587 type
588 });
589 }
590 async function vipsHasTransparency(url) {
591 const { vipsHasTransparency: hasTransparency } = await loadVipsModule();
592 const response = await fetch(url);
593 if (!response.ok) {
594 throw new Error(`Failed to fetch image: ${response.status}`);
595 }
596 return hasTransparency(await response.arrayBuffer());
597 }
598 async function vipsResizeImage(id, file, resize, smartCrop, addSuffix, signal, scaledSuffix, quality) {
599 if (signal?.aborted) {
600 throw new Error("Operation aborted");
601 }
602 const { vipsResizeImage: resizeImage } = await loadVipsModule();
603 const { buffer, width, height, originalWidth, originalHeight } = await resizeImage(
604 id,
605 await file.arrayBuffer(),
606 file.type,
607 resize,
608 smartCrop,
609 quality
610 );
611 let fileName = file.name;
612 const wasResized = originalWidth > width || originalHeight > height;
613 if (wasResized) {
614 const basename = getFileBasename(file.name);
615 if (scaledSuffix) {
616 fileName = file.name.replace(basename, `${basename}-scaled`);
617 } else if (addSuffix) {
618 fileName = file.name.replace(
619 basename,
620 `${basename}-${width}x${height}`
621 );
622 }
623 }
624 const resultFile = new ImageFile(
625 new File(
626 [new Blob([buffer], { type: file.type })],
627 fileName,
628 {
629 type: file.type
630 }
631 ),
632 width,
633 height,
634 originalWidth,
635 originalHeight
636 );
637 return resultFile;
638 }
639 async function vipsRotateImage(id, file, orientation, signal) {
640 if (signal?.aborted) {
641 throw new Error("Operation aborted");
642 }
643 if (orientation === 1) {
644 return file;
645 }
646 const { vipsRotateImage: rotateImage } = await loadVipsModule();
647 const { buffer, width, height } = await rotateImage(
648 id,
649 await file.arrayBuffer(),
650 file.type,
651 orientation
652 );
653 const basename = getFileBasename(file.name);
654 const fileName = file.name.replace(basename, `${basename}-rotated`);
655 const resultFile = new ImageFile(
656 new File(
657 [new Blob([buffer], { type: file.type })],
658 fileName,
659 {
660 type: file.type
661 }
662 ),
663 width,
664 height
665 );
666 return resultFile;
667 }
668 async function vipsCancelOperations(id) {
669 if (!vipsModule) {
670 return false;
671 }
672 return vipsModule.vipsCancelOperations(id);
673 }
674 function terminateVipsWorker() {
675 if (vipsModule) {
676 vipsModule.terminateVipsWorker();
677 }
678 }
679
680 // packages/upload-media/build-module/validate-mime-type.mjs
681 var import_i18n2 = __toESM(require_i18n(), 1);
682
683 // packages/upload-media/build-module/upload-error.mjs
684 var UploadError = class extends Error {
685 code;
686 file;
687 constructor({ code, message, file, cause }) {
688 super(message, { cause });
689 Object.setPrototypeOf(this, new.target.prototype);
690 this.code = code;
691 this.file = file;
692 }
693 };
694
695 // packages/upload-media/build-module/validate-mime-type.mjs
696 function validateMimeType(file, allowedTypes) {
697 if (!allowedTypes) {
698 return;
699 }
700 const isAllowedType = allowedTypes.some((allowedType) => {
701 if (allowedType.includes("/")) {
702 return allowedType === file.type;
703 }
704 return file.type.startsWith(`${allowedType}/`);
705 });
706 if (file.type && !isAllowedType) {
707 throw new UploadError({
708 code: "MIME_TYPE_NOT_SUPPORTED",
709 message: (0, import_i18n2.sprintf)(
710 // translators: %s: file name.
711 (0, import_i18n2.__)("%s: Sorry, this file type is not supported here."),
712 file.name
713 ),
714 file
715 });
716 }
717 }
718
719 // packages/upload-media/build-module/validate-mime-type-for-user.mjs
720 var import_i18n3 = __toESM(require_i18n(), 1);
721
722 // packages/upload-media/build-module/get-mime-types-array.mjs
723 function getMimeTypesArray(wpMimeTypesObject) {
724 if (!wpMimeTypesObject) {
725 return null;
726 }
727 return Object.entries(wpMimeTypesObject).flatMap(
728 ([extensionsString, mime]) => {
729 const [type] = mime.split("/");
730 const extensions = extensionsString.split("|");
731 return [
732 mime,
733 ...extensions.map(
734 (extension) => `${type}/${extension}`
735 )
736 ];
737 }
738 );
739 }
740
741 // packages/upload-media/build-module/validate-mime-type-for-user.mjs
742 function validateMimeTypeForUser(file, wpAllowedMimeTypes) {
743 const allowedMimeTypesForUser = getMimeTypesArray(wpAllowedMimeTypes);
744 if (!allowedMimeTypesForUser) {
745 return;
746 }
747 const isAllowedMimeTypeForUser = allowedMimeTypesForUser.includes(
748 file.type
749 );
750 if (file.type && !isAllowedMimeTypeForUser) {
751 throw new UploadError({
752 code: "MIME_TYPE_NOT_ALLOWED_FOR_USER",
753 message: (0, import_i18n3.sprintf)(
754 // translators: %s: file name.
755 (0, import_i18n3.__)(
756 "%s: Sorry, you are not allowed to upload this file type."
757 ),
758 file.name
759 ),
760 file
761 });
762 }
763 }
764
765 // packages/upload-media/build-module/validate-file-size.mjs
766 var import_i18n4 = __toESM(require_i18n(), 1);
767 function validateFileSize(file, maxUploadFileSize) {
768 if (file.size <= 0) {
769 throw new UploadError({
770 code: "EMPTY_FILE",
771 message: (0, import_i18n4.sprintf)(
772 // translators: %s: file name.
773 (0, import_i18n4.__)("%s: This file is empty."),
774 file.name
775 ),
776 file
777 });
778 }
779 if (maxUploadFileSize && file.size > maxUploadFileSize) {
780 throw new UploadError({
781 code: "SIZE_ABOVE_LIMIT",
782 message: (0, import_i18n4.sprintf)(
783 // translators: %s: file name.
784 (0, import_i18n4.__)(
785 "%s: This file exceeds the maximum upload size for this site."
786 ),
787 file.name
788 ),
789 file
790 });
791 }
792 }
793
794 // packages/upload-media/build-module/store/actions.mjs
795 function addItems({
796 files,
797 onChange,
798 onSuccess,
799 onError,
800 onBatchSuccess,
801 additionalData,
802 allowedTypes
803 }) {
804 return async ({ select: select2, dispatch }) => {
805 const batchId = v4_default();
806 for (const file of files) {
807 try {
808 validateMimeType(file, allowedTypes);
809 validateMimeTypeForUser(
810 file,
811 select2.getSettings().allowedMimeTypes
812 );
813 } catch (error) {
814 onError?.(error);
815 continue;
816 }
817 try {
818 validateFileSize(
819 file,
820 select2.getSettings().maxUploadFileSize
821 );
822 } catch (error) {
823 onError?.(error);
824 continue;
825 }
826 dispatch.addItem({
827 file,
828 batchId,
829 onChange,
830 onSuccess,
831 onBatchSuccess,
832 onError,
833 additionalData
834 });
835 }
836 };
837 }
838 function cancelItem(id, error, silent = false) {
839 return async ({ select: select2, dispatch }) => {
840 const item = select2.getItem(id);
841 if (!item) {
842 return;
843 }
844 item.abortController?.abort();
845 await vipsCancelOperations(id);
846 if (!silent) {
847 const { onError } = item;
848 onError?.(error ?? new Error("Upload cancelled"));
849 if (!onError && error) {
850 console.error("Upload cancelled", error);
851 }
852 }
853 dispatch({
854 type: Type.Cancel,
855 id,
856 error
857 });
858 dispatch.removeItem(id);
859 dispatch.revokeBlobUrls(id);
860 if (item.batchId && select2.isBatchUploaded(item.batchId)) {
861 item.onBatchSuccess?.();
862 }
863 };
864 }
865 function retryItem(id) {
866 return async ({ select: select2, dispatch }) => {
867 const item = select2.getItem(id);
868 if (!item) {
869 return;
870 }
871 if (!item.error) {
872 return;
873 }
874 dispatch({
875 type: Type.RetryItem,
876 id
877 });
878 dispatch.processItem(id);
879 };
880 }
881
882 // packages/upload-media/build-module/store/private-actions.mjs
883 var private_actions_exports = {};
884 __export(private_actions_exports, {
885 addItem: () => addItem,
886 addSideloadItem: () => addSideloadItem,
887 finalizeItem: () => finalizeItem,
888 finishOperation: () => finishOperation,
889 generateThumbnails: () => generateThumbnails,
890 getTranscodeImageOperation: () => getTranscodeImageOperation,
891 pauseItem: () => pauseItem,
892 pauseQueue: () => pauseQueue,
893 prepareItem: () => prepareItem,
894 processItem: () => processItem,
895 removeItem: () => removeItem,
896 resizeCropItem: () => resizeCropItem,
897 resumeQueue: () => resumeQueue,
898 revokeBlobUrls: () => revokeBlobUrls,
899 rotateItem: () => rotateItem,
900 sideloadItem: () => sideloadItem,
901 transcodeImageItem: () => transcodeImageItem,
902 updateItemProgress: () => updateItemProgress,
903 updateSettings: () => updateSettings,
904 uploadItem: () => uploadItem
905 });
906 var import_blob = __toESM(require_blob(), 1);
907
908 // packages/upload-media/build-module/heic-parser.mjs
909 var Reader = class {
910 view;
911 buffer;
912 pos;
913 constructor(buffer, offset = 0) {
914 this.buffer = buffer;
915 this.view = new DataView(buffer);
916 this.pos = offset;
917 }
918 u8() {
919 const v = this.view.getUint8(this.pos);
920 this.pos += 1;
921 return v;
922 }
923 u16() {
924 const v = this.view.getUint16(this.pos);
925 this.pos += 2;
926 return v;
927 }
928 u32() {
929 const v = this.view.getUint32(this.pos);
930 this.pos += 4;
931 return v;
932 }
933 u64() {
934 const hi = this.view.getUint32(this.pos);
935 const lo = this.view.getUint32(this.pos + 4);
936 this.pos += 8;
937 return hi * 4294967296 + lo;
938 }
939 /**
940 * Read a variable-width unsigned integer (0, 4 or 8 bytes).
941 *
942 * @param size Byte width to read (0, 4, or 8).
943 */
944 uN(size) {
945 if (size === 0) {
946 return 0;
947 }
948 if (size === 4) {
949 return this.u32();
950 }
951 if (size === 8) {
952 return this.u64();
953 }
954 throw new Error(`Unsupported uint size: ${size}`);
955 }
956 str(len) {
957 let s = "";
958 for (let i = 0; i < len; i++) {
959 s += String.fromCharCode(this.view.getUint8(this.pos + i));
960 }
961 this.pos += len;
962 return s;
963 }
964 bytes(len) {
965 const b = new Uint8Array(this.buffer, this.pos, len);
966 this.pos += len;
967 return new Uint8Array(b);
968 }
969 };
970 function readBox(r) {
971 if (r.pos + 8 > r.view.byteLength) {
972 return null;
973 }
974 const offset = r.pos;
975 let size = r.u32();
976 const type = r.str(4);
977 let headerSize = 8;
978 if (size === 1) {
979 size = r.u64();
980 headerSize = 16;
981 } else if (size === 0) {
982 size = r.view.byteLength - offset;
983 }
984 return { type, offset, size, headerSize };
985 }
986 function findBoxes(r, start, end) {
987 const boxes = [];
988 r.pos = start;
989 while (r.pos < end) {
990 const box = readBox(r);
991 if (!box || box.size < 8) {
992 break;
993 }
994 boxes.push(box);
995 r.pos = box.offset + box.size;
996 }
997 return boxes;
998 }
999 function findBox(r, start, end, type) {
1000 r.pos = start;
1001 while (r.pos < end) {
1002 const box = readBox(r);
1003 if (!box || box.size < 8) {
1004 break;
1005 }
1006 if (box.type === type) {
1007 return box;
1008 }
1009 r.pos = box.offset + box.size;
1010 }
1011 return void 0;
1012 }
1013 function parsePitm(r, box) {
1014 r.pos = box.offset + box.headerSize;
1015 const version = r.u8();
1016 r.pos += 3;
1017 return version === 0 ? r.u16() : r.u32();
1018 }
1019 function parseIloc(r, box) {
1020 r.pos = box.offset + box.headerSize;
1021 const version = r.u8();
1022 r.pos += 3;
1023 const byte1 = r.u8();
1024 const offsetSize = byte1 >> 4 & 15;
1025 const lengthSize = byte1 & 15;
1026 const byte2 = r.u8();
1027 const baseOffsetSize = byte2 >> 4 & 15;
1028 const indexSize = version >= 1 ? byte2 & 15 : 0;
1029 const itemCount = version < 2 ? r.u16() : r.u32();
1030 const items = /* @__PURE__ */ new Map();
1031 for (let i = 0; i < itemCount; i++) {
1032 const itemId = version < 2 ? r.u16() : r.u32();
1033 let constructionMethod = 0;
1034 if (version === 1 || version === 2) {
1035 const cm = r.u16();
1036 constructionMethod = cm & 15;
1037 }
1038 r.u16();
1039 const baseOffset = r.uN(baseOffsetSize);
1040 const extentCount = r.u16();
1041 const extents = [];
1042 for (let j = 0; j < extentCount; j++) {
1043 if (version >= 1) {
1044 r.uN(indexSize);
1045 }
1046 const extOffset = r.uN(offsetSize);
1047 const extLength = r.uN(lengthSize);
1048 extents.push({
1049 offset: baseOffset + extOffset,
1050 length: extLength
1051 });
1052 }
1053 items.set(itemId, { constructionMethod, extents });
1054 }
1055 return items;
1056 }
1057 function parseIpma(r, box) {
1058 r.pos = box.offset + box.headerSize;
1059 const vf = r.u32();
1060 const version = vf >>> 24;
1061 const flags = vf & 16777215;
1062 const largeIndex = (flags & 1) !== 0;
1063 const entryCount = r.u32();
1064 const associations = /* @__PURE__ */ new Map();
1065 for (let i = 0; i < entryCount; i++) {
1066 const itemId = version < 1 ? r.u16() : r.u32();
1067 const assocCount = r.u8();
1068 const indices = [];
1069 for (let j = 0; j < assocCount; j++) {
1070 if (largeIndex) {
1071 indices.push(r.u16() & 32767);
1072 } else {
1073 indices.push(r.u8() & 127);
1074 }
1075 }
1076 associations.set(itemId, indices);
1077 }
1078 return associations;
1079 }
1080 function parseIspe(r, box) {
1081 r.pos = box.offset + box.headerSize + 4;
1082 return { width: r.u32(), height: r.u32() };
1083 }
1084 function parseIrot(r, box) {
1085 r.pos = box.offset + box.headerSize;
1086 return (r.u8() & 3) * 90;
1087 }
1088 function parseIinf(r, box) {
1089 r.pos = box.offset + box.headerSize;
1090 const version = r.u8();
1091 r.pos += 3;
1092 const entryCount = version === 0 ? r.u16() : r.u32();
1093 const itemTypes = /* @__PURE__ */ new Map();
1094 const entriesStart = r.pos;
1095 const boxEnd = box.offset + box.size;
1096 const infeBoxes = findBoxes(r, entriesStart, boxEnd);
1097 for (let i = 0; i < Math.min(entryCount, infeBoxes.length); i++) {
1098 const infe = infeBoxes[i];
1099 if (infe.type !== "infe") {
1100 continue;
1101 }
1102 r.pos = infe.offset + infe.headerSize;
1103 const infeVersion = r.u8();
1104 r.pos += 3;
1105 if (infeVersion >= 2) {
1106 const itemId = infeVersion === 2 ? r.u16() : r.u32();
1107 r.u16();
1108 const itemType = r.str(4);
1109 itemTypes.set(itemId, itemType);
1110 }
1111 }
1112 return itemTypes;
1113 }
1114 function parseIref(r, box, refType) {
1115 r.pos = box.offset + box.headerSize;
1116 const version = r.u8();
1117 r.pos += 3;
1118 const refs = /* @__PURE__ */ new Map();
1119 const boxEnd = box.offset + box.size;
1120 while (r.pos < boxEnd) {
1121 const refBox = readBox(r);
1122 if (!refBox || refBox.size < 8) {
1123 break;
1124 }
1125 r.pos = refBox.offset + refBox.headerSize;
1126 const fromId = version === 0 ? r.u16() : r.u32();
1127 const refCount = r.u16();
1128 const toIds = [];
1129 for (let i = 0; i < refCount; i++) {
1130 toIds.push(version === 0 ? r.u16() : r.u32());
1131 }
1132 if (refBox.type === refType) {
1133 refs.set(fromId, toIds);
1134 }
1135 r.pos = refBox.offset + refBox.size;
1136 }
1137 return refs;
1138 }
1139 function reverseBits32(n) {
1140 n = n >>> 1 & 1431655765 | (n & 1431655765) << 1;
1141 n = n >>> 2 & 858993459 | (n & 858993459) << 2;
1142 n = n >>> 4 & 252645135 | (n & 252645135) << 4;
1143 n = n >>> 8 & 16711935 | (n & 16711935) << 8;
1144 n = n >>> 16 | n << 16;
1145 return n >>> 0;
1146 }
1147 function buildCodecString(r, recordOffset) {
1148 r.pos = recordOffset;
1149 r.u8();
1150 const byte1 = r.u8();
1151 const profileSpace = byte1 >> 6 & 3;
1152 const tierFlag = byte1 >> 5 & 1;
1153 const profileIdc = byte1 & 31;
1154 const compatFlags = r.u32();
1155 const constraintBytes = r.bytes(6);
1156 const levelIdc = r.u8();
1157 const spacePrefix = profileSpace > 0 ? String.fromCharCode(64 + profileSpace) : "";
1158 const compatHex = reverseBits32(compatFlags).toString(16).toUpperCase();
1159 const tierChar = tierFlag ? "H" : "L";
1160 let lastNonZero = -1;
1161 for (let i = 5; i >= 0; i--) {
1162 if (constraintBytes[i] !== 0) {
1163 lastNonZero = i;
1164 break;
1165 }
1166 }
1167 let constraintStr = "";
1168 if (lastNonZero >= 0) {
1169 const parts = [];
1170 for (let i = 0; i <= lastNonZero; i++) {
1171 parts.push(constraintBytes[i].toString(16).toUpperCase());
1172 }
1173 constraintStr = "." + parts.join(".");
1174 }
1175 return `hvc1.${spacePrefix}${profileIdc}.${compatHex}.${tierChar}${levelIdc}${constraintStr}`;
1176 }
1177 function readItemData(buffer, loc, idatOffset) {
1178 const baseOffset = loc.constructionMethod === 1 ? idatOffset : 0;
1179 if (loc.extents.length === 1) {
1180 const ext = loc.extents[0];
1181 const start = baseOffset + ext.offset;
1182 return new Uint8Array(buffer.slice(start, start + ext.length));
1183 }
1184 let totalLength = 0;
1185 for (const ext of loc.extents) {
1186 totalLength += ext.length;
1187 }
1188 const data = new Uint8Array(totalLength);
1189 let pos = 0;
1190 for (const ext of loc.extents) {
1191 const start = baseOffset + ext.offset;
1192 data.set(
1193 new Uint8Array(buffer.slice(start, start + ext.length)),
1194 pos
1195 );
1196 pos += ext.length;
1197 }
1198 return data;
1199 }
1200 function findHvcProperties(propIndices, properties) {
1201 let hvcCBox;
1202 let ispeBox;
1203 let irotBox;
1204 for (const idx of propIndices) {
1205 if (idx < 1 || idx > properties.length) {
1206 continue;
1207 }
1208 const prop = properties[idx - 1];
1209 if (prop.type === "hvcC" && !hvcCBox) {
1210 hvcCBox = prop;
1211 }
1212 if (prop.type === "ispe" && !ispeBox) {
1213 ispeBox = prop;
1214 }
1215 if (prop.type === "irot" && !irotBox) {
1216 irotBox = prop;
1217 }
1218 }
1219 if (!hvcCBox) {
1220 throw new Error("No HEVC configuration (hvcC) found");
1221 }
1222 if (!ispeBox) {
1223 throw new Error("No image dimensions (ispe) found");
1224 }
1225 return { hvcCBox, ispeBox, irotBox };
1226 }
1227 function parseHeic(buffer) {
1228 const r = new Reader(buffer);
1229 const fileEnd = buffer.byteLength;
1230 const metaBox = findBox(r, 0, fileEnd, "meta");
1231 if (!metaBox) {
1232 throw new Error("No meta box found in HEIC file");
1233 }
1234 const metaChildStart = metaBox.offset + metaBox.headerSize + 4;
1235 const metaEnd = metaBox.offset + metaBox.size;
1236 const children = findBoxes(r, metaChildStart, metaEnd);
1237 const pitmBox = children.find((b) => b.type === "pitm");
1238 const ilocBox = children.find((b) => b.type === "iloc");
1239 const iprpBox = children.find((b) => b.type === "iprp");
1240 const iinfBox = children.find((b) => b.type === "iinf");
1241 const irefBox = children.find((b) => b.type === "iref");
1242 const idatBox = children.find((b) => b.type === "idat");
1243 const idatOffset = idatBox ? idatBox.offset + idatBox.headerSize : 0;
1244 if (!pitmBox || !ilocBox || !iprpBox) {
1245 throw new Error("Missing required boxes (pitm, iloc, iprp) in HEIC");
1246 }
1247 const primaryId = parsePitm(r, pitmBox);
1248 const locations = parseIloc(r, ilocBox);
1249 const iprpStart = iprpBox.offset + iprpBox.headerSize;
1250 const iprpEnd = iprpBox.offset + iprpBox.size;
1251 const iprpChildren = findBoxes(r, iprpStart, iprpEnd);
1252 const ipcoBox = iprpChildren.find((b) => b.type === "ipco");
1253 const ipmaBox = iprpChildren.find((b) => b.type === "ipma");
1254 if (!ipcoBox || !ipmaBox) {
1255 throw new Error("Missing ipco or ipma in HEIC properties");
1256 }
1257 const allAssoc = parseIpma(r, ipmaBox);
1258 const ipcoStart = ipcoBox.offset + ipcoBox.headerSize;
1259 const ipcoEnd = ipcoBox.offset + ipcoBox.size;
1260 const properties = findBoxes(r, ipcoStart, ipcoEnd);
1261 let primaryItemType = "hvc1";
1262 if (iinfBox) {
1263 const itemTypes = parseIinf(r, iinfBox);
1264 const t = itemTypes.get(primaryId);
1265 if (t) {
1266 primaryItemType = t;
1267 }
1268 }
1269 if (primaryItemType === "grid") {
1270 return parseGridImage(
1271 r,
1272 buffer,
1273 primaryId,
1274 locations,
1275 allAssoc,
1276 properties,
1277 irefBox,
1278 idatOffset
1279 );
1280 }
1281 const primaryLoc = locations.get(primaryId);
1282 if (!primaryLoc || primaryLoc.extents.length === 0) {
1283 throw new Error(`No location data for primary item ${primaryId}`);
1284 }
1285 const primaryPropIndices = allAssoc.get(primaryId);
1286 if (!primaryPropIndices || primaryPropIndices.length === 0) {
1287 throw new Error("No property associations for primary item");
1288 }
1289 const { hvcCBox, ispeBox, irotBox } = findHvcProperties(
1290 primaryPropIndices,
1291 properties
1292 );
1293 const hvcCDataStart = hvcCBox.offset + hvcCBox.headerSize;
1294 const hvcCDataSize = hvcCBox.size - hvcCBox.headerSize;
1295 const description = new Uint8Array(
1296 buffer.slice(hvcCDataStart, hvcCDataStart + hvcCDataSize)
1297 );
1298 const codecString = buildCodecString(r, hvcCDataStart);
1299 const { width, height } = parseIspe(r, ispeBox);
1300 const rotation = irotBox ? parseIrot(r, irotBox) : 0;
1301 return {
1302 codecString,
1303 description,
1304 tiles: [
1305 {
1306 data: readItemData(buffer, primaryLoc, idatOffset),
1307 x: 0,
1308 y: 0
1309 }
1310 ],
1311 tileWidth: width,
1312 tileHeight: height,
1313 outputWidth: width,
1314 outputHeight: height,
1315 rotation
1316 };
1317 }
1318 function parseGridImage(r, buffer, gridItemId, locations, allAssoc, properties, irefBox, idatOffset) {
1319 const gridLoc = locations.get(gridItemId);
1320 if (!gridLoc || gridLoc.extents.length === 0) {
1321 throw new Error("No location data for grid item");
1322 }
1323 const gridData = readItemData(buffer, gridLoc, idatOffset);
1324 const largeFields = gridData.length > 1 && (gridData[1] & 1) !== 0;
1325 const minGridSize = largeFields ? 12 : 8;
1326 if (gridData.length < minGridSize) {
1327 throw new Error(
1328 `Grid descriptor too short: ${gridData.length} bytes`
1329 );
1330 }
1331 const rows = gridData[2] + 1;
1332 const columns = gridData[3] + 1;
1333 const gv = new DataView(gridData.buffer, gridData.byteOffset);
1334 let outputWidth;
1335 let outputHeight;
1336 if (largeFields) {
1337 outputWidth = gv.getUint32(4);
1338 outputHeight = gv.getUint32(8);
1339 } else {
1340 outputWidth = gv.getUint16(4);
1341 outputHeight = gv.getUint16(6);
1342 }
1343 if (!irefBox) {
1344 throw new Error("Grid image requires iref box");
1345 }
1346 const dimgRefs = parseIref(r, irefBox, "dimg");
1347 const tileItemIds = dimgRefs.get(gridItemId);
1348 if (!tileItemIds || tileItemIds.length === 0) {
1349 throw new Error("No tile references found for grid item");
1350 }
1351 const expectedTiles = rows * columns;
1352 if (tileItemIds.length < expectedTiles) {
1353 throw new Error(
1354 `Grid expects ${expectedTiles} tiles but found ${tileItemIds.length}`
1355 );
1356 }
1357 const firstTileProps = allAssoc.get(tileItemIds[0]);
1358 if (!firstTileProps || firstTileProps.length === 0) {
1359 throw new Error("No property associations for tile item");
1360 }
1361 const { hvcCBox, ispeBox } = findHvcProperties(
1362 firstTileProps,
1363 properties
1364 );
1365 const gridProps = allAssoc.get(gridItemId) || [];
1366 let irotBox;
1367 for (const idx of gridProps) {
1368 if (idx >= 1 && idx <= properties.length) {
1369 const prop = properties[idx - 1];
1370 if (prop.type === "irot") {
1371 irotBox = prop;
1372 break;
1373 }
1374 }
1375 }
1376 const hvcCDataStart = hvcCBox.offset + hvcCBox.headerSize;
1377 const hvcCDataSize = hvcCBox.size - hvcCBox.headerSize;
1378 const description = new Uint8Array(
1379 buffer.slice(hvcCDataStart, hvcCDataStart + hvcCDataSize)
1380 );
1381 const codecString = buildCodecString(r, hvcCDataStart);
1382 const { width: tileWidth, height: tileHeight } = parseIspe(r, ispeBox);
1383 const tiles = [];
1384 for (let row = 0; row < rows; row++) {
1385 for (let col = 0; col < columns; col++) {
1386 const tileIdx = row * columns + col;
1387 const tileId = tileItemIds[tileIdx];
1388 const tileLoc = locations.get(tileId);
1389 if (!tileLoc || tileLoc.extents.length === 0) {
1390 throw new Error(`No location data for tile item ${tileId}`);
1391 }
1392 tiles.push({
1393 data: readItemData(buffer, tileLoc, idatOffset),
1394 x: col * tileWidth,
1395 y: row * tileHeight
1396 });
1397 }
1398 }
1399 const rotation = irotBox ? parseIrot(r, irotBox) : 0;
1400 return {
1401 codecString,
1402 description,
1403 tiles,
1404 tileWidth,
1405 tileHeight,
1406 outputWidth,
1407 outputHeight,
1408 rotation
1409 };
1410 }
1411
1412 // packages/upload-media/build-module/canvas-utils.mjs
1413 async function canvasConvertToJpeg(file, quality = 0.82) {
1414 const baseName = getFileBasename(file.name);
1415 try {
1416 const bitmap = await createImageBitmap(file);
1417 try {
1418 const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
1419 const ctx = canvas.getContext("2d");
1420 if (!ctx) {
1421 throw new Error("Could not get canvas 2d context");
1422 }
1423 ctx.drawImage(bitmap, 0, 0);
1424 const jpegBlob = await canvas.convertToBlob({
1425 type: "image/jpeg",
1426 quality
1427 });
1428 return new File([jpegBlob], `${baseName}.jpg`, {
1429 type: "image/jpeg"
1430 });
1431 } finally {
1432 bitmap.close();
1433 }
1434 } catch {
1435 }
1436 if (typeof ImageDecoder !== "undefined") {
1437 const supported = await ImageDecoder.isTypeSupported(file.type);
1438 if (supported) {
1439 const decoder = new ImageDecoder({
1440 type: file.type,
1441 data: file.stream()
1442 });
1443 try {
1444 const { image: videoFrame } = await decoder.decode();
1445 try {
1446 const canvas = new OffscreenCanvas(
1447 videoFrame.displayWidth,
1448 videoFrame.displayHeight
1449 );
1450 const ctx = canvas.getContext("2d");
1451 if (!ctx) {
1452 throw new Error("Could not get canvas 2d context");
1453 }
1454 ctx.drawImage(videoFrame, 0, 0);
1455 const jpegBlob = await canvas.convertToBlob({
1456 type: "image/jpeg",
1457 quality
1458 });
1459 return new File([jpegBlob], `${baseName}.jpg`, {
1460 type: "image/jpeg"
1461 });
1462 } finally {
1463 videoFrame.close();
1464 }
1465 } finally {
1466 decoder.close();
1467 }
1468 }
1469 }
1470 if (typeof VideoDecoder !== "undefined") {
1471 try {
1472 const heicData = parseHeic(await file.arrayBuffer());
1473 const support = await VideoDecoder.isConfigSupported({
1474 codec: heicData.codecString
1475 });
1476 if (support.supported) {
1477 const canvas = new OffscreenCanvas(
1478 heicData.outputWidth,
1479 heicData.outputHeight
1480 );
1481 const ctx = canvas.getContext("2d");
1482 if (!ctx) {
1483 throw new Error("Could not get canvas 2d context");
1484 }
1485 for (const tile of heicData.tiles) {
1486 const frame = await decodeHevcFrame(
1487 heicData.codecString,
1488 heicData.description,
1489 heicData.tileWidth,
1490 heicData.tileHeight,
1491 tile.data
1492 );
1493 try {
1494 ctx.drawImage(frame, tile.x, tile.y);
1495 } finally {
1496 frame.close();
1497 }
1498 }
1499 const outputCanvas = applyRotation(canvas, heicData.rotation);
1500 const jpegBlob = await outputCanvas.convertToBlob({
1501 type: "image/jpeg",
1502 quality
1503 });
1504 return new File([jpegBlob], `${baseName}.jpg`, {
1505 type: "image/jpeg"
1506 });
1507 }
1508 } catch {
1509 }
1510 }
1511 throw new Error(
1512 "This browser cannot decode HEIC images. Please use Safari or convert to JPEG before uploading."
1513 );
1514 }
1515 function applyRotation(source, rotation) {
1516 if (rotation === 0) {
1517 return source;
1518 }
1519 const swap = rotation === 90 || rotation === 270;
1520 const w = swap ? source.height : source.width;
1521 const h = swap ? source.width : source.height;
1522 const rotated = new OffscreenCanvas(w, h);
1523 const ctx = rotated.getContext("2d");
1524 if (!ctx) {
1525 return source;
1526 }
1527 ctx.translate(w / 2, h / 2);
1528 ctx.rotate(-rotation * Math.PI / 180);
1529 ctx.drawImage(source, -source.width / 2, -source.height / 2);
1530 return rotated;
1531 }
1532 function decodeHevcFrame(codec, description, width, height, data) {
1533 return new Promise((resolve, reject) => {
1534 const decoder = new VideoDecoder({
1535 output: (frame) => {
1536 decoder.close();
1537 resolve(frame);
1538 },
1539 error: (e) => {
1540 if (decoder.state !== "closed") {
1541 decoder.close();
1542 }
1543 reject(e);
1544 }
1545 });
1546 decoder.configure({
1547 codec,
1548 codedWidth: width,
1549 codedHeight: height,
1550 description
1551 });
1552 decoder.decode(
1553 new EncodedVideoChunk({
1554 type: "key",
1555 timestamp: 0,
1556 data
1557 })
1558 );
1559 decoder.flush().catch((e) => {
1560 if (decoder.state !== "closed") {
1561 decoder.close();
1562 }
1563 reject(e);
1564 });
1565 });
1566 }
1567
1568 // packages/upload-media/build-module/feature-detection.mjs
1569 var cachedResult = null;
1570 function detectClientSideMediaSupport() {
1571 if (cachedResult !== null) {
1572 return cachedResult;
1573 }
1574 if (typeof WebAssembly === "undefined") {
1575 cachedResult = {
1576 supported: false,
1577 reason: "WebAssembly is not supported in this browser."
1578 };
1579 return cachedResult;
1580 }
1581 if (typeof SharedArrayBuffer === "undefined") {
1582 cachedResult = {
1583 supported: false,
1584 reason: "SharedArrayBuffer is not available. This may be due to missing cross-origin isolation headers."
1585 };
1586 return cachedResult;
1587 }
1588 if (typeof Worker === "undefined") {
1589 cachedResult = {
1590 supported: false,
1591 reason: "Web Workers are not supported in this browser."
1592 };
1593 return cachedResult;
1594 }
1595 if (typeof navigator !== "undefined" && "deviceMemory" in navigator && navigator.deviceMemory <= 2) {
1596 cachedResult = {
1597 supported: false,
1598 reason: "Device has insufficient memory for client-side media processing."
1599 };
1600 return cachedResult;
1601 }
1602 if (typeof navigator !== "undefined" && "hardwareConcurrency" in navigator && navigator.hardwareConcurrency < 2) {
1603 cachedResult = {
1604 supported: false,
1605 reason: "Device has insufficient CPU cores for client-side media processing."
1606 };
1607 return cachedResult;
1608 }
1609 if (typeof navigator !== "undefined") {
1610 const connection = navigator.connection;
1611 if (connection) {
1612 if (connection.saveData) {
1613 cachedResult = {
1614 supported: false,
1615 reason: "Data saver mode is enabled."
1616 };
1617 return cachedResult;
1618 }
1619 if (connection.effectiveType === "slow-2g" || connection.effectiveType === "2g") {
1620 cachedResult = {
1621 supported: false,
1622 reason: "Network connection is too slow for client-side media processing."
1623 };
1624 return cachedResult;
1625 }
1626 }
1627 }
1628 if (typeof window !== "undefined") {
1629 try {
1630 const testBlob = new Blob([""], {
1631 type: "application/javascript"
1632 });
1633 const testUrl = URL.createObjectURL(testBlob);
1634 try {
1635 const testWorker = new Worker(testUrl);
1636 testWorker.terminate();
1637 } finally {
1638 URL.revokeObjectURL(testUrl);
1639 }
1640 } catch {
1641 cachedResult = {
1642 supported: false,
1643 reason: "The site's Content Security Policy (CSP) does not allow blob: workers. The worker-src directive must include blob: to enable client-side media processing."
1644 };
1645 return cachedResult;
1646 }
1647 }
1648 cachedResult = { supported: true };
1649 return cachedResult;
1650 }
1651 function isClientSideMediaSupported() {
1652 return detectClientSideMediaSupport().supported;
1653 }
1654 function isHeicCanvasSupported() {
1655 return typeof createImageBitmap !== "undefined" && typeof OffscreenCanvas !== "undefined";
1656 }
1657 function clearFeatureDetectionCache() {
1658 cachedResult = null;
1659 }
1660
1661 // packages/upload-media/build-module/stub-file.mjs
1662 var StubFile = class extends File {
1663 constructor(fileName = "stub-file") {
1664 super([], fileName);
1665 }
1666 };
1667
1668 // packages/upload-media/build-module/store/private-actions.mjs
1669 var DEFAULT_OUTPUT_QUALITY = 0.82;
1670 function addItem({
1671 file: fileOrBlob,
1672 batchId,
1673 onChange,
1674 onSuccess,
1675 onBatchSuccess,
1676 onError,
1677 additionalData = {},
1678 sourceUrl,
1679 sourceAttachmentId,
1680 abortController,
1681 operations
1682 }) {
1683 return async ({ dispatch }) => {
1684 const itemId = v4_default();
1685 const file = convertBlobToFile(fileOrBlob);
1686 let blobUrl;
1687 if (!(file instanceof StubFile)) {
1688 blobUrl = (0, import_blob.createBlobURL)(file);
1689 dispatch({
1690 type: Type.CacheBlobUrl,
1691 id: itemId,
1692 blobUrl
1693 });
1694 }
1695 dispatch({
1696 type: Type.Add,
1697 item: {
1698 id: itemId,
1699 batchId,
1700 status: ItemStatus.Processing,
1701 sourceFile: cloneFile(file),
1702 file,
1703 attachment: {
1704 url: blobUrl
1705 },
1706 additionalData: {
1707 generate_sub_sizes: false,
1708 ...additionalData
1709 },
1710 onChange,
1711 onSuccess,
1712 onBatchSuccess,
1713 onError,
1714 sourceUrl,
1715 sourceAttachmentId,
1716 abortController: abortController || new AbortController(),
1717 operations: Array.isArray(operations) ? operations : [OperationType.Prepare]
1718 }
1719 });
1720 dispatch.processItem(itemId);
1721 };
1722 }
1723 function addSideloadItem({
1724 file,
1725 onChange,
1726 additionalData,
1727 operations,
1728 batchId,
1729 parentId
1730 }) {
1731 return ({ dispatch }) => {
1732 const itemId = v4_default();
1733 dispatch({
1734 type: Type.Add,
1735 item: {
1736 id: itemId,
1737 batchId,
1738 status: ItemStatus.Processing,
1739 sourceFile: cloneFile(file),
1740 file,
1741 onChange,
1742 additionalData: {
1743 ...additionalData
1744 },
1745 parentId,
1746 operations: Array.isArray(operations) ? operations : [OperationType.Prepare],
1747 abortController: new AbortController()
1748 }
1749 });
1750 dispatch.processItem(itemId);
1751 };
1752 }
1753 function processItem(id) {
1754 return async ({ select: select2, dispatch }) => {
1755 if (select2.isPaused()) {
1756 return;
1757 }
1758 const item = select2.getItem(id);
1759 if (!item) {
1760 return;
1761 }
1762 const {
1763 attachment,
1764 onChange,
1765 onSuccess,
1766 onBatchSuccess,
1767 batchId,
1768 parentId
1769 } = item;
1770 const operation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0];
1771 const operationArgs = Array.isArray(item.operations?.[0]) ? item.operations[0][1] : void 0;
1772 if (operation === OperationType.Upload) {
1773 const settings = select2.getSettings();
1774 const activeCount = select2.getActiveUploadCount();
1775 if (activeCount >= settings.maxConcurrentUploads) {
1776 return;
1777 }
1778 }
1779 if (operation === OperationType.ResizeCrop || operation === OperationType.Rotate) {
1780 const settings = select2.getSettings();
1781 const activeCount = select2.getActiveImageProcessingCount();
1782 if (activeCount >= settings.maxConcurrentImageProcessing) {
1783 return;
1784 }
1785 }
1786 if (attachment) {
1787 const isHeicUrl = attachment.url && /\.hei[cf]$/i.test(attachment.url);
1788 if (!isHeicUrl) {
1789 onChange?.([attachment]);
1790 }
1791 }
1792 if (!operation) {
1793 if (parentId || !parentId && !select2.hasPendingItemsByParentId(id)) {
1794 if (attachment) {
1795 onSuccess?.([attachment]);
1796 }
1797 dispatch.removeItem(id);
1798 dispatch.revokeBlobUrls(id);
1799 if (batchId && select2.isBatchUploaded(batchId)) {
1800 onBatchSuccess?.();
1801 }
1802 }
1803 if (parentId && batchId && select2.isBatchUploaded(batchId)) {
1804 const parentItem = select2.getItem(parentId);
1805 if (!parentItem) {
1806 return;
1807 }
1808 if (parentItem.operations && parentItem.operations.length > 0) {
1809 dispatch.processItem(parentId);
1810 return;
1811 }
1812 if (attachment) {
1813 parentItem.onSuccess?.([attachment]);
1814 }
1815 dispatch.removeItem(parentId);
1816 dispatch.revokeBlobUrls(parentId);
1817 if (parentItem.batchId && select2.isBatchUploaded(parentItem.batchId)) {
1818 parentItem.onBatchSuccess?.();
1819 }
1820 }
1821 return;
1822 }
1823 if (operation === OperationType.Finalize && select2.hasPendingItemsByParentId(id)) {
1824 return;
1825 }
1826 dispatch({
1827 type: Type.OperationStart,
1828 id,
1829 operation
1830 });
1831 switch (operation) {
1832 case OperationType.Prepare:
1833 dispatch.prepareItem(item.id);
1834 break;
1835 case OperationType.ResizeCrop:
1836 dispatch.resizeCropItem(
1837 item.id,
1838 operationArgs
1839 );
1840 break;
1841 case OperationType.Rotate:
1842 dispatch.rotateItem(
1843 item.id,
1844 operationArgs
1845 );
1846 break;
1847 case OperationType.TranscodeImage:
1848 dispatch.transcodeImageItem(
1849 item.id,
1850 operationArgs
1851 );
1852 break;
1853 case OperationType.Upload:
1854 if (item.parentId) {
1855 dispatch.sideloadItem(id);
1856 } else {
1857 dispatch.uploadItem(id);
1858 }
1859 break;
1860 case OperationType.ThumbnailGeneration:
1861 dispatch.generateThumbnails(id);
1862 break;
1863 case OperationType.Finalize:
1864 dispatch.finalizeItem(id);
1865 break;
1866 }
1867 };
1868 }
1869 function pauseQueue() {
1870 return {
1871 type: Type.PauseQueue
1872 };
1873 }
1874 function resumeQueue() {
1875 return async ({ select: select2, dispatch }) => {
1876 dispatch({
1877 type: Type.ResumeQueue
1878 });
1879 for (const item of select2.getAllItems()) {
1880 dispatch.processItem(item.id);
1881 }
1882 };
1883 }
1884 function pauseItem(id) {
1885 return async ({ dispatch }) => {
1886 dispatch({
1887 type: Type.PauseItem,
1888 id
1889 });
1890 };
1891 }
1892 function removeItem(id) {
1893 return async ({ select: select2, dispatch }) => {
1894 const item = select2.getItem(id);
1895 if (!item) {
1896 return;
1897 }
1898 dispatch({
1899 type: Type.Remove,
1900 id
1901 });
1902 if (select2.getAllItems().length === 0) {
1903 terminateVipsWorker();
1904 }
1905 };
1906 }
1907 function finishOperation(id, updates) {
1908 return async ({ select: select2, dispatch }) => {
1909 const item = select2.getItem(id);
1910 const previousOperation = item?.currentOperation;
1911 dispatch({
1912 type: Type.OperationFinish,
1913 id,
1914 item: updates
1915 });
1916 dispatch.processItem(id);
1917 if (previousOperation === OperationType.Upload) {
1918 const pendingUploads = select2.getPendingUploads();
1919 for (const pendingItem of pendingUploads) {
1920 dispatch.processItem(pendingItem.id);
1921 }
1922 }
1923 if (previousOperation === OperationType.ResizeCrop || previousOperation === OperationType.Rotate) {
1924 const pendingItems = select2.getPendingImageProcessing();
1925 for (const pendingItem of pendingItems) {
1926 dispatch.processItem(pendingItem.id);
1927 }
1928 }
1929 };
1930 }
1931 var VALID_IMAGE_FORMATS = ["jpeg", "webp", "avif", "png", "gif"];
1932 function isValidImageFormat(format) {
1933 return VALID_IMAGE_FORMATS.includes(format);
1934 }
1935 async function getTranscodeImageOperation(file, outputMimeType, interlaced = false) {
1936 if (file.type === "image/png" && outputMimeType === "image/jpeg") {
1937 const blobUrl = (0, import_blob.createBlobURL)(file);
1938 try {
1939 const hasAlpha = await vipsHasTransparency(blobUrl);
1940 if (hasAlpha) {
1941 return null;
1942 }
1943 } catch {
1944 return null;
1945 } finally {
1946 (0, import_blob.revokeBlobURL)(blobUrl);
1947 }
1948 }
1949 const formatPart = outputMimeType.split("/")[1];
1950 if (!isValidImageFormat(formatPart)) {
1951 return null;
1952 }
1953 return [
1954 OperationType.TranscodeImage,
1955 {
1956 outputFormat: formatPart,
1957 outputQuality: DEFAULT_OUTPUT_QUALITY,
1958 interlaced
1959 }
1960 ];
1961 }
1962 function prepareItem(id) {
1963 return async ({ select: select2, dispatch }) => {
1964 const item = select2.getItem(id);
1965 if (!item) {
1966 return;
1967 }
1968 const { file } = item;
1969 const operations = [];
1970 const settings = select2.getSettings();
1971 let heicJpeg = null;
1972 const isImage = file.type.startsWith("image/");
1973 const isVipsSupported = CLIENT_SIDE_SUPPORTED_MIME_TYPES.includes(
1974 file.type
1975 );
1976 const isHeic = HEIC_MIME_TYPES.includes(file.type);
1977 if (isImage && isVipsSupported) {
1978 const { bigImageSizeThreshold } = settings;
1979 if (bigImageSizeThreshold) {
1980 operations.push([
1981 OperationType.ResizeCrop,
1982 {
1983 resize: {
1984 width: bigImageSizeThreshold,
1985 height: bigImageSizeThreshold
1986 },
1987 isThresholdResize: true
1988 }
1989 ]);
1990 }
1991 operations.push(
1992 OperationType.Upload,
1993 OperationType.ThumbnailGeneration,
1994 OperationType.Finalize
1995 );
1996 } else if (isImage && isHeic) {
1997 try {
1998 heicJpeg = await canvasConvertToJpeg(
1999 file,
2000 settings.imageQuality ?? DEFAULT_OUTPUT_QUALITY
2001 );
2002 } catch {
2003 dispatch.cancelItem(
2004 id,
2005 new UploadError({
2006 code: "HEIC_DECODE_ERROR",
2007 message: "This browser cannot decode HEIC images and the server does not support them either. Please convert to JPEG before uploading.",
2008 file
2009 })
2010 );
2011 return;
2012 }
2013 operations.push(
2014 OperationType.Upload,
2015 OperationType.ThumbnailGeneration,
2016 OperationType.Finalize
2017 );
2018 } else {
2019 operations.push(OperationType.Upload);
2020 }
2021 dispatch({
2022 type: Type.AddOperations,
2023 id,
2024 operations
2025 });
2026 let updates = {};
2027 if (isHeic && heicJpeg) {
2028 const vipsAvailable = isClientSideMediaSupported();
2029 updates = {
2030 file: heicJpeg,
2031 sourceFile: heicJpeg,
2032 originalHeicFile: item.file,
2033 additionalData: {
2034 ...item.additionalData,
2035 generate_sub_sizes: !vipsAvailable,
2036 convert_format: true
2037 }
2038 };
2039 } else if (!isVipsSupported || !isImage) {
2040 updates = {
2041 additionalData: {
2042 ...item.additionalData,
2043 generate_sub_sizes: true,
2044 convert_format: true
2045 }
2046 };
2047 }
2048 dispatch.finishOperation(id, updates);
2049 };
2050 }
2051 function uploadItem(id) {
2052 return async ({ select: select2, dispatch }) => {
2053 const item = select2.getItem(id);
2054 if (!item) {
2055 return;
2056 }
2057 select2.getSettings().mediaUpload({
2058 filesList: [item.file],
2059 additionalData: item.additionalData,
2060 signal: item.abortController?.signal,
2061 onFileChange: ([attachment]) => {
2062 if (attachment && !(0, import_blob.isBlobURL)(attachment.url)) {
2063 dispatch.finishOperation(id, {
2064 attachment
2065 });
2066 }
2067 },
2068 onSuccess: ([attachment]) => {
2069 dispatch.finishOperation(id, {
2070 attachment
2071 });
2072 },
2073 onError: (error) => {
2074 dispatch.cancelItem(id, error);
2075 }
2076 });
2077 };
2078 }
2079 function sideloadItem(id) {
2080 return async ({ select: select2, dispatch }) => {
2081 const item = select2.getItem(id);
2082 if (!item) {
2083 return;
2084 }
2085 const { post, ...additionalData } = item.additionalData;
2086 const mediaSideload = select2.getSettings().mediaSideload;
2087 if (!mediaSideload) {
2088 dispatch.finishOperation(id, {});
2089 return;
2090 }
2091 mediaSideload({
2092 file: item.file,
2093 attachmentId: post,
2094 additionalData,
2095 signal: item.abortController?.signal,
2096 onSuccess: (subSize) => {
2097 if (item.parentId) {
2098 dispatch({
2099 type: Type.AccumulateSubSize,
2100 id: item.parentId,
2101 subSize
2102 });
2103 }
2104 dispatch.finishOperation(id, {});
2105 },
2106 onError: (error) => {
2107 dispatch.cancelItem(id, error);
2108 }
2109 });
2110 };
2111 }
2112 function resizeCropItem(id, args) {
2113 return async ({ select: select2, dispatch }) => {
2114 const item = select2.getItem(id);
2115 if (!item) {
2116 return;
2117 }
2118 if (!args?.resize) {
2119 dispatch.finishOperation(id, {
2120 file: item.file
2121 });
2122 return;
2123 }
2124 const addSuffix = Boolean(item.parentId);
2125 const scaledSuffix = Boolean(args.isThresholdResize);
2126 try {
2127 const file = await vipsResizeImage(
2128 item.id,
2129 item.file,
2130 args.resize,
2131 false,
2132 // smartCrop
2133 addSuffix,
2134 item.abortController?.signal,
2135 scaledSuffix
2136 );
2137 const blobUrl = (0, import_blob.createBlobURL)(file);
2138 dispatch({
2139 type: Type.CacheBlobUrl,
2140 id,
2141 blobUrl
2142 });
2143 dispatch.finishOperation(id, {
2144 file,
2145 attachment: {
2146 url: blobUrl
2147 }
2148 });
2149 } catch (error) {
2150 dispatch.cancelItem(
2151 id,
2152 new UploadError({
2153 code: "IMAGE_TRANSCODING_ERROR",
2154 message: "File could not be uploaded",
2155 file: item.file,
2156 cause: error instanceof Error ? error : void 0
2157 })
2158 );
2159 }
2160 };
2161 }
2162 function rotateItem(id, args) {
2163 return async ({ select: select2, dispatch }) => {
2164 const item = select2.getItem(id);
2165 if (!item) {
2166 return;
2167 }
2168 if (!args?.orientation || args.orientation === 1) {
2169 dispatch.finishOperation(id, {
2170 file: item.file
2171 });
2172 return;
2173 }
2174 try {
2175 const file = await vipsRotateImage(
2176 item.id,
2177 item.file,
2178 args.orientation,
2179 item.abortController?.signal
2180 );
2181 const blobUrl = (0, import_blob.createBlobURL)(file);
2182 dispatch({
2183 type: Type.CacheBlobUrl,
2184 id,
2185 blobUrl
2186 });
2187 dispatch.finishOperation(id, {
2188 file,
2189 attachment: {
2190 url: blobUrl
2191 }
2192 });
2193 } catch (error) {
2194 dispatch.cancelItem(
2195 id,
2196 new UploadError({
2197 code: "IMAGE_ROTATION_ERROR",
2198 message: "Image could not be rotated",
2199 file: item.file,
2200 cause: error instanceof Error ? error : void 0
2201 })
2202 );
2203 }
2204 };
2205 }
2206 function transcodeImageItem(id, args) {
2207 return async ({ select: select2, dispatch }) => {
2208 const item = select2.getItem(id);
2209 if (!item) {
2210 return;
2211 }
2212 if (!args?.outputFormat) {
2213 dispatch.finishOperation(id, {
2214 file: item.file
2215 });
2216 return;
2217 }
2218 const outputMimeType = `image/${args.outputFormat}`;
2219 const quality = args.outputQuality ?? DEFAULT_OUTPUT_QUALITY;
2220 const interlaced = args.interlaced ?? false;
2221 try {
2222 const file = await vipsConvertImageFormat(
2223 item.id,
2224 item.file,
2225 outputMimeType,
2226 quality,
2227 interlaced
2228 );
2229 const blobUrl = (0, import_blob.createBlobURL)(file);
2230 dispatch({
2231 type: Type.CacheBlobUrl,
2232 id,
2233 blobUrl
2234 });
2235 dispatch.finishOperation(id, {
2236 file,
2237 attachment: {
2238 url: blobUrl
2239 }
2240 });
2241 } catch (error) {
2242 dispatch.cancelItem(
2243 id,
2244 new UploadError({
2245 code: "MEDIA_TRANSCODING_ERROR",
2246 message: "Image could not be transcoded to the target format",
2247 file: item.file,
2248 cause: error instanceof Error ? error : void 0
2249 })
2250 );
2251 }
2252 };
2253 }
2254 function generateThumbnails(id) {
2255 return async ({ select: select2, dispatch }) => {
2256 const item = select2.getItem(id);
2257 if (!item) {
2258 return;
2259 }
2260 if (!item.attachment) {
2261 dispatch.finishOperation(id, {});
2262 return;
2263 }
2264 const attachment = item.attachment;
2265 const settings = select2.getSettings();
2266 if (item.originalHeicFile && attachment.id) {
2267 dispatch.addSideloadItem({
2268 file: item.originalHeicFile,
2269 batchId: v4_default(),
2270 parentId: item.id,
2271 additionalData: {
2272 post: attachment.id,
2273 image_size: "original-heic",
2274 convert_format: false
2275 },
2276 operations: [OperationType.Upload]
2277 });
2278 }
2279 {
2280 const needsRotation = attachment.exif_orientation && attachment.exif_orientation !== 1 && !item.file.name.includes("-scaled");
2281 if (needsRotation && attachment.id) {
2282 try {
2283 const rotatedFile = await vipsRotateImage(
2284 item.id,
2285 item.sourceFile,
2286 attachment.exif_orientation,
2287 item.abortController?.signal
2288 );
2289 dispatch.addSideloadItem({
2290 file: rotatedFile,
2291 batchId: v4_default(),
2292 parentId: item.id,
2293 additionalData: {
2294 post: attachment.id,
2295 image_size: "original",
2296 convert_format: false
2297 },
2298 operations: [OperationType.Upload]
2299 });
2300 } catch {
2301 console.warn(
2302 "Failed to rotate image, continuing with thumbnails"
2303 );
2304 }
2305 }
2306 }
2307 if (!item.parentId && attachment.missing_image_sizes && attachment.missing_image_sizes.length > 0) {
2308 const allImageSizes = settings.allImageSizes || {};
2309 const sizesToGenerate = attachment.missing_image_sizes;
2310 const thumbnailSource = item.sourceFile;
2311 const file = attachment.filename ? renameFile(thumbnailSource, attachment.filename) : thumbnailSource;
2312 const batchId = v4_default();
2313 const outputMimeType = attachment.image_output_format;
2314 const interlaced = attachment.image_save_progressive ?? false;
2315 let thumbnailTranscodeOperation = null;
2316 if (outputMimeType) {
2317 thumbnailTranscodeOperation = await getTranscodeImageOperation(
2318 thumbnailSource,
2319 outputMimeType,
2320 interlaced
2321 );
2322 }
2323 const dimensionGroups = /* @__PURE__ */ new Map();
2324 for (const name of sizesToGenerate) {
2325 const imageSize = allImageSizes[name];
2326 if (!imageSize) {
2327 console.warn(
2328 `Image size "${name}" not found in configuration`
2329 );
2330 continue;
2331 }
2332 const key = `${imageSize.width}x${imageSize.height}x${imageSize.crop}`;
2333 const group = dimensionGroups.get(key);
2334 if (group) {
2335 group.push(name);
2336 } else {
2337 dimensionGroups.set(key, [name]);
2338 }
2339 }
2340 for (const [, names] of dimensionGroups) {
2341 const imageSize = allImageSizes[names[0]];
2342 const thumbnailOperations = [
2343 [OperationType.ResizeCrop, { resize: imageSize }]
2344 ];
2345 if (thumbnailTranscodeOperation) {
2346 thumbnailOperations.push(thumbnailTranscodeOperation);
2347 }
2348 thumbnailOperations.push(OperationType.Upload);
2349 const imageSizeParam = names.length === 1 ? names[0] : names;
2350 dispatch.addSideloadItem({
2351 file,
2352 batchId,
2353 parentId: item.id,
2354 additionalData: {
2355 // Sideloading does not use the parent post ID but the
2356 // attachment ID as the image sizes need to be added to it.
2357 post: attachment.id,
2358 image_size: imageSizeParam,
2359 convert_format: false
2360 },
2361 operations: thumbnailOperations
2362 });
2363 }
2364 {
2365 const { bigImageSizeThreshold } = settings;
2366 if (bigImageSizeThreshold && attachment.id) {
2367 const bitmap = await createImageBitmap(thumbnailSource);
2368 const needsScaling = bitmap.width > bigImageSizeThreshold || bitmap.height > bigImageSizeThreshold;
2369 bitmap.close();
2370 if (needsScaling) {
2371 const sourceForScaled = attachment.filename ? renameFile(thumbnailSource, attachment.filename) : thumbnailSource;
2372 const scaledOperations = [
2373 [
2374 OperationType.ResizeCrop,
2375 {
2376 resize: {
2377 width: bigImageSizeThreshold,
2378 height: bigImageSizeThreshold
2379 },
2380 isThresholdResize: true
2381 }
2382 ]
2383 ];
2384 if (thumbnailTranscodeOperation) {
2385 scaledOperations.push(
2386 thumbnailTranscodeOperation
2387 );
2388 }
2389 scaledOperations.push(OperationType.Upload);
2390 dispatch.addSideloadItem({
2391 file: sourceForScaled,
2392 batchId,
2393 parentId: item.id,
2394 additionalData: {
2395 post: attachment.id,
2396 image_size: "scaled",
2397 convert_format: false
2398 },
2399 operations: scaledOperations
2400 });
2401 }
2402 }
2403 }
2404 }
2405 dispatch.finishOperation(id, {});
2406 };
2407 }
2408 function finalizeItem(id) {
2409 return async ({ select: select2, dispatch }) => {
2410 const item = select2.getItem(id);
2411 if (!item) {
2412 return;
2413 }
2414 const attachment = item.attachment;
2415 const { mediaFinalize } = select2.getSettings();
2416 if (attachment?.id && mediaFinalize) {
2417 try {
2418 await mediaFinalize(attachment.id, item.subSizes || []);
2419 } catch (error) {
2420 console.warn("Media finalization failed:", error);
2421 }
2422 }
2423 dispatch.finishOperation(id, {});
2424 };
2425 }
2426 function revokeBlobUrls(id) {
2427 return async ({ select: select2, dispatch }) => {
2428 const blobUrls = select2.getBlobUrls(id);
2429 for (const blobUrl of blobUrls) {
2430 (0, import_blob.revokeBlobURL)(blobUrl);
2431 }
2432 dispatch({
2433 type: Type.RevokeBlobUrls,
2434 id
2435 });
2436 };
2437 }
2438 function updateItemProgress(id, progress) {
2439 return async ({ dispatch }) => {
2440 dispatch({
2441 type: Type.UpdateProgress,
2442 id,
2443 progress
2444 });
2445 };
2446 }
2447 function updateSettings(settings) {
2448 return {
2449 type: Type.UpdateSettings,
2450 settings
2451 };
2452 }
2453
2454 // packages/upload-media/build-module/lock-unlock.mjs
2455 var import_private_apis = __toESM(require_private_apis(), 1);
2456 var { lock, unlock } = (0, import_private_apis.__dangerousOptInToUnstableAPIsOnlyForCoreModules)(
2457 "I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.",
2458 "@wordpress/upload-media"
2459 );
2460
2461 // packages/upload-media/build-module/store/index.mjs
2462 var storeConfig = {
2463 reducer: reducer_default,
2464 selectors: selectors_exports,
2465 actions: actions_exports
2466 };
2467 var store = (0, import_data.createReduxStore)(STORE_NAME, {
2468 reducer: reducer_default,
2469 selectors: selectors_exports,
2470 actions: actions_exports
2471 });
2472 if (!(0, import_data.select)(store)) {
2473 (0, import_data.register)(store);
2474 }
2475 unlock(store).registerPrivateActions(private_actions_exports);
2476 unlock(store).registerPrivateSelectors(private_selectors_exports);
2477
2478 // packages/upload-media/build-module/components/provider/index.mjs
2479 var import_element2 = __toESM(require_element(), 1);
2480 var import_data3 = __toESM(require_data(), 1);
2481
2482 // packages/upload-media/build-module/components/provider/with-registry-provider.mjs
2483 var import_element = __toESM(require_element(), 1);
2484 var import_data2 = __toESM(require_data(), 1);
2485 var import_compose = __toESM(require_compose(), 1);
2486 var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
2487 function getSubRegistry(subRegistries, registry, useSubRegistry) {
2488 if (!useSubRegistry) {
2489 return registry;
2490 }
2491 let subRegistry = subRegistries.get(registry);
2492 if (!subRegistry) {
2493 subRegistry = (0, import_data2.createRegistry)({}, registry);
2494 subRegistry.registerStore(STORE_NAME, storeConfig);
2495 subRegistries.set(registry, subRegistry);
2496 }
2497 return subRegistry;
2498 }
2499 var withRegistryProvider = (0, import_compose.createHigherOrderComponent)(
2500 (WrappedComponent) => ({ useSubRegistry = true, ...props }) => {
2501 const registry = (0, import_data2.useRegistry)();
2502 const [subRegistries] = (0, import_element.useState)(() => /* @__PURE__ */ new WeakMap());
2503 const subRegistry = getSubRegistry(
2504 subRegistries,
2505 registry,
2506 useSubRegistry
2507 );
2508 if (subRegistry === registry) {
2509 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WrappedComponent, { registry, ...props });
2510 }
2511 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_data2.RegistryProvider, { value: subRegistry, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WrappedComponent, { registry: subRegistry, ...props }) });
2512 },
2513 "withRegistryProvider"
2514 );
2515 var with_registry_provider_default = withRegistryProvider;
2516
2517 // packages/upload-media/build-module/components/provider/index.mjs
2518 var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
2519 var MediaUploadProvider = with_registry_provider_default((props) => {
2520 const { children, settings } = props;
2521 const { updateSettings: updateSettings2 } = unlock((0, import_data3.useDispatch)(store));
2522 (0, import_element2.useEffect)(() => {
2523 updateSettings2(settings);
2524 }, [settings, updateSettings2]);
2525 return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
2526 });
2527 var provider_default = MediaUploadProvider;
2528 return __toCommonJS(index_exports);
2529 })();
2530 //# sourceMappingURL=index.js.map
2531