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

Added class information for core/embed in the frontend #4118

Merged
merged 1 commit into from
Feb 19, 2018
Merged

Added class information for core/embed in the frontend #4118

merged 1 commit into from
Feb 19, 2018

Conversation

Luehrsen
Copy link
Contributor

@Luehrsen Luehrsen commented Dec 21, 2017

Description

This piece of code extends the core/embed block to fetch the information provided by the oEmbed endpoint and adds information about the embed type and embed provider to the block wrapper.

<figure class="wp-block-embed-youtube wp-block-embed type-video provider-youtube">
    [...]
</figure>

This should provide precise information about what is being embedded to frontend developers and give them the ability to better style according to embedded content.

Please see #4107 for a more detailed description.

How Has This Been Tested?

This has been tested locally and manually. No automated tests were built or run.

Types of changes

New feature: Descriptive css classes for the frontend rendering of an embed block

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows has proper inline documentation.

@aduth
Copy link
Member

aduth commented Jan 2, 2018

The provider_name variable on line 126 should be sanitised.

By sanitized, do you just mean made safe for use in a class name?

In which case, you might be able to use one or more of Lodash's string methods:

@Luehrsen
Copy link
Contributor Author

Luehrsen commented Jan 2, 2018

@aduth That was exactly what I was looking for! Awesome!

Will update this PR tomorrow.

@aduth
Copy link
Member

aduth commented Jan 2, 2018

Noting that kebabCase should handle both escaping and dash-delimiting:

_.kebabCase( 'Foo" onerror="javascript:alert(\"hax\")"' )
// "foo-onerror-javascript-alert-hax"

@Luehrsen
Copy link
Contributor Author

Luehrsen commented Jan 3, 2018

I have provided a patch and sanitised the provider name. Thanks @aduth for the help!

At this point I am unsure how to handle the tests. I understand that the fixture html-files provide what the end result should look like, but most of the URLs are not valid oEmbed ressources.

So that is where I'm stuck at the moment.

@Luehrsen Luehrsen changed the title Added class information for core/embed in the frontend for #4107 Added class information for core/embed in the frontend Jan 4, 2018
Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

At this point I am unsure how to handle the tests. I understand that the fixture html-files provide what the end result should look like, but most of the URLs are not valid oEmbed ressources.

I think it should be enough to run npm run fixtures:regenerate and commit the changes?

const { html, type } = obj;
const { html, type, provider_name: providerName } = obj;
const providerNameSlug = kebabCase( toLower( providerName ) );
console.log(providerNameSlug, providerName);
Copy link
Member

Choose a reason for hiding this comment

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

We'll want to remove this debugging statement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed in recent commit.

@@ -114,11 +123,15 @@ function getEmbedBlockSettings( { title, icon, category = 'embed', transforms, k
return;
}
response.json().then( ( obj ) => {
const { html, type } = obj;
const { html, type, provider_name: providerName } = obj;
const providerNameSlug = kebabCase( toLower( providerName ) );
Copy link
Member

Choose a reason for hiding this comment

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

Does kebabCase not handle toLower already?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, afaik kebabCase handles lowerCase, not toLower, which leads to ugly transformations from YouTube to you-tube.


if ( ! url ) {
return;
}

const embedClassName = classnames(
'wp-block-embed',
align ? `align${ align }` : null,
Copy link
Member

Choose a reason for hiding this comment

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

A nice feature of classnames is passing an object for optionally included class names:

const embedClassName = classnames( 'wp-block-embed', {
	[ `align${ align }` ]: align,
	[ `type-${ type }` ]: type,
	[ `provider-${ providerNameSlug }` ]: providerNameSlug,
} );

https://www.npmjs.com/package/classnames

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to reflect the optionally included class names syntax.

@Luehrsen
Copy link
Contributor Author

Luehrsen commented Jan 4, 2018

Thank you @aduth for the review! Will implement these changes on the next commit.

I still have issues with the fixtures though. I am running the dev environment locally and through docker, as described here.

Running any of the npm run fixtures: commands gives me an error. I traced it to the ´get-server-blocks.php´ script, which expects a regular wordpress in the folders 'above' the gutenberg folder. By design this doesn't exist in the docker workflow.

Am I missing something?

@aduth
Copy link
Member

aduth commented Jan 5, 2018

I traced it to the ´get-server-blocks.php´ script, which expects a regular wordpress in the folders 'above' the gutenberg folder.

The script also accepts an ABSPATH environment variable (which I assume can also be passed through npm run fixtures:regenerate) to assign the WordPress folder location. I'm not entirely sure where this would exist in the Docker workflow since I'm not using Docker, but I can try to investigate (cc also @youknowriad).

@Luehrsen
Copy link
Contributor Author

Luehrsen commented Jan 6, 2018

I suspect the current issue is, that npm run fixtures:[...] does not work with the Docker workflow.

Can anyone confirm, that it works? And if so, how? (I already tried to run npm from inside the docker container, but obviously it did not have npm or any of the build requirements installed.)

const embedClassName = classnames( 'wp-block-embed', {
[ `align${ align }` ]: align,
[ `type-${ type }` ]: type,
[ `provider-${ providerNameSlug }` ]: providerNameSlug,
Copy link
Member

Choose a reason for hiding this comment

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

"align" is generally legacy for us, but for the others, let's try to use the is- and has- convention, which limits potential clashes. (The encouragement being that people would style as .wp-block-embed.is-provider-youtube.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good proposal. Will implement that with next commit.


if ( ! url ) {
return;
}

const embedClassName = classnames( 'wp-block-embed', {
Copy link
Member

Choose a reason for hiding this comment

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

This class should be auto-generated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Technically yes, but this is only true on the core/embed block. If the user chooses one of the flavored embed blocks, e.g. core/embed-youtube, the class will change to wp-block-embed-youtube and the wp-block-embed class will not be available anymore.

You could mitigate that in CSS with unqualified attribute selectors (as described in #4107), but that would be at a huge cost for frontend rendering performance.

So I am currently thinking about how to avoid class duplication on core/embed, the behavior on the flavored embeds is as intended.

Copy link
Member

Choose a reason for hiding this comment

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

Since for a YouTube embed, the wp-block-embed-youtube class is applied, isn't the is-provider-youtube class then redundant?

Copy link
Member

Choose a reason for hiding this comment

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

Non-blocking: We'd probably expect the fixture markup to be different for most embeds, i.e. including providerNameSlug and type attributes / classes:

<!-- wp:core-embed/youtube {"url":"https://www.youtube.com/watch?v=c-WDHG6rrdU","align":"right","type":"video","providerNameSlug":"youtube"} -->
<figure class="wp-block-embed-youtube wp-block-embed is-alignright is-type-video is-provider-youtube">
    https://www.youtube.com/watch?v=c-WDHG6rrdU
</figure>
<!-- /wp:core-embed/youtube -->

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The 'is-provider-' classes are needed for two reasons:

  1. We cannot be sure, that the user currently uses the correct block. They can use the wp-block-embed to yield the same result as with wp-block-embed-youtube. That was the whole premise of this PR.

  2. The provider name can be different for some providers like the wordpress embed, where it describes the URL where the content is coming from. That adds another level of description for theme editors. (Like the ability to style the WP Embed block differently by provider.)

As for the fixture markup, how would I approach that? Do I have to add that by hand?

@pento
Copy link
Member

pento commented Jan 10, 2018

In #4279, I've changed the fixtures:server-registered script to run in the Docker instance, so that it no longer requires a local WordPress install.

@pento
Copy link
Member

pento commented Jan 10, 2018

Oh, in the mean time, you should be able to run this, instead of npm run fixtures:regenerate:

> npm run fixtures:clean
> docker-compose -f docker/docker-compose.yml run -w /var/www/html/wp-content/plugins/gutenberg -e ABSPATH=/usr/src/wordpress/ --rm wordpress ./bin/get-server-blocks.php > blocks/test/server-registered.json
> cross-env GENERATE_MISSING_FIXTURES=y npm run test-unit

@Luehrsen
Copy link
Contributor Author

@pento Awesome, thanks! One quick note: I had to install cross-env globally to make it run.

And I still think I'm doing something wrong with the fixtures.

Anyways, on round of drinks on me in Belgrade.

@pento
Copy link
Member

pento commented Jan 11, 2018

Oh, it looks like you don't need to use cross-env, you can just run GENERATE_MISSING_FIXTURES=y npm run test-unit.

The current errors are caused by the fixture files not having the wp-block-embed class - you'll need to add that manually to the core-embed__*.html files, then regenerate the fixtures.

@Luehrsen
Copy link
Contributor Author

@pento Thanks a lot. Fixtures seem to work now.

Travis still complains, but that doesn't seem to be related to the tests, something in npm fails.


if ( ! url ) {
return;
}

const embedClassName = classnames( {
[ `wp-block-embed` ]: true,
Copy link
Member

Choose a reason for hiding this comment

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

Plain strings should use single quotes - this is the Travis error you're seeing.

@Luehrsen
Copy link
Contributor Author

Luehrsen commented Jan 12, 2018

Okay, this seems to be what I wanted to do.

With this I have introduced a duplication issue on the core/embed block. (Which now has the wp-block-embed class twice.) This is a result of forcing the wp-block-embedclass onto the child blocks like core-embed/vine and core-embed/youtube.

I would address the issue in another PR, where I add a proper duplication check in the addGeneratedClassName class.

( And thanks to @pento, @aduth and @mtias for your patience with me! )

@Luehrsen
Copy link
Contributor Author

@aduth Any timeline, thoughts or requirements for this PR going to be merged? :)

Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

Should the fixtures HTML be updated to include examples of where we'd now expect providerNameSlug and type?

Apologies for the delay in re-reviewing this one. I'm away on a work trip this week but will try to keep a closer eye on it.

if ( html ) {
this.setState( { html, type } );
this.setState( { html, type, providerNameSlug } );
setAttributes( { type, providerNameSlug } );
Copy link
Member

Choose a reason for hiding this comment

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

If we're setting this into attributes, is there a need on the previous line to set into state as well? Wouldn't this be redundant, and at worst potentially fall out of sync?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I have tested we actually need both. The state delivers the html, while the attributes deliver stuff that is needed on save. But I am far away from understanding the inner workings of react.

Copy link
Member

Choose a reason for hiding this comment

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

Noting that because this sets attributes, when loading an existing post which had contained the previous embed block, it will immediately become marked as "dirty" (i.e. needing save) because its attributes have changed.

I guess this would be expected though.

@@ -0,0 +1,6 @@
<!-- wp:core-embed/vine {"url":"https://vine.com/"} -->
Copy link
Member

Choose a reason for hiding this comment

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

I think these Vine files were inadvertently reintroduced after being removed in #4521.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Merging the master branch into my PR branch should fix it, or should it not?

Copy link
Member

Choose a reason for hiding this comment

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

No, I think it will re-add the files when merged.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have deleted them by hand now. That should do the trick.

@@ -3242,6 +3242,44 @@
"estraverse": "4.2.0"
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't expect there should be any changes to this file if we're not updating package.json.

@Luehrsen
Copy link
Contributor Author

Luehrsen commented Feb 1, 2018

@aduth can you take a quick look at the recent changes and merge if it fits? :)

aduth
aduth previously requested changes Feb 1, 2018
Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

The permissions changes on package-lock.json are unexpected.


if ( ! url ) {
return;
}

const embedClassName = classnames( 'wp-block-embed', {
Copy link
Member

Choose a reason for hiding this comment

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

Since for a YouTube embed, the wp-block-embed-youtube class is applied, isn't the is-provider-youtube class then redundant?


if ( ! url ) {
return;
}

const embedClassName = classnames( 'wp-block-embed', {
Copy link
Member

Choose a reason for hiding this comment

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

Non-blocking: We'd probably expect the fixture markup to be different for most embeds, i.e. including providerNameSlug and type attributes / classes:

<!-- wp:core-embed/youtube {"url":"https://www.youtube.com/watch?v=c-WDHG6rrdU","align":"right","type":"video","providerNameSlug":"youtube"} -->
<figure class="wp-block-embed-youtube wp-block-embed is-alignright is-type-video is-provider-youtube">
    https://www.youtube.com/watch?v=c-WDHG6rrdU
</figure>
<!-- /wp:core-embed/youtube -->

@aduth aduth added [Feature] Blocks Overall functionality of blocks and removed [Status] In Progress Tracking issues with work in progress labels Feb 1, 2018
@Luehrsen
Copy link
Contributor Author

Luehrsen commented Feb 2, 2018

@aduth @pento I might need help with the package-lock.json

I don't think I'm able to remove it from the PR, but I copied the current package-lock.json from origin/master by hand. Is there anything else I can do?

@aduth
Copy link
Member

aduth commented Feb 2, 2018

As for the fixture markup, how would I approach that? Do I have to add that by hand?

The .html (not .serialized.html) file in blocks/test/fixtures for each block is the only one which needs to be managed manually. The rest are automatically regenerated with the npm run fixtures:regenerate command. Again, this is not strictly necessary, though if we expect these blocks to be saved with that particular markup, even if optional, might be good to update the fixtures to reflect this.

I might need help with the package-lock.json. I don't think I'm able to remove it from the PR, but I copied the current package-lock.json from origin/master by hand.

Based on the contents, you might have copied an older version? I'd expect copying the contents from here and committing them should resolve any changes:

https://raw.githubusercontent.com/WordPress/gutenberg/master/package-lock.json

Otherwise, if you give me commit access to your fork, I could try to resolve it.

@Luehrsen
Copy link
Contributor Author

@aduth tried a last time by updating from hand from master.

If it is still out of sync, you should have access to my fork. :)

bildschirmfoto 2018-02-10 um 23 04 47

Greetings from Dubai!

@Luehrsen
Copy link
Contributor Author

@aduth Any chance of this getting some attention? Thanks!

Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

How should we plan to document for developers to apply styles to an embed block, if they must choose between .wp-block-embed-youtube and .is-provider-youtube?

I rebased your branch and force-pushed to your repository, to make sure it's up to date with latest changes. After verifying changes, you'll want to delete your local copy of your branch, git fetch, and git checkout anew.

if ( html ) {
this.setState( { html, type } );
this.setState( { html, type, providerNameSlug } );
setAttributes( { type, providerNameSlug } );
Copy link
Member

Choose a reason for hiding this comment

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

Noting that because this sets attributes, when loading an existing post which had contained the previous embed block, it will immediately become marked as "dirty" (i.e. needing save) because its attributes have changed.

I guess this would be expected though.

@aduth aduth dismissed their stale review February 19, 2018 16:55

package-lock.json changes undone

@Luehrsen
Copy link
Contributor Author

Luehrsen commented Feb 19, 2018

As for documentation of the different class types.

wp-block-embed-* gives definite information about what block is being used. This is not a reliable source, due to the fact that multiple values are valid for the same block. E.g.: A Youtube video can be used with wp-block-embed-youtube and wp-block-embed. This class is used to style a specific block.

is-type-* gives general information about the oEmbed type as per oEmbed spec. Valid values are Photo, Video, Link, Rich. This class is used to style a specific group of content. (E.g.: Make all Videos 16:9)

is-provider-* gives specific information about the provider of a piece of embedded content. This is mapped to the provider_name as per oEmbed spec. Please note, that the provider can be very broad, like 'youtube', or very specific, like is-provider-wp-munich for a link like https://www.wp-munich.com/wordpress/first-look-gutenberg-wordpress/.

Examples:
If you want to reliably style all embedded youtube videos: Use the .is-provider-youtube class.
If you want to reliably style all videos to be 16:9: Use the .is-type-video class.

Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

Looks good 👍 Thanks for your patience.

@aduth aduth merged commit 0ad578c into WordPress:master Feb 19, 2018
@aduth
Copy link
Member

aduth commented Feb 24, 2018

"align" is generally legacy for us, but for the others, let's try to use the is- and has- convention, which limits potential clashes. (The encouragement being that people would style as .wp-block-embed.is-provider-youtube.

@mtias Re-reading this, did you intend for alignment to be kept in legacy format?

It's is- prefixed as of the changes merged here.

I'm finding that, as such, there's a block invalidation in the demo content for embed by alignment:

gutenberg/post-content.js

Lines 129 to 131 in aa1df37

'<!-- wp:embed {"url":"https://vimeo.com/22439234","align":"wide"} -->',
'<figure class="wp-block-embed alignwide">https://vimeo.com/22439234</figure>',
'<!-- /wp:embed -->',

We need to decide between:

  • Revert to legacy format (from is-alignwide back to alignwide)
  • Update the demo post content

@mtias
Copy link
Member

mtias commented Feb 24, 2018

@aduth I'd like to update all classes, but it won't be a trivial thing. As it stands, we should probably just use alignwide until we can stop using alignleft, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Blocks Overall functionality of blocks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants