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 refactor and tidy #10958

Merged
merged 10 commits into from
Nov 1, 2018
43 changes: 3 additions & 40 deletions packages/block-library/src/embed/edit.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
/**
* Internal dependencies
*/
import { isFromWordPress, createUpgradedEmbedBlock } from './util';
import { ASPECT_RATIOS } from './constants';
import { isFromWordPress, createUpgradedEmbedBlock, getClassNames } from './util';
import { EmbedLoading, EmbedControls, EmbedPreview, EmbedEditUrl } from './components';

/**
* External dependencies
*/
import { kebabCase, toLower } from 'lodash';
import classnames from 'classnames/dedupe';

/**
* WordPress dependencies
Expand Down Expand Up @@ -77,37 +75,6 @@ export function getEmbedEditComponent( title, icon, responsive = true ) {
setAttributes( { url } );
}

/**
* Gets the appropriate CSS class names to enforce an aspect ratio when the embed is resized
* if the HTML has an iframe with width and height set.
*
* @param {string} html The preview HTML that possibly contains an iframe with width and height set.
* @param {boolean} allowResponsive If the classes should be added, or removed.
* @return {Object} Object with classnames set for use with `classnames`.
*/
getAspectRatioClassNames( html, allowResponsive = true ) {
const previewDocument = document.implementation.createHTMLDocument( '' );
previewDocument.body.innerHTML = html;
const iframe = previewDocument.body.querySelector( 'iframe' );

// If we have a fixed aspect iframe, and it's a responsive embed block.
if ( responsive && iframe && iframe.height && iframe.width ) {
const aspectRatio = ( iframe.width / iframe.height ).toFixed( 2 );
// Given the actual aspect ratio, find the widest ratio to support it.
for ( let ratioIndex = 0; ratioIndex < ASPECT_RATIOS.length; ratioIndex++ ) {
const potentialRatio = ASPECT_RATIOS[ ratioIndex ];
if ( aspectRatio >= potentialRatio.ratio ) {
return {
[ potentialRatio.className ]: allowResponsive,
'wp-has-aspect-ratio': allowResponsive,
};
}
}
}

return this.props.attributes.className;
}

/***
* Gets block attributes based on the preview and responsive state.
*
Expand All @@ -133,10 +100,7 @@ export function getEmbedEditComponent( title, icon, responsive = true ) {
attributes.providerNameSlug = providerNameSlug;
}

attributes.className = classnames(
this.props.attributes.className,
this.getAspectRatioClassNames( html, allowResponsive )
);
attributes.className = getClassNames( html, this.props.attributes.className, responsive && allowResponsive );

return attributes;
}
Expand All @@ -161,12 +125,11 @@ export function getEmbedEditComponent( title, icon, responsive = true ) {
toggleResponsive() {
const { allowResponsive, className } = this.props.attributes;
const { html } = this.props.preview;
const responsiveClassNames = this.getAspectRatioClassNames( html, ! allowResponsive );

this.props.setAttributes(
{
allowResponsive: ! allowResponsive,
className: classnames( className, responsiveClassNames ),
className: getClassNames( html, className, responsive && ! allowResponsive ),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering what the responsive variable is, is it whether the type of embed supports responsiveness?

On a separate note, it might be nice to extract ! allowResponsive into a separate variable so that it doesn't have to be repeated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, responsive is a flag for if the block allows responsive content or not.

}
);
}
Expand Down
37 changes: 36 additions & 1 deletion packages/block-library/src/embed/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
* Internal dependencies
*/
import { common, others } from './core-embeds';
import { DEFAULT_EMBED_BLOCK, WORDPRESS_EMBED_BLOCK } from './constants';
import { DEFAULT_EMBED_BLOCK, WORDPRESS_EMBED_BLOCK, ASPECT_RATIOS } from './constants';

/**
* External dependencies
*/
import { includes } from 'lodash';
import classnames from 'classnames/dedupe';

/**
* WordPress dependencies
Expand Down Expand Up @@ -113,3 +114,37 @@ export const createUpgradedEmbedBlock = ( props, attributesFromPreview ) => {
}
}
};

/**
* Returns class names with any relevant responsive aspect ratio names.
*
* @param {string} html The preview HTML that possibly contains an iframe with width and height set.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, I think the params are supposed to be lined up like they are here:

/**
* Returns the entity's getter method name given its kind and name.
*
* @param {string} kind Entity kind.
* @param {string} name Entity name.
* @param {string} prefix Function prefix.
* @param {boolean} usePlural Whether to use the plural form or not.
*
* @return {string} Method name
*/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it's actually really hard to find a good example of this, and I'm sure I just created some doc blocks where they weren't lined up myself 🤦‍♂️

* @param {string} existingClassNames Any existing class names.
* @param {boolean} allowResponsive If the responsive class names should be added, or removed.
* @return {string} Deduped class names.
*/
export function getClassNames( html, existingClassNames, allowResponsive = true ) {
const previewDocument = document.implementation.createHTMLDocument( '' );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose one future improvement is that this function is quite expensive when allowResponsive is false, when really all it has to do is strip the responsive classnames out of the string.

previewDocument.body.innerHTML = html;
const iframe = previewDocument.body.querySelector( 'iframe' );

// If we have a fixed aspect iframe, and it's a responsive embed block.
if ( iframe && iframe.height && iframe.width ) {
const aspectRatio = ( iframe.width / iframe.height ).toFixed( 2 );
// Given the actual aspect ratio, find the widest ratio to support it.
for ( let ratioIndex = 0; ratioIndex < ASPECT_RATIOS.length; ratioIndex++ ) {
const potentialRatio = ASPECT_RATIOS[ ratioIndex ];
if ( aspectRatio >= potentialRatio.ratio ) {
return classnames(
existingClassNames,
{
[ potentialRatio.className ]: allowResponsive,
'wp-has-aspect-ratio': allowResponsive,
}
);
}
}
}

return existingClassNames;
}