@wordpress/block-library
Version:
Block library for the WordPress editor.
8 lines (7 loc) • 22.3 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/image/use-open-image-media-editor-modal.js"],
"sourcesContent": ["import { store as coreStore } from '@wordpress/core-data';\nimport {\n\tprivateApis as blockEditorPrivateApis,\n\tstore as blockEditorStore,\n} from '@wordpress/block-editor';\nimport { __unstableStripHTML as stripHTML } from '@wordpress/dom';\nimport { useRegistry, useSelect } from '@wordpress/data';\nimport { useCallback, useEffect, useRef } from '@wordpress/element';\nimport { unlock } from '../lock-unlock';\nimport {\n\tDEFAULT_MEDIA_SIZE_SLUG,\n\tLINK_DESTINATION_ATTACHMENT,\n\tLINK_DESTINATION_MEDIA,\n} from './constants';\n\nfunction normalizeImageBlockCaption( caption ) {\n\tif ( typeof caption !== 'string' ) {\n\t\treturn '';\n\t}\n\n\tconst textContent = stripHTML( caption ).trim();\n\n\tif ( ! textContent ) {\n\t\treturn '';\n\t}\n\n\treturn caption.replace( /\\n/g, '<br>' );\n}\n\nfunction getAttachmentCaption( attachment ) {\n\tconst caption = attachment?.caption;\n\n\tif ( typeof caption === 'string' ) {\n\t\treturn normalizeImageBlockCaption( caption );\n\t}\n\n\tif (\n\t\tcaption &&\n\t\ttypeof caption === 'object' &&\n\t\tObject.hasOwn( caption, 'raw' )\n\t) {\n\t\treturn normalizeImageBlockCaption( caption.raw );\n\t}\n\n\treturn undefined;\n}\n\nexport function getImageBlockMetadataFromAttachment( attachment ) {\n\treturn {\n\t\talt:\n\t\t\ttypeof attachment?.alt_text === 'string'\n\t\t\t\t? attachment.alt_text\n\t\t\t\t: attachment?.alt || '',\n\t\tcaption: getAttachmentCaption( attachment ),\n\t};\n}\n\nfunction normalizeMetadataAttribute( value ) {\n\treturn value || '';\n}\n\nexport function getSyncedImageBlockAttributes(\n\tcurrentAttributes,\n\toriginalAttachment,\n\tupdatedAttachment\n) {\n\tif ( ! originalAttachment || ! updatedAttachment ) {\n\t\treturn {};\n\t}\n\n\tconst originalMetadata =\n\t\tgetImageBlockMetadataFromAttachment( originalAttachment );\n\tconst updatedMetadata =\n\t\tgetImageBlockMetadataFromAttachment( updatedAttachment );\n\tconst syncedAttributes = {};\n\n\tconst normalizedCurrentAlt = normalizeMetadataAttribute(\n\t\tcurrentAttributes.alt\n\t);\n\tif (\n\t\toriginalMetadata.alt !== updatedMetadata.alt &&\n\t\t( normalizedCurrentAlt === originalMetadata.alt ||\n\t\t\t! normalizedCurrentAlt )\n\t) {\n\t\tsyncedAttributes.alt = updatedMetadata.alt;\n\t}\n\n\tconst normalizedCurrentCaption = normalizeMetadataAttribute(\n\t\tcurrentAttributes.caption\n\t);\n\tif (\n\t\toriginalMetadata.caption !== undefined &&\n\t\tupdatedMetadata.caption !== undefined &&\n\t\toriginalMetadata.caption !== updatedMetadata.caption &&\n\t\t( normalizedCurrentCaption === originalMetadata.caption ||\n\t\t\t! normalizedCurrentCaption )\n\t) {\n\t\tsyncedAttributes.caption = updatedMetadata.caption || undefined;\n\t}\n\n\treturn syncedAttributes;\n}\n\n/**\n * Resolves the attributes needed to keep the selected image size on a new\n * attachment.\n *\n * WordPress skips generating a sub-size larger than the file itself, so the\n * selected size may not exist on the edited image; fall back to full when it\n * doesn't.\n *\n * @param {string|undefined} sizeSlug The block's currently selected size.\n * @param {Object} attachment The new attachment record.\n *\n * @return {Object|undefined} Attributes to apply, if any.\n */\nfunction getNewAttachmentSizeAttributes( sizeSlug, attachment ) {\n\tconst sizes = attachment.media_details?.sizes;\n\n\tif ( ! sizeSlug || sizeSlug === DEFAULT_MEDIA_SIZE_SLUG || ! sizes ) {\n\t\treturn undefined;\n\t}\n\n\tconst sizeUrl = sizes[ sizeSlug ]?.source_url;\n\n\tif ( sizeUrl ) {\n\t\treturn { url: sizeUrl };\n\t}\n\n\tconst fullUrl = attachment.source_url ?? sizes.full?.source_url;\n\n\treturn fullUrl\n\t\t? { url: fullUrl, sizeSlug: DEFAULT_MEDIA_SIZE_SLUG }\n\t\t: undefined;\n}\n\n/**\n * Resolves the link attributes needed to keep the block's link pointing at the\n * new attachment.\n *\n * Only the destinations derived from the attachment follow the edited image. A\n * `custom` link is the user's own URL and a `none` link has nothing to point\n * at, so both are left alone. When the record doesn't carry the field, the\n * existing link is kept rather than cleared.\n *\n * @param {string|undefined} linkDestination The block's link destination.\n * @param {Object} attachment The new attachment record.\n *\n * @return {Object|undefined} Attributes to apply, if any.\n */\nfunction getNewAttachmentLinkAttributes( linkDestination, attachment ) {\n\t// Media file links point at the full-size file, independently of the size\n\t// the block renders.\n\tif ( linkDestination === LINK_DESTINATION_MEDIA ) {\n\t\treturn attachment.source_url\n\t\t\t? { href: attachment.source_url }\n\t\t\t: undefined;\n\t}\n\n\tif ( linkDestination === LINK_DESTINATION_ATTACHMENT ) {\n\t\treturn attachment.link ? { href: attachment.link } : undefined;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Resolves the block attributes that are derived from the attachment, for an\n * edit that saved to a different one.\n *\n * Editing media (crop, rotate, flip) creates a new attachment with its own\n * generated sub-sizes and its own attachment page, and the media editor\n * reports the full-size file. Without re-deriving these, the size control\n * keeps reporting e.g. \"Medium\" while the block renders the full-size image,\n * and a \"Media file\" or \"Attachment page\" link still points at the image as it\n * was before the edit. Everything else the user set on the block — dimensions,\n * lightbox, title, custom links — is left untouched.\n *\n * @param {Object} blockAttributes The block's current attributes.\n * @param {Object|undefined} attachment The new attachment record.\n *\n * @return {Object|undefined} Attributes to apply, or undefined when the\n * attachment record isn't known yet.\n */\nexport function getNewAttachmentImageBlockAttributes(\n\tblockAttributes,\n\tattachment\n) {\n\tif ( ! attachment ) {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\t...getNewAttachmentSizeAttributes(\n\t\t\tblockAttributes.sizeSlug,\n\t\t\tattachment\n\t\t),\n\t\t...getNewAttachmentLinkAttributes(\n\t\t\tblockAttributes.linkDestination,\n\t\t\tattachment\n\t\t),\n\t};\n}\n\nconst { openMediaEditorModalKey } = unlock( blockEditorPrivateApis );\n\nfunction getAttachmentFallbackForEmptyBlockMetadata( { alt, caption } ) {\n\tconst attachment = {};\n\n\tif ( ! alt ) {\n\t\tattachment.alt_text = '';\n\t}\n\n\tif ( ! caption?.toString() ) {\n\t\tattachment.caption = '';\n\t}\n\n\treturn Object.keys( attachment ).length ? attachment : undefined;\n}\n\nfunction hasKnownAttachmentMetadata( attachment ) {\n\tif ( ! attachment ) {\n\t\treturn false;\n\t}\n\n\tconst hasKnownAlt =\n\t\ttypeof attachment.alt_text === 'string' ||\n\t\ttypeof attachment.alt === 'string';\n\tconst hasKnownCaption =\n\t\tgetImageBlockMetadataFromAttachment( attachment ).caption !== undefined;\n\n\treturn hasKnownAlt && hasKnownCaption;\n}\n\nexport function useOpenImageMediaEditorModal( {\n\tattributes,\n\tsetAttributes,\n\tonClose,\n\tonUrlChange,\n} ) {\n\t// Keep this hook private to the Image block and pass the block attributes\n\t// object so the callsite stays compact. Destructure only the attributes\n\t// the update needs to read — those synced from the attachment's metadata,\n\t// and those derived from which attachment the block points at; add more\n\t// here if the sync policy grows.\n\tconst { id, url, alt, caption, sizeSlug, linkDestination } = attributes;\n\tconst registry = useRegistry();\n\tconst openMediaEditorModal = useSelect(\n\t\t( select ) =>\n\t\t\tselect( blockEditorStore ).getSettings()[ openMediaEditorModalKey ],\n\t\t[]\n\t);\n\t// Track the block's current attachment and metadata in a ref so\n\t// handleMediaUpdate can read the latest values without being listed as\n\t// dependencies (which would recreate the callback and re-register the\n\t// onUpdate handler on every block change while the modal is open).\n\tconst blockAttributesRef = useRef( {\n\t\tid,\n\t\turl,\n\t\talt,\n\t\tcaption: caption?.toString(),\n\t\tsizeSlug,\n\t\tlinkDestination,\n\t} );\n\t// Snapshot of the attachment's metadata taken just before the modal opens,\n\t// used as the baseline for detecting what changed during the editing session.\n\tconst mediaEditorMetadataBaselineRef = useRef();\n\t// Incremented on every handleMediaUpdate call; stale async continuations\n\t// check against this to bail out if a newer update has since started.\n\tconst mediaEditorMetadataSyncRequestRef = useRef( 0 );\n\n\tuseEffect( () => {\n\t\tblockAttributesRef.current = {\n\t\t\tid,\n\t\t\turl,\n\t\t\talt,\n\t\t\tcaption: caption?.toString(),\n\t\t\tsizeSlug,\n\t\t\tlinkDestination,\n\t\t};\n\t}, [ alt, caption, id, linkDestination, sizeSlug, url ] );\n\n\t// Reads the cached attachment record. The `attachment` postType entity\n\t// fetches with `context: 'edit'` by default, so `getEditedEntityRecord`\n\t// returns the edit-context record — carrying `caption` as `{ raw }` and a\n\t// usable `alt_text` — without us specifying a context. It is resolver-\n\t// backed, so on a cold cache this also kicks off the fetch and returns a\n\t// falsy value synchronously; that resolution shares its cache key with the\n\t// `resolveAttachmentRecord` call below (both keyed on the no-query\n\t// `getEntityRecord`), so the two dedupe into a single request.\n\tconst getCachedAttachmentRecord = useCallback(\n\t\t( attachmentId ) =>\n\t\t\tregistry\n\t\t\t\t.select( coreStore )\n\t\t\t\t.getEditedEntityRecord(\n\t\t\t\t\t'postType',\n\t\t\t\t\t'attachment',\n\t\t\t\t\tattachmentId\n\t\t\t\t),\n\t\t[ registry ]\n\t);\n\n\tconst resolveAttachmentRecord = useCallback(\n\t\tasync ( attachmentId ) => {\n\t\t\tconst resolveSelect = registry.resolveSelect( coreStore );\n\n\t\t\ttry {\n\t\t\t\treturn await resolveSelect.getEntityRecord(\n\t\t\t\t\t'postType',\n\t\t\t\t\t'attachment',\n\t\t\t\t\tattachmentId\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t},\n\t\t[ registry ]\n\t);\n\n\tconst resolveFreshAttachmentRecord = useCallback(\n\t\tasync ( attachmentId ) => {\n\t\t\t// Invalidate the cached resolution so resolveAttachmentRecord\n\t\t\t// re-fetches the server state that reflects the media editor's\n\t\t\t// saved changes.\n\t\t\tconst { invalidateResolution } = registry.dispatch( coreStore );\n\n\t\t\tinvalidateResolution( 'getEntityRecord', [\n\t\t\t\t'postType',\n\t\t\t\t'attachment',\n\t\t\t\tattachmentId,\n\t\t\t] );\n\t\t\treturn resolveAttachmentRecord( attachmentId );\n\t\t},\n\t\t[ registry, resolveAttachmentRecord ]\n\t);\n\n\tconst handleMediaUpdate = useCallback(\n\t\tasync ( { id: newId, url: newUrl } ) => {\n\t\t\tif ( typeof newId !== 'number' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Capture and clear the baseline so a rapid second save doesn't\n\t\t\t// reuse a stale snapshot.\n\t\t\tconst originalAttachment = mediaEditorMetadataBaselineRef.current;\n\t\t\tmediaEditorMetadataBaselineRef.current = undefined;\n\t\t\tconst syncRequest = ++mediaEditorMetadataSyncRequestRef.current;\n\t\t\tconst nextAttributes = {};\n\n\t\t\tconst currentBlockAttributes = blockAttributesRef.current;\n\t\t\tconst isNewAttachment = newId !== currentBlockAttributes.id;\n\n\t\t\tif ( isNewAttachment ) {\n\t\t\t\tnextAttributes.id = newId;\n\t\t\t\tnextAttributes.url = newUrl ?? currentBlockAttributes.url;\n\t\t\t\tif ( nextAttributes.url !== currentBlockAttributes.url ) {\n\t\t\t\t\t// The block is about to point at a freshly generated file\n\t\t\t\t\t// the browser hasn't loaded yet; let the caller show a\n\t\t\t\t\t// loading state until its <img> fires load/error. Raising\n\t\t\t\t\t// it here, before anything is awaited, keeps the rest of\n\t\t\t\t\t// this update behind that loading state: the attributes\n\t\t\t\t\t// land in a single `setAttributes` at the end, so the\n\t\t\t\t\t// image never renders against half-updated settings.\n\t\t\t\t\tonUrlChange?.( nextAttributes.url );\n\t\t\t\t}\n\t\t\t\tblockAttributesRef.current = {\n\t\t\t\t\t...blockAttributesRef.current,\n\t\t\t\t\tid: nextAttributes.id,\n\t\t\t\t\turl: nextAttributes.url,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif ( originalAttachment || isNewAttachment ) {\n\t\t\t\t// Fetch fresh server state so this reflects what the media\n\t\t\t\t// editor actually saved, not a potentially stale cache.\n\t\t\t\tconst resolvedAttachment =\n\t\t\t\t\tawait resolveFreshAttachmentRecord( newId );\n\n\t\t\t\t// A newer update started while we were awaiting; discard\n\t\t\t\t// this one.\n\t\t\t\tif (\n\t\t\t\t\tsyncRequest !== mediaEditorMetadataSyncRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// A failed refetch returns nothing, which would leave the\n\t\t\t\t// block pointing at the new file while its size and link\n\t\t\t\t// still describe the old one. The record the media editor\n\t\t\t\t// received when it saved is already in the store, so fall\n\t\t\t\t// back to that rather than half-updating the block.\n\t\t\t\tconst attachmentRecord =\n\t\t\t\t\tresolvedAttachment ?? getCachedAttachmentRecord( newId );\n\n\t\t\t\tconst latestBlockAttributes = blockAttributesRef.current;\n\n\t\t\t\t// Sync alt text and caption back to the block only when\n\t\t\t\t// they were changed in the media editor. Fields the user\n\t\t\t\t// has independently customised on the block (i.e. values\n\t\t\t\t// that don't match the pre-session attachment metadata)\n\t\t\t\t// are left untouched. Without a baseline there's no way to\n\t\t\t\t// tell the two apart, so nothing is synced.\n\t\t\t\tif ( originalAttachment ) {\n\t\t\t\t\tconst resolvedMetadataAttributes =\n\t\t\t\t\t\tgetSyncedImageBlockAttributes(\n\t\t\t\t\t\t\tlatestBlockAttributes,\n\t\t\t\t\t\t\toriginalAttachment,\n\t\t\t\t\t\t\tattachmentRecord\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif ( Object.keys( resolvedMetadataAttributes ).length ) {\n\t\t\t\t\t\tObject.assign(\n\t\t\t\t\t\t\tnextAttributes,\n\t\t\t\t\t\t\tresolvedMetadataAttributes\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isNewAttachment ) {\n\t\t\t\t\tconst derivedAttributes =\n\t\t\t\t\t\tgetNewAttachmentImageBlockAttributes(\n\t\t\t\t\t\t\tlatestBlockAttributes,\n\t\t\t\t\t\t\tattachmentRecord\n\t\t\t\t\t\t);\n\n\t\t\t\t\tif ( derivedAttributes ) {\n\t\t\t\t\t\tObject.assign( nextAttributes, derivedAttributes );\n\n\t\t\t\t\t\t// The URL announced before the resolve was the\n\t\t\t\t\t\t// full-size file the media editor reported, and\n\t\t\t\t\t\t// deriving the selected size can change it.\n\t\t\t\t\t\t// Re-announce so the pending swap names the file\n\t\t\t\t\t\t// that actually lands: an update that is undone or\n\t\t\t\t\t\t// superseded never changes the <img> src, and the\n\t\t\t\t\t\t// block then clears its loading state by matching\n\t\t\t\t\t\t// the pending URL against the rendered one.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tderivedAttributes.url &&\n\t\t\t\t\t\t\tderivedAttributes.url !== latestBlockAttributes.url\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tonUrlChange?.( derivedAttributes.url );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( Object.keys( nextAttributes ).length ) {\n\t\t\t\tblockAttributesRef.current = {\n\t\t\t\t\t...blockAttributesRef.current,\n\t\t\t\t\t...nextAttributes,\n\t\t\t\t};\n\t\t\t\tsetAttributes( nextAttributes );\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\tgetCachedAttachmentRecord,\n\t\t\tonUrlChange,\n\t\t\tresolveFreshAttachmentRecord,\n\t\t\tsetAttributes,\n\t\t]\n\t);\n\n\tconst openImageMediaEditorModal = useCallback( async () => {\n\t\tif ( ! id || ! openMediaEditorModal ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Snapshot the attachment's current metadata before the user makes\n\t\t// any changes so handleMediaUpdate can compare against it later. Use\n\t\t// the cached record when it's already present; only resolve when\n\t\t// nothing is cached yet, then fall back to a minimal object derived\n\t\t// from the block's own attributes.\n\t\tconst cachedAttachmentRecord = getCachedAttachmentRecord( id );\n\t\tconst fallbackAttachmentRecord =\n\t\t\tgetAttachmentFallbackForEmptyBlockMetadata(\n\t\t\t\tblockAttributesRef.current\n\t\t\t);\n\t\tconst resolvedAttachmentRecord = hasKnownAttachmentMetadata(\n\t\t\tcachedAttachmentRecord\n\t\t)\n\t\t\t? undefined\n\t\t\t: await resolveAttachmentRecord( id );\n\n\t\tmediaEditorMetadataBaselineRef.current =\n\t\t\tresolvedAttachmentRecord ||\n\t\t\t( hasKnownAttachmentMetadata( cachedAttachmentRecord )\n\t\t\t\t? cachedAttachmentRecord\n\t\t\t\t: fallbackAttachmentRecord ) ||\n\t\t\tcachedAttachmentRecord;\n\n\t\topenMediaEditorModal( {\n\t\t\tid,\n\t\t\tonUpdate: handleMediaUpdate,\n\t\t\tonClose,\n\t\t} );\n\t}, [\n\t\tgetCachedAttachmentRecord,\n\t\thandleMediaUpdate,\n\t\tid,\n\t\tonClose,\n\t\topenMediaEditorModal,\n\t\tresolveAttachmentRecord,\n\t] );\n\n\treturn id && openMediaEditorModal ? openImageMediaEditorModal : undefined;\n}\n"],
"mappings": "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",
"names": []
}