PluginProbe
Gutenberg / 23.2.2
Gutenberg v23.2.2
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.2.2, at build/scripts/upload-media/index.js

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