-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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 URLs on paste from text block #2192
Conversation
57368ed
to
9ebd63a
Compare
Asking for feedback for the general approach. We'll need to manually add matchers for every embed, not sure if we can pull this from core. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be acceptable to call the oembed API with URLs and see if they return anything? That seems a bit heavy on the async calls, but thought I'd suggest it anyway :) does for maintain a list of regexs on the client side?
(Afk til Monday here, sorry for not looking up the client side of things in core myself!)
@notnownikki No worries! Yes this will have a client side list. I think server side will give us a strange experience. Then we have no idea what sort of URLs are embeddable, we need to wait until we hear back from the server, by which time the text can have changed. We could also set a general embed placeholder, but then need to take it away when it can't be embedded. That seems pretty strange. With individual patterns we can make this experience a lot nicer than core atm. We can even show custom placeholders and block sizes if we want... |
5e4e1a0
to
646efe9
Compare
Ideally this list also has the block names, or some kind of identifier, and extra info we need on the client side such as title and icon. We also need to make sure the regular expressions are JS compatible https://github.com/WordPress/WordPress/blob/4.8.1/wp-includes/class-oembed.php#L57 |
blocks/editable/patterns.js
Outdated
@@ -47,6 +47,10 @@ export default function( editor ) { | |||
canUndo = null; | |||
} ); | |||
|
|||
editor.on( 'pastepostprocess', () => { | |||
setTimeout( space ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this affecting pasting non-url things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That will be fine, but I agree it's better to separate. Still needs polishing :)
blocks/library/embed/index.js
Outdated
@@ -39,6 +39,18 @@ function getEmbedBlockSettings( { title, icon, category = 'embed' } ) { | |||
caption: children( 'figcaption' ), | |||
}, | |||
|
|||
transforms: { | |||
from: matchers.map( ( regExp ) => ( { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While current direction of #1902 is to rename all references of "query" and "matchers" to "source", do you think we still ought to name this something more distinct? Like patterns
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Patterns sounds great, didn't thing about the renaming, thanks!
blocks/library/embed/index.js
Outdated
@@ -458,5 +470,11 @@ registerBlockType( | |||
getEmbedBlockSettings( { | |||
title: 'YouTube', | |||
icon: 'video-alt3', | |||
name: 'core-embed/youtube', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With some duplication here on block name, especially specific to the cases where we're providing patterns, do you have any thoughts on my suggestion at #2175 (review) for consolidating embed registration.
Maybe:
[
[ 'core/embed', 'Embed', 'video-alt3' ],
[ 'core-embed/twitter', 'Twitter', 'twitter' ],
[
'core-embed/youtube',
'YouTube',
'video-alt3',
[
/^\s*(https?:\/\/(?:m\.|www\.)?youtube\.com\/watch\S+)\s*/i,
/^\s*(https?:\/\/(?:m\.|www\.)?youtube\.com\/playlist\S+)\s*/i,
/^\s*(https?:\/\/youtu\.be\/\S+)\s*/i,
],
],
// ...
].forEach( ( [ blockName, title, icon, patterns ] ) => {
registerBlockType(
blockName,
getEmbedBlockSettings( {
title,
icon,
blockName,
patterns,
} )
);
} );
(Or instead of array structure, an object { blockName, title, icon, patterns }
)
My main concern being the implied dependency between name
and matchers
. Since name
is only being passed to getEmbedBlockSettings
if matchers
passed as well, this might mislead future maintainers to think they have access to name in future revisions to getEmbedBlockSettings
. Or, otherwise, we pass name
in all cases, but then we have excessive duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine either way tbh. Still thinking maybe it makes more sense to pass attributes rather than a block, and create the block in the patterns plugin. That should always be the same anyway. I think I did the same for paste.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be a great feature. I am a bit concerned about duplicating lists of supported embed providers between the core oembed class and the patterns file. Seems like a bit of overhead to maintain both, but understand the speed aspect of things.
I attempted to test using the following url: https://www.youtube.com/watch?v=ea2WoUtbzuw. The embed appears to begin taking place but then things go sideways and the following is shown in my console:
blocks/library/embed/index.js
Outdated
matchers: [ | ||
/^\s*(https?:\/\/(?:m\.|www\.)?youtube\.com\/watch\S+)\s*/i, | ||
/^\s*(https?:\/\/(?:m\.|www\.)?youtube\.com\/playlist\S+)\s*/i, | ||
/^\s*(https?:\/\/youtu\.be\/\S+)\s*/i, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As of r41179 core is now supporting YouTube embed URL patterns too, eg: https://www.youtube.com/embed/ea2WoUtbzuw
Should we create a Core API Task issue for listing all available embed patterns? Or bootstrap this data from PHP side†? Or just try running URL through oEmbed proxy endpoint and asynchronously updating if it returns a result? What about pasting custom embed providers? Scalability of this is concerning. † $oembed = _wp_oembed_get_object();
return $oembed->providers; |
If we decide to also do OpenGraph, maybe this is not needed... #2047 (comment) Then we just embed every URL that is pasted on its own line. |
180e7b7
to
d38ff02
Compare
Codecov Report
@@ Coverage Diff @@
## master #2192 +/- ##
==========================================
+ Coverage 22.99% 23.28% +0.28%
==========================================
Files 141 141
Lines 4393 4420 +27
Branches 746 748 +2
==========================================
+ Hits 1010 1029 +19
- Misses 2852 2859 +7
- Partials 531 532 +1
Continue to review full report at Codecov.
|
55a1e8b
to
aec2017
Compare
I love this. I think it might be nice to require you to press enter before the link is converted. I'm not sure. Perhaps it's okay to get this in as is, to get feedback, and then address as needed? |
blocks/library/embed/index.js
Outdated
{ | ||
type: 'pattern', | ||
trigger: 'paste', | ||
regExp: /^\s*(https:\/\/\S+)\s*/i, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The s
in https
should be optional: https?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all URLs will be https, but sure, let's be more tolerant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We ought to handle the case where the pasted URL is not embeddable. Currently it converts to an embed block, even when the oEmbed proxy returns with code: "oembed_invalid_url"
@@ -31,6 +31,7 @@ registerBlockType( 'core/code', { | |||
from: [ | |||
{ | |||
type: 'pattern', | |||
trigger: 'enter', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: These patterns are hard to discover. Didn't realize I had to Shift+Enter to trigger the transform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're broken in master. I need to fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Should work en plain enter.)
@aduth Are you okay with iterating on this? |
🚢 |
@@ -49,6 +48,10 @@ export default function( editor ) { | |||
canUndo = null; | |||
} ); | |||
|
|||
editor.on( 'pastepostprocess', () => { | |||
setTimeout( () => searchFirstText( pastePatterns ) ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the setTimeout
here (and the more recent inline
handling), we need to make sure that the editor still exists in searchFirstText
, since because it is called asynchronously, the editor might be removed in the time since scheduled. I discovered this in my own work (caused by an unrelated bug), but was difficult to track down the cause of the error'ing that occurs here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I noticed some issues too in another PR. While this specific line has been removed, it's still an issue in the keydown event callback.
Still needs some polishing. Only YouTube works for now.