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

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