diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-includes/js/dist/media-utils.js --- a/wp/wp-includes/js/dist/media-utils.js Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-includes/js/dist/media-utils.js Fri Sep 05 18:40:08 2025 +0200 @@ -1,48 +1,48 @@ -/******/ (function() { // webpackBootstrap +/******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ // The require scope /******/ var __webpack_require__ = {}; /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ -/******/ !function() { +/******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { +/******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? -/******/ function() { return module['default']; } : -/******/ function() { return module; }; +/******/ () => (module['default']) : +/******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; -/******/ }(); +/******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ -/******/ !function() { +/******/ (() => { /******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = function(exports, definition) { +/******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; -/******/ }(); +/******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ !function() { -/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } -/******/ }(); +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ -/******/ !function() { +/******/ (() => { /******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { +/******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; -/******/ }(); +/******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; @@ -51,38 +51,31 @@ // EXPORTS __webpack_require__.d(__webpack_exports__, { - "MediaUpload": function() { return /* reexport */ media_upload; }, - "uploadMedia": function() { return /* reexport */ uploadMedia; } + MediaUpload: () => (/* reexport */ media_upload), + uploadMedia: () => (/* reexport */ uploadMedia) }); -;// CONCATENATED MODULE: external "lodash" -var external_lodash_namespaceObject = window["lodash"]; ;// CONCATENATED MODULE: external ["wp","element"] -var external_wp_element_namespaceObject = window["wp"]["element"]; +const external_wp_element_namespaceObject = window["wp"]["element"]; ;// CONCATENATED MODULE: external ["wp","i18n"] -var external_wp_i18n_namespaceObject = window["wp"]["i18n"]; +const external_wp_i18n_namespaceObject = window["wp"]["i18n"]; ;// CONCATENATED MODULE: ./node_modules/@wordpress/media-utils/build-module/components/media-upload/index.js /** - * External dependencies - */ - -/** * WordPress dependencies */ +const DEFAULT_EMPTY_GALLERY = []; -const { - wp -} = window; -const DEFAULT_EMPTY_GALLERY = []; /** * Prepares the Featured Image toolbars and frames. * - * @return {wp.media.view.MediaFrame.Select} The default media workflow. + * @return {window.wp.media.view.MediaFrame.Select} The default media workflow. */ - const getFeaturedImageMediaFrame = () => { + const { + wp + } = window; return wp.media.view.MediaFrame.Select.extend({ /** * Enables the Set Featured Image Button. @@ -96,7 +89,6 @@ state: this.options.state }); }, - /** * Handle the edit state requirements of selected media item. * @@ -107,13 +99,14 @@ const view = new wp.media.view.EditImage({ model: selection.single(), controller: this - }).render(); // Set the view to the EditImage frame using the selected image. + }).render(); - this.content.set(view); // After bringing in the frame, load the actual editor via an ajax call. + // Set the view to the EditImage frame using the selected image. + this.content.set(view); + // After bringing in the frame, load the actual editor via an ajax call. view.loadEditor(); }, - /** * Create the default states. * @@ -128,14 +121,16 @@ } }); }; + /** * Prepares the Gallery toolbars and frames. * - * @return {wp.media.view.MediaFrame.Post} The default media workflow. + * @return {window.wp.media.view.MediaFrame.Post} The default media workflow. */ - - const getGalleryDetailsMediaFrame = () => { + const { + wp + } = window; /** * Custom gallery details frame. * @@ -161,25 +156,23 @@ requires: { library: true }, - /** * @fires wp.media.controller.State#update */ click() { const controller = this.controller, - state = controller.state(); + state = controller.state(); controller.close(); - state.trigger('update', state.get('library')); // Restore and reset the default state. + state.trigger('update', state.get('library')); + // Restore and reset the default state. controller.setState(controller.options.state); controller.reset(); } - } } })); }, - /** * Handle the edit state requirements of selected media item. * @@ -190,13 +183,14 @@ const view = new wp.media.view.EditImage({ model: selection.single(), controller: this - }).render(); // Set the view to the EditImage frame using the selected image. + }).render(); - this.content.set(view); // After bringing in the frame, load the actual editor via an ajax call. + // Set the view to the EditImage frame using the selected image. + this.content.set(view); + // After bringing in the frame, load the actual editor via an ajax call. view.loadEditor(); }, - /** * Create the default states. * @@ -213,9 +207,10 @@ filterable: 'uploaded', multiple: 'add', editable: false, - library: wp.media.query((0,external_lodash_namespaceObject.defaults)({ - type: 'image' - }, this.options.library)) + library: wp.media.query({ + type: 'image', + ...this.options.library + }) }), new wp.media.controller.EditImage({ model: this.options.editImage }), new wp.media.controller.GalleryEdit({ @@ -227,16 +222,23 @@ }), new wp.media.controller.GalleryAdd()]); } }); -}; // The media library image object contains numerous attributes +}; + +// The media library image object contains numerous attributes // we only need this set to display the image in the library. - - const slimImageObject = img => { const attrSet = ['sizes', 'mime', 'type', 'subtype', 'id', 'url', 'alt', 'link', 'caption']; - return (0,external_lodash_namespaceObject.pick)(img, attrSet); + return attrSet.reduce((result, key) => { + if (img?.hasOwnProperty(key)) { + result[key] = img[key]; + } + return result; + }, {}); }; - const getAttachmentsCollection = ids => { + const { + wp + } = window; return wp.media.query({ order: 'ASC', orderby: 'post__in', @@ -246,52 +248,15 @@ type: 'image' }); }; - class MediaUpload extends external_wp_element_namespaceObject.Component { - constructor(_ref) { - let { - allowedTypes, - gallery = false, - unstableFeaturedImageFlow = false, - modalClass, - multiple = false, - title = (0,external_wp_i18n_namespaceObject.__)('Select or Upload Media') - } = _ref; + constructor() { super(...arguments); this.openModal = this.openModal.bind(this); this.onOpen = this.onOpen.bind(this); this.onSelect = this.onSelect.bind(this); this.onUpdate = this.onUpdate.bind(this); this.onClose = this.onClose.bind(this); - - if (gallery) { - this.buildAndSetGalleryFrame(); - } else { - const frameConfig = { - title, - multiple - }; - - if (!!allowedTypes) { - frameConfig.library = { - type: allowedTypes - }; - } - - this.frame = wp.media(frameConfig); - } - - if (modalClass) { - this.frame.$el.addClass(modalClass); - } - - if (unstableFeaturedImageFlow) { - this.buildAndSetFeatureImageFrame(); - } - - this.initializeListeners(); } - initializeListeners() { // When an image is selected in the media frame... this.frame.on('select', this.onSelect); @@ -299,44 +264,43 @@ this.frame.on('open', this.onOpen); this.frame.on('close', this.onClose); } + /** * Sets the Gallery frame and initializes listeners. * * @return {void} */ - - buildAndSetGalleryFrame() { const { addToGallery = false, allowedTypes, multiple = false, value = DEFAULT_EMPTY_GALLERY - } = this.props; // If the value did not changed there is no need to rebuild the frame, + } = this.props; + + // If the value did not changed there is no need to rebuild the frame, // we can continue to use the existing one. - if (value === this.lastGalleryValue) { return; } + const { + wp + } = window; + this.lastGalleryValue = value; - this.lastGalleryValue = value; // If a frame already existed remove it. - + // If a frame already existed remove it. if (this.frame) { this.frame.remove(); } - let currentState; - if (addToGallery) { currentState = 'gallery-library'; } else { currentState = value && value.length ? 'gallery-edit' : 'gallery'; } - if (!this.GalleryDetailsMediaFrame) { this.GalleryDetailsMediaFrame = getGalleryDetailsMediaFrame(); } - const attachments = getAttachmentsCollection(value); const selection = new wp.media.model.Selection(attachments.models, { props: attachments.props.toJSON(), @@ -352,33 +316,46 @@ wp.media.frame = this.frame; this.initializeListeners(); } + /** * Initializes the Media Library requirements for the featured image flow. * * @return {void} */ - - buildAndSetFeatureImageFrame() { + const { + wp + } = window; + const { + value: featuredImageId, + multiple, + allowedTypes + } = this.props; const featuredImageFrame = getFeaturedImageMediaFrame(); - const attachments = getAttachmentsCollection(this.props.value); + const attachments = getAttachmentsCollection(featuredImageId); const selection = new wp.media.model.Selection(attachments.models, { props: attachments.props.toJSON() }); this.frame = new featuredImageFrame({ - mimeType: this.props.allowedTypes, + mimeType: allowedTypes, state: 'featured-image', - multiple: this.props.multiple, + multiple, selection, - editing: this.props.value ? true : false + editing: featuredImageId }); wp.media.frame = this.frame; + // In order to select the current featured image when opening + // the media library we have to set the appropriate settings. + // Currently they are set in php for the post editor, but + // not for site editor. + wp.media.view.settings.post = { + ...wp.media.view.settings.post, + featuredImageId: featuredImageId || -1 + }; } - componentWillUnmount() { - this.frame.remove(); + this.frame?.remove(); } - onUpdate(selections) { const { onSelect, @@ -386,124 +363,145 @@ } = this.props; const state = this.frame.state(); const selectedImages = selections || state.get('selection'); - if (!selectedImages || !selectedImages.models.length) { return; } - if (multiple) { onSelect(selectedImages.models.map(model => slimImageObject(model.toJSON()))); } else { onSelect(slimImageObject(selectedImages.models[0].toJSON())); } } - onSelect() { const { onSelect, multiple = false - } = this.props; // Get media attachment details from the frame state. - + } = this.props; + // Get media attachment details from the frame state. const attachment = this.frame.state().get('selection').toJSON(); onSelect(multiple ? attachment : attachment[0]); } - onOpen() { - var _this$props$value; + const { + wp + } = window; + const { + value + } = this.props; + this.updateCollection(); - this.updateCollection(); // Handle both this.props.value being either (number[]) multiple ids - // (for galleries) or a (number) singular id (e.g. image block). + //Handle active tab in media model on model open. + if (this.props.mode) { + this.frame.content.mode(this.props.mode); + } - const hasMedia = Array.isArray(this.props.value) ? !!((_this$props$value = this.props.value) !== null && _this$props$value !== void 0 && _this$props$value.length) : !!this.props.value; - + // Handle both this.props.value being either (number[]) multiple ids + // (for galleries) or a (number) singular id (e.g. image block). + const hasMedia = Array.isArray(value) ? !!value?.length : !!value; if (!hasMedia) { return; } - const isGallery = this.props.gallery; const selection = this.frame.state().get('selection'); - + const valueArray = Array.isArray(value) ? value : [value]; if (!isGallery) { - (0,external_lodash_namespaceObject.castArray)(this.props.value).forEach(id => { + valueArray.forEach(id => { selection.add(wp.media.attachment(id)); }); - } // Load the images so they are available in the media modal. - - - const attachments = getAttachmentsCollection((0,external_lodash_namespaceObject.castArray)(this.props.value)); // Once attachments are loaded, set the current selection. + } + // Load the images so they are available in the media modal. + const attachments = getAttachmentsCollection(valueArray); + + // Once attachments are loaded, set the current selection. attachments.more().done(function () { - var _attachments$models; - - if (isGallery && attachments !== null && attachments !== void 0 && (_attachments$models = attachments.models) !== null && _attachments$models !== void 0 && _attachments$models.length) { + if (isGallery && attachments?.models?.length) { selection.add(attachments.models); } }); } - onClose() { const { onClose } = this.props; - if (onClose) { onClose(); } } - updateCollection() { const frameContent = this.frame.content.get(); - if (frameContent && frameContent.collection) { - const collection = frameContent.collection; // Clean all attachments we have in memory. + const collection = frameContent.collection; - collection.toArray().forEach(model => model.trigger('destroy', model)); // Reset has more flag, if library had small amount of items all items may have been loaded before. + // Clean all attachments we have in memory. + collection.toArray().forEach(model => model.trigger('destroy', model)); - collection.mirroring._hasMore = true; // Request items. + // Reset has more flag, if library had small amount of items all items may have been loaded before. + collection.mirroring._hasMore = true; + // Request items. collection.more(); } } - openModal() { - if (this.props.gallery) { + const { + allowedTypes, + gallery = false, + unstableFeaturedImageFlow = false, + modalClass, + multiple = false, + title = (0,external_wp_i18n_namespaceObject.__)('Select or Upload Media') + } = this.props; + const { + wp + } = window; + if (gallery) { this.buildAndSetGalleryFrame(); + } else { + const frameConfig = { + title, + multiple + }; + if (!!allowedTypes) { + frameConfig.library = { + type: allowedTypes + }; + } + this.frame = wp.media(frameConfig); } - + if (modalClass) { + this.frame.$el.addClass(modalClass); + } + if (unstableFeaturedImageFlow) { + this.buildAndSetFeatureImageFrame(); + } + this.initializeListeners(); this.frame.open(); } - render() { return this.props.render({ open: this.openModal }); } - } - -/* harmony default export */ var media_upload = (MediaUpload); +/* harmony default export */ const media_upload = (MediaUpload); ;// CONCATENATED MODULE: ./node_modules/@wordpress/media-utils/build-module/components/index.js ;// CONCATENATED MODULE: external ["wp","apiFetch"] -var external_wp_apiFetch_namespaceObject = window["wp"]["apiFetch"]; +const external_wp_apiFetch_namespaceObject = window["wp"]["apiFetch"]; var external_wp_apiFetch_default = /*#__PURE__*/__webpack_require__.n(external_wp_apiFetch_namespaceObject); ;// CONCATENATED MODULE: external ["wp","blob"] -var external_wp_blob_namespaceObject = window["wp"]["blob"]; +const external_wp_blob_namespaceObject = window["wp"]["blob"]; ;// CONCATENATED MODULE: ./node_modules/@wordpress/media-utils/build-module/utils/upload-media.js - - -/** - * External dependencies - */ - /** * WordPress dependencies */ +const noop = () => {}; /** * Browsers may use unexpected mime types, and they differ from browser to browser. @@ -518,18 +516,17 @@ * * @return {?Array} An array of mime types or the parameter passed if it was "falsy". */ - function getMimeTypesArray(wpMimeTypesObject) { if (!wpMimeTypesObject) { return wpMimeTypesObject; } - - return (0,external_lodash_namespaceObject.flatMap)(wpMimeTypesObject, (mime, extensionsString) => { + return Object.entries(wpMimeTypesObject).map(([extensionsString, mime]) => { const [type] = mime.split('/'); const extensions = extensionsString.split('|'); - return [mime, ...(0,external_lodash_namespaceObject.map)(extensions, extension => `${type}/${extension}`)]; - }); + return [mime, ...extensions.map(extension => `${type}/${extension}`)]; + }).flat(); } + /** * Media Upload is used by audio, image, gallery, video, and file blocks to * handle uploading a media file when a file upload button is activated. @@ -545,121 +542,119 @@ * @param {Function} $0.onFileChange Function called each time a file or a temporary representation of the file is available. * @param {?Object} $0.wpAllowedMimeTypes List of allowed mime types and file extensions. */ - -async function uploadMedia(_ref) { - let { - allowedTypes, - additionalData = {}, - filesList, - maxUploadFileSize, - onError = external_lodash_namespaceObject.noop, - onFileChange, - wpAllowedMimeTypes = null - } = _ref; +async function uploadMedia({ + allowedTypes, + additionalData = {}, + filesList, + maxUploadFileSize, + onError = noop, + onFileChange, + wpAllowedMimeTypes = null +}) { // Cast filesList to array. const files = [...filesList]; const filesSet = []; - const setAndUpdateFiles = (idx, value) => { - (0,external_wp_blob_namespaceObject.revokeBlobURL)((0,external_lodash_namespaceObject.get)(filesSet, [idx, 'url'])); + (0,external_wp_blob_namespaceObject.revokeBlobURL)(filesSet[idx]?.url); filesSet[idx] = value; - onFileChange((0,external_lodash_namespaceObject.compact)(filesSet)); - }; // Allowed type specified by consumer. + onFileChange(filesSet.filter(Boolean)); + }; - + // Allowed type specified by consumer. const isAllowedType = fileType => { if (!allowedTypes) { return true; } - - return (0,external_lodash_namespaceObject.some)(allowedTypes, allowedType => { + return allowedTypes.some(allowedType => { // If a complete mimetype is specified verify if it matches exactly the mime type of the file. - if ((0,external_lodash_namespaceObject.includes)(allowedType, '/')) { + if (allowedType.includes('/')) { return allowedType === fileType; - } // Otherwise a general mime type is used and we should verify if the file mimetype starts with it. - - - return (0,external_lodash_namespaceObject.startsWith)(fileType, `${allowedType}/`); + } + // Otherwise a general mime type is used and we should verify if the file mimetype starts with it. + return fileType.startsWith(`${allowedType}/`); }); - }; // Allowed types for the current WP_User. - - - const allowedMimeTypesForUser = getMimeTypesArray(wpAllowedMimeTypes); - - const isAllowedMimeTypeForUser = fileType => { - return (0,external_lodash_namespaceObject.includes)(allowedMimeTypesForUser, fileType); - }; // Build the error message including the filename. - - - const triggerError = error => { - error.message = [(0,external_wp_element_namespaceObject.createElement)("strong", { - key: "filename" - }, error.file.name), ': ', error.message]; - onError(error); }; + // Allowed types for the current WP_User. + const allowedMimeTypesForUser = getMimeTypesArray(wpAllowedMimeTypes); + const isAllowedMimeTypeForUser = fileType => { + return allowedMimeTypesForUser.includes(fileType); + }; const validFiles = []; - for (const mediaFile of files) { // Verify if user is allowed to upload this mime type. // Defer to the server when type not detected. if (allowedMimeTypesForUser && mediaFile.type && !isAllowedMimeTypeForUser(mediaFile.type)) { - triggerError({ + onError({ code: 'MIME_TYPE_NOT_ALLOWED_FOR_USER', - message: (0,external_wp_i18n_namespaceObject.__)('Sorry, you are not allowed to upload this file type.'), - file: mediaFile - }); - continue; - } // Check if the block supports this mime type. - // Defer to the server when type not detected. - - - if (mediaFile.type && !isAllowedType(mediaFile.type)) { - triggerError({ - code: 'MIME_TYPE_NOT_SUPPORTED', - message: (0,external_wp_i18n_namespaceObject.__)('Sorry, this file type is not supported here.'), - file: mediaFile - }); - continue; - } // Verify if file is greater than the maximum file upload size allowed for the site. - - - if (maxUploadFileSize && mediaFile.size > maxUploadFileSize) { - triggerError({ - code: 'SIZE_ABOVE_LIMIT', - message: (0,external_wp_i18n_namespaceObject.__)('This file exceeds the maximum upload size for this site.'), - file: mediaFile - }); - continue; - } // Don't allow empty files to be uploaded. - - - if (mediaFile.size <= 0) { - triggerError({ - code: 'EMPTY_FILE', - message: (0,external_wp_i18n_namespaceObject.__)('This file is empty.'), + message: (0,external_wp_i18n_namespaceObject.sprintf)( + // translators: %s: file name. + (0,external_wp_i18n_namespaceObject.__)('%s: Sorry, you are not allowed to upload this file type.'), mediaFile.name), file: mediaFile }); continue; } - validFiles.push(mediaFile); // Set temporary URL to create placeholder media file, this is replaced + // Check if the block supports this mime type. + // Defer to the server when type not detected. + if (mediaFile.type && !isAllowedType(mediaFile.type)) { + onError({ + code: 'MIME_TYPE_NOT_SUPPORTED', + message: (0,external_wp_i18n_namespaceObject.sprintf)( + // translators: %s: file name. + (0,external_wp_i18n_namespaceObject.__)('%s: Sorry, this file type is not supported here.'), mediaFile.name), + file: mediaFile + }); + continue; + } + + // Verify if file is greater than the maximum file upload size allowed for the site. + if (maxUploadFileSize && mediaFile.size > maxUploadFileSize) { + onError({ + code: 'SIZE_ABOVE_LIMIT', + message: (0,external_wp_i18n_namespaceObject.sprintf)( + // translators: %s: file name. + (0,external_wp_i18n_namespaceObject.__)('%s: This file exceeds the maximum upload size for this site.'), mediaFile.name), + file: mediaFile + }); + continue; + } + + // Don't allow empty files to be uploaded. + if (mediaFile.size <= 0) { + onError({ + code: 'EMPTY_FILE', + message: (0,external_wp_i18n_namespaceObject.sprintf)( + // translators: %s: file name. + (0,external_wp_i18n_namespaceObject.__)('%s: This file is empty.'), mediaFile.name), + file: mediaFile + }); + continue; + } + validFiles.push(mediaFile); + + // Set temporary URL to create placeholder media file, this is replaced // with final file from media gallery when upload is `done` below. - filesSet.push({ url: (0,external_wp_blob_namespaceObject.createBlobURL)(mediaFile) }); onFileChange(filesSet); } - for (let idx = 0; idx < validFiles.length; ++idx) { const mediaFile = validFiles[idx]; - try { + var _savedMedia$caption$r; const savedMedia = await createMediaFromFile(mediaFile, additionalData); - const mediaObject = { ...(0,external_lodash_namespaceObject.omit)(savedMedia, ['alt_text', 'source_url']), + // eslint-disable-next-line camelcase + const { + alt_text, + source_url, + ...savedMediaProps + } = savedMedia; + const mediaObject = { + ...savedMediaProps, alt: savedMedia.alt_text, - caption: (0,external_lodash_namespaceObject.get)(savedMedia, ['caption', 'raw'], ''), + caption: (_savedMedia$caption$r = savedMedia.caption?.raw) !== null && _savedMedia$caption$r !== void 0 ? _savedMedia$caption$r : '', title: savedMedia.title.raw, url: savedMedia.source_url }; @@ -668,14 +663,13 @@ // Reset to empty on failure. setAndUpdateFiles(idx, null); let message; - - if ((0,external_lodash_namespaceObject.has)(error, ['message'])) { - message = (0,external_lodash_namespaceObject.get)(error, ['message']); + if (error.message) { + message = error.message; } else { - message = (0,external_wp_i18n_namespaceObject.sprintf)( // translators: %s: file name + message = (0,external_wp_i18n_namespaceObject.sprintf)( + // translators: %s: file name (0,external_wp_i18n_namespaceObject.__)('Error while uploading file %s to the media library.'), mediaFile.name); } - onError({ code: 'GENERAL', message, @@ -684,18 +678,20 @@ } } } + /** * @param {File} file Media File to Save. * @param {?Object} additionalData Additional data to include in the request. * * @return {Promise} Media Object Promise. */ - function createMediaFromFile(file, additionalData) { // Create upload payload. const data = new window.FormData(); data.append('file', file, file.name || file.type.replace('/', '.')); - (0,external_lodash_namespaceObject.forEach)(additionalData, (value, key) => data.append(key, value)); + if (additionalData) { + Object.entries(additionalData).forEach(([key, value]) => data.append(key, value)); + } return external_wp_apiFetch_default()({ path: '/wp/v2/media', body: data,