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