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

Embed Block: Fix Aspect Ratio Classes #29641 #41141

Merged
merged 4 commits into from
Mar 8, 2023
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
28 changes: 16 additions & 12 deletions packages/block-library/src/embed/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {
createUpgradedEmbedBlock,
getClassNames,
removeAspectRatioClasses,
fallback,
getEmbedInfoByProvider,
getMergedAttributesWithPreview,
Expand Down Expand Up @@ -99,16 +100,14 @@ const EmbedEdit = ( props ) => {
/**
* Returns the attributes derived from the preview, merged with the current attributes.
*
* @param {boolean} ignorePreviousClassName Determines if the previous className attribute should be ignored when merging.
* @return {Object} Merged attributes.
*/
const getMergedAttributes = ( ignorePreviousClassName = false ) =>
const getMergedAttributes = () =>
getMergedAttributesWithPreview(
attributes,
preview,
title,
responsive,
ignorePreviousClassName
responsive
);

const toggleResponsive = () => {
Expand Down Expand Up @@ -136,21 +135,20 @@ const EmbedEdit = ( props ) => {
setURL( newURL );
setIsEditingURL( false );
setAttributes( { url: newURL } );
}, [ preview?.html, attributesUrl ] );
}, [ preview?.html, attributesUrl, cannotEmbed, fetching ] );

// Handle incoming preview.
useEffect( () => {
if ( preview && ! isEditingURL ) {
// When obtaining an incoming preview, we set the attributes derived from
// the preview data. In this case when getting the merged attributes,
// we ignore the previous classname because it might not match the expected
// classes by the new preview.
setAttributes( getMergedAttributes( true ) );
// When obtaining an incoming preview,
// we set the attributes derived from the preview data.
const mergedAttributes = getMergedAttributes();
setAttributes( mergedAttributes );

if ( onReplace ) {
const upgradedBlock = createUpgradedEmbedBlock(
props,
getMergedAttributes()
mergedAttributes
);

if ( upgradedBlock ) {
Expand Down Expand Up @@ -188,8 +186,14 @@ const EmbedEdit = ( props ) => {
event.preventDefault();
}

// If the embed URL was changed, we need to reset the aspect ratio class.
// To do this we have to remove the existing ratio class so it can be recalculated.
const blockClass = removeAspectRatioClasses(
attributes.className
);

setIsEditingURL( false );
setAttributes( { url } );
setAttributes( { url, className: blockClass } );
} }
value={ url }
cannotEmbed={ cannotEmbed }
Expand Down
46 changes: 28 additions & 18 deletions packages/block-library/src/embed/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import {
createUpgradedEmbedBlock,
getClassNames,
removeAspectRatioClasses,
fallback,
getEmbedInfoByProvider,
getMergedAttributesWithPreview,
Expand Down Expand Up @@ -123,16 +124,14 @@ const EmbedEdit = ( props ) => {
/**
* Returns the attributes derived from the preview, merged with the current attributes.
*
* @param {boolean} ignorePreviousClassName Determines if the previous className attribute should be ignored when merging.
* @return {Object} Merged attributes.
*/
const getMergedAttributes = ( ignorePreviousClassName = false ) =>
const getMergedAttributes = () =>
getMergedAttributesWithPreview(
attributes,
preview,
title,
responsive,
ignorePreviousClassName
responsive
);

const toggleResponsive = () => {
Expand All @@ -159,21 +158,20 @@ const EmbedEdit = ( props ) => {
const newURL = url.replace( /\/$/, '' );
setIsEditingURL( false );
setAttributes( { url: newURL } );
}, [ preview?.html, url ] );
}, [ preview?.html, url, cannotEmbed, fetching ] );

// Handle incoming preview.
useEffect( () => {
if ( preview && ! isEditingURL ) {
// When obtaining an incoming preview, we set the attributes derived from
// the preview data. In this case when getting the merged attributes,
// we ignore the previous classname because it might not match the expected
// classes by the new preview.
setAttributes( getMergedAttributes( true ) );
// When obtaining an incoming preview,
// we set the attributes derived from the preview data.
const mergedAttributes = getMergedAttributes();
setAttributes( mergedAttributes );

if ( onReplace ) {
const upgradedBlock = createUpgradedEmbedBlock(
props,
getMergedAttributes()
mergedAttributes
);

if ( upgradedBlock ) {
Expand All @@ -188,13 +186,25 @@ const EmbedEdit = ( props ) => {
[ isEditingURL ]
);

const onEditURL = useCallback( ( value ) => {
// The order of the following calls is important, we need to update the URL attribute before changing `isEditingURL`,
// otherwise the side-effect that potentially replaces the block when updating the local state won't use the new URL
// for creating the new block.
setAttributes( { url: value } );
setIsEditingURL( false );
}, [] );
const onEditURL = useCallback(
( value ) => {
// If the embed URL was changed, we need to reset the aspect ratio class.
// To do this we have to remove the existing ratio class so it can be recalculated.
if ( attributes.url !== value ) {
const blockClass = removeAspectRatioClasses(
attributes.className
);
setAttributes( { className: blockClass } );
}

// The order of the following calls is important, we need to update the URL attribute before changing `isEditingURL`,
// otherwise the side-effect that potentially replaces the block when updating the local state won't use the new URL
// for creating the new block.
setAttributes( { url: value } );
setIsEditingURL( false );
},
[ attributes, setAttributes ]
);

const blockProps = useBlockProps();

Expand Down
12 changes: 12 additions & 0 deletions packages/block-library/src/embed/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
createUpgradedEmbedBlock,
getEmbedInfoByProvider,
removeAspectRatioClasses,
hasAspectRatioClass,
} from '../util';
import { embedInstagramIcon } from '../icons';
import variations from '../variations';
Expand Down Expand Up @@ -101,6 +102,17 @@ describe( 'utils', () => {
).toEqual( expected );
} );
} );
describe( 'hasAspectRatioClass', () => {
it( 'should return false if an aspect ratio class does not exist', () => {
const existingClassNames = 'wp-block-embed is-type-video';
expect( hasAspectRatioClass( existingClassNames ) ).toBe( false );
} );
it( 'should return true if an aspect ratio class exists', () => {
const existingClassNames =
'wp-block-embed is-type-video wp-embed-aspect-16-9 wp-has-aspect-ratio';
expect( hasAspectRatioClass( existingClassNames ) ).toBe( true );
} );
} );
describe( 'removeAspectRatioClasses', () => {
it( 'should return the same falsy value as received', () => {
const existingClassNames = undefined;
Expand Down
37 changes: 29 additions & 8 deletions packages/block-library/src/embed/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,21 @@ export const createUpgradedEmbedBlock = (
} );
};

/**
* Determine if the block already has an aspect ratio class applied.
*
* @param {string} existingClassNames Existing block classes.
* @return {boolean} True or false if the classnames contain an aspect ratio class.
*/
export const hasAspectRatioClass = ( existingClassNames ) => {
if ( ! existingClassNames ) {
return false;
}
return ASPECT_RATIOS.some( ( { className } ) =>
existingClassNames.includes( className )
);
};
TylerB24890 marked this conversation as resolved.
Show resolved Hide resolved

/**
* Removes all previously set aspect ratio related classes and return the rest
* existing class names.
Expand Down Expand Up @@ -283,6 +298,13 @@ export const getAttributesFromPreview = memoize(
attributes.providerNameSlug = providerNameSlug;
}

// Aspect ratio classes are removed when the embed URL is updated.
// If the embed already has an aspect ratio class, that means the URL has not changed.
// Which also means no need to regenerate it with getClassNames.
if ( hasAspectRatioClass( currentClassNames ) ) {
return attributes;
}

attributes.className = getClassNames(
html,
currentClassNames,
Expand All @@ -296,27 +318,26 @@ export const getAttributesFromPreview = memoize(
/**
* Returns the attributes derived from the preview, merged with the current attributes.
*
* @param {Object} currentAttributes The current attributes of the block.
* @param {Object} preview The preview data.
* @param {string} title The block's title, e.g. Twitter.
* @param {boolean} isResponsive Boolean indicating if the block supports responsive content.
* @param {boolean} ignorePreviousClassName Determines if the previous className attribute should be ignored when merging.
* @param {Object} currentAttributes The current attributes of the block.
* @param {Object} preview The preview data.
* @param {string} title The block's title, e.g. Twitter.
* @param {boolean} isResponsive Boolean indicating if the block supports responsive content.
* @return {Object} Merged attributes.
*/
export const getMergedAttributesWithPreview = (
currentAttributes,
preview,
title,
isResponsive,
ignorePreviousClassName = false
isResponsive
) => {
const { allowResponsive, className } = currentAttributes;

return {
...currentAttributes,
...getAttributesFromPreview(
preview,
title,
ignorePreviousClassName ? undefined : className,
className,
isResponsive,
allowResponsive
),
Expand Down