Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Image block preserves alt text from media library #41839

Merged
merged 5 commits into from
Jun 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/block-library/src/image/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ export class ImageEdit extends Component {
id: media.id,
url: media.url,
caption: media.caption,
alt: media.alt,
};

let additionalAttributes;
Expand Down
44 changes: 38 additions & 6 deletions packages/block-library/src/image/test/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Clipboard from '@react-native-clipboard/clipboard';
*/
import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
import {
requestMediaPicker,
setFeaturedImage,
sendMediaUpload,
subscribeMediaUpload,
Expand Down Expand Up @@ -49,6 +50,10 @@ jest.mock( 'lodash', () => {
return { ...actual, delay: ( cb ) => cb() };
} );

function mockGetMedia( media ) {
jest.spyOn( select( coreStore ), 'getMedia' ).mockReturnValue( media );
}

const apiFetchPromise = Promise.resolve( {} );

const clipboardPromise = Promise.resolve( '' );
Expand Down Expand Up @@ -292,12 +297,6 @@ describe( 'Image Block', () => {
);
}

function mockGetMedia( media ) {
jest.spyOn( select( coreStore ), 'getMedia' ).mockReturnValueOnce(
media
);
}

it( 'does not prompt to replace featured image during a new image upload', () => {
// Arrange
const INITIAL_IMAGE = { id: 1, url: 'mock-url-1' };
Expand Down Expand Up @@ -406,4 +405,37 @@ describe( 'Image Block', () => {
);
} );
} );

it( 'sets src and alt attributes when selecting media', async () => {
const IMAGE = { id: 1, url: 'mock-image', alt: 'A beautiful mountain' };
requestMediaPicker.mockImplementationOnce(
( source, filter, multiple, callback ) => {
callback( {
id: IMAGE.id,
url: IMAGE.url,
alt: IMAGE.alt,
} );
}
);
mockGetMedia( {
id: IMAGE.id,
source_url: IMAGE.url,
} );

const initialHtml = `
<!-- wp:image -->
<figure class="wp-block-image">
<img alt="" />
</figure>
<!-- /wp:image -->`;
const screen = await initializeEditor( { initialHtml } );

fireEvent.press( screen.getByText( 'ADD IMAGE' ) );
fireEvent.press( screen.getByText( 'WordPress Media Library' ) );

const expectedHtml = `<!-- wp:image {"id":${ IMAGE.id },"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="${ IMAGE.url }" alt="${ IMAGE.alt }" class="wp-image-${ IMAGE.id }"/></figure>
<!-- /wp:image -->`;
expect( getEditorHtml() ).toBe( expectedHtml );
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ interface RNMedia {
val type: String
val caption: String
val title: String
val alt: String
fun toMap(): WritableMap
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,20 @@ data class Media(
override val url: String,
override val type: String,
override val caption: String = "",
override val title: String = ""
override val title: String = "",
override val alt: String = ""
) : RNMedia {
override fun toMap(): WritableMap = WritableNativeMap().apply {
putInt("id", id)
putString("url", url)
putString("type", type)
putString("caption", caption)
putString("title", title)
putString("alt", alt)
}

companion object {
@JvmStatic
fun createRNMediaUsingMimeType(
id: Int,
url: String,
mimeType: String?,
caption: String?,
title: String?
): Media {
private fun convertToType(mimeType: String?): String {
val isMediaType = { mediaType: MediaType ->
mimeType?.startsWith(mediaType.name.toLowerCase(Locale.ROOT)) == true
}
Expand All @@ -41,6 +36,30 @@ data class Media(
isMediaType(VIDEO) -> VIDEO
else -> OTHER
}.name.toLowerCase(Locale.ROOT)
return type;
}

@JvmStatic
fun createRNMediaUsingMimeType(
id: Int,
url: String,
mimeType: String?,
caption: String?,
title: String?,
alt: String?,
): Media {
val type = convertToType(mimeType)
return Media(id, url, type, caption ?: "", title ?: "", alt ?: "")
}
@JvmStatic
fun createRNMediaUsingMimeType(
id: Int,
url: String,
mimeType: String?,
caption: String?,
title: String?,
): Media {
val type = convertToType(mimeType)
return Media(id, url, type, caption ?: "", title ?: "")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ public struct MediaInfo: Encodable {
public let type: String?
public let title: String?
public let caption: String?
public let alt: String?

public init(id: Int32?, url: String?, type: String?, caption: String? = nil, title: String? = nil) {
public init(id: Int32?, url: String?, type: String?, caption: String? = nil, title: String? = nil, alt: String? = nil) {
self.id = id
self.url = url
self.type = type
self.caption = caption
self.title = title
self.alt = alt
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/react-native-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ For each user feature we should also add a importance categorization label to i
## Unreleased

- [*] Add 'Insert from URL' option to Video block [#41493]
- [*] Image block copies the alt text from the media library when selecting an item [#41839]

## 1.78.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ exports.imageCompletehtml = `<!-- wp:image {"id":1,"sizeslug":"large"} -->
<!-- /wp:paragraph -->`;

exports.imageShorteHtml = `<!-- wp:image {"id":1,"sizeslug":"large"} -->
<figure class="wp-block-image size-large"><img src="https://cldup.com/cXyG__fTLN.jpg" alt="" class="wp-image-1"/><figcaption>C'est la vie my friends</figcaption></figure>
<figure class="wp-block-image size-large"><img src="https://cldup.com/cXyG__fTLN.jpg" alt="A snow-capped mountain top in a cloudy sky with red-leafed trees in the foreground" class="wp-image-1"/><figcaption>C'est la vie my friends</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.gutenberg;

import static org.wordpress.mobile.WPAndroidGlue.Media.createRNMediaUsingMimeType;

import android.app.Application;
import android.content.Intent;
import android.content.res.Configuration;
Expand Down Expand Up @@ -83,17 +85,17 @@ public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelected

switch (mediaType) {
case IMAGE:
rnMediaList.add(new Media(1, "https://cldup.com/cXyG__fTLN.jpg", "image", "Mountain", ""));
rnMediaList.add(createRNMediaUsingMimeType(1, "https://cldup.com/cXyG__fTLN.jpg", "image", "Mountain", "", "A snow-capped mountain top in a cloudy sky with red-leafed trees in the foreground"));
break;
case VIDEO:
rnMediaList.add(new Media(2, "https://i.cloudup.com/YtZFJbuQCE.mov", "video", "Cloudup", ""));
rnMediaList.add(createRNMediaUsingMimeType(2, "https://i.cloudup.com/YtZFJbuQCE.mov", "video", "Cloudup", ""));
break;
case ANY:
case OTHER:
rnMediaList.add(new Media(3, "https://wordpress.org/latest.zip", "zip", "WordPress latest version", "WordPress.zip"));
rnMediaList.add(createRNMediaUsingMimeType(3, "https://wordpress.org/latest.zip", "zip", "WordPress latest version", "WordPress.zip"));
break;
case AUDIO:
rnMediaList.add(new Media(5, "https://cldup.com/59IrU0WJtq.mp3", "audio", "Summer presto", ""));
rnMediaList.add(createRNMediaUsingMimeType(5, "https://cldup.com/59IrU0WJtq.mp3", "audio", "Summer presto", ""));
break;
}
mediaSelectedCallback.onMediaFileSelected(rnMediaList);
Expand Down Expand Up @@ -145,7 +147,7 @@ public void getOtherMediaPickerOptions(OtherMediaOptionsReceivedCallback otherMe
public void requestMediaPickFrom(String mediaSource, MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection) {
if (mediaSource.equals("1")) {
List<RNMedia> rnMediaList = new ArrayList<>();
rnMediaList.add(new Media(1, "https://grad.illinois.edu/sites/default/files/pdfs/cvsamples.pdf", "other", "","cvsamples.pdf"));
rnMediaList.add(createRNMediaUsingMimeType(1, "https://grad.illinois.edu/sites/default/files/pdfs/cvsamples.pdf", "other", "","cvsamples.pdf"));
mediaSelectedCallback.onMediaFileSelected(rnMediaList);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
case .image:
if(allowMultipleSelection) {
callback([MediaInfo(id: 1, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image"),
MediaInfo(id: 3, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image", caption: "Mountain")])
MediaInfo(id: 3, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image", caption: "Mountain", alt: "A snow-capped mountain top in a cloudy sky with red-leafed trees in the foreground")])
} else {
callback([MediaInfo(id: 1, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image", caption: "Mountain")])
callback([MediaInfo(id: 1, url: "https://cldup.com/cXyG__fTLN.jpg", type: "image", caption: "Mountain", alt: "A snow-capped mountain top in a cloudy sky with red-leafed trees in the foreground")])
}
case .video:
if(allowMultipleSelection) {
Expand Down