PluginProbe
Extendify / 3.1.4
Extendify v3.1.4
3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 0.7.0 All 126 releases
extendify / src / Agent / lib / replace-image.js

replace-image.js in Extendify 3.1.4, at src/Agent/lib/replace-image.js

63 lines 2.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { createBlock, parse, serialize } from '@wordpress/blocks';
2
3 // core/media-text keys its image off media* attributes; url/id do nothing there.
4 const IMAGE_ATTRIBUTES = {
5 'core/image': { url: 'url', id: 'id', alt: 'alt' },
6 'core/cover': { url: 'url', id: 'id', alt: 'alt' },
7 'core/media-text': {
8 url: 'mediaUrl',
9 id: 'mediaId',
10 alt: 'mediaAlt',
11 // A video side would keep rendering as one.
12 set: { mediaType: 'image' },
13 // mediaSizeSlug names a size of the attachment being replaced.
14 clear: ['mediaSizeSlug'],
15 },
16 };
17
18 // Swapping an un-fetched url into the live img flashes broken while it loads.
19 export const preloadImage = (src) =>
20 new Promise((resolve, reject) => {
21 const img = new Image();
22 img.onload = () => resolve(src);
23 img.onerror = reject;
24 img.src = src;
25 });
26
27 // The block's own save() regenerates the markup (img src, wp-image-{id}) from
28 // the attributes, so nothing here touches the HTML.
29 export const swapBlockImage = (serializedBlock, image) => {
30 const url = image?.source_url || image?.url;
31 if (!url || !image?.id) return null;
32 // The attachment's alt carries the AI-generated disclosure prefix.
33 const alt = image.alt_text ?? '';
34 const parsed = parse(serializedBlock);
35 if (!parsed.some((block) => IMAGE_ATTRIBUTES[block.name])) return null;
36 const blocks = parsed.map((block) => {
37 const slots = IMAGE_ATTRIBUTES[block.name];
38 if (!slots) return block;
39 const attributes = {
40 ...block.attributes,
41 [slots.url]: url,
42 [slots.id]: image.id,
43 ...slots.set,
44 };
45 if (alt) attributes[slots.alt] = alt;
46 else delete attributes[slots.alt];
47 for (const name of slots.clear ?? []) delete attributes[name];
48 // Remove the import class to stop the unsplash cron from seeing it
49 const className = (attributes.className ?? '')
50 .split(/\s+/)
51 .filter((cls) => cls && cls !== 'extendify-image-import')
52 .join(' ');
53 if (className) attributes.className = className;
54 else delete attributes.className;
55 // serialize() echoes a drifted block's original source, dropping the swap —
56 // rebuild it (the editor's own recovery) so the new image reaches the markup.
57 return block.isValid === false
58 ? createBlock(block.name, attributes, block.innerBlocks)
59 : { ...block, attributes };
60 });
61 return serialize(blocks);
62 };
63