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