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