{@snippet features/build-media-source}
The {@link module:media-embed/mediaembed~MediaEmbed} feature brings support for embeddable media (such as YouTube videos or tweets) in the editor content.
Depending on configuration, it may require using services like iframely or embed.ly to display content of these embedded media on your target website. Read more about displaying embedded media.
Example URLs:
{@snippet features/media-embed}
To add this feature to your editor, install the @ckeditor/ckeditor5-media-embed package:
npm install --save @ckeditor/ckeditor5-media-embed
Then add 'MediaEmbed' to your plugin list and {@link module:media-embed/mediaembed~MediaEmbedConfig configure} the feature:
import MediaEmbed from '@ckeditor/ckeditor5-media-embed/src/mediaembed';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ MediaEmbed, ... ],
toolbar: [ 'mediaEmbed', ... ]
mediaEmbed: {
// configuration...
}
} )
.then( ... )
.catch( ... );
The data output format of the feature can be configured using the {@link module:media-embed/mediaembed~MediaEmbedConfig#semanticDataOutput config.mediaEmbed.semanticDataOutput}:
TODO (when false, default) – outputs media in the same way it works in the editor, i.e. the media preview is saved to the database.
<figure class="media">
<div data-oembed-url="https://url">
<iframe src="https://preview"></iframe>
</div>
</figure>
TODO (when true) – does not include the preview of the media, just just the <oembed> tag with the url attribute. Best when the application processes (expands) the media on the server–side or directly in the front–end, preserving the versatile database representation.
<figure class="media">
<oembed url="https://url"></oembed>
</figure>
You can easily [expand](#using-media-in-the-frontend) the media using popular embed services in the front–end of your application regardless of the data output type you chose in your database.
CKEditor comes with several supported media providers which can be extended or altered.
Names of providers with previews:
'dailymotion','spotify','youtube','vimeo'Names of providers without previews:
'instagram','twitter','google','flickr','facebook'
The default media provider configuration may not support all possible media URLs, only the most common are included.
To override the default providers, use {@link module:media-embed/mediaembed~MediaEmbedConfig#providers config.mediaEmbed.providers} and define your set according to the {@link module:media-embed/mediaembed~MediaEmbedProvider provider syntax}:
ClassicEditor
.create( editorElement, {
plugins: [ MediaEmbed, ... ],
mediaEmbed: {
providers: [
{
name: 'myProvider',
url: /^(https:\/\/)?(www\.)?example\.com\/media\/(\w+)/,
html: mediaId => '...'
},
...
]
}
} )
.then( ... )
.catch( ... );
To extend the default list of default providers, use {@link module:media-embed/mediaembed~MediaEmbedConfig#extraProviders config.mediaEmbed.extraProviders}.
To remove certain providers, use {@link module:media-embed/mediaembed~MediaEmbedConfig#removeProviders config.mediaEmbed.premoveProviders}.
The media embed feature produces output that may not contain previews of some embedded media. That happens for all media types when the feature is configured to produce a semantic output and for non-previewable media in the default configuration. That means that you need to transform the output <oembed> elements into real media on your target website.
There are many ways to do that. The simplest, plug-and-play solutions are described here. You can also implement this transformation as part of your backend service and you can use different services than described in this section.
Iframely offers the embed.js library which converts various media URLs into rich previews. It works in the front–end and remains fully compatible with the output produced by CKEditor.
First, having secured the API key, load the embed.js library from the CDN into your website:
<head>
...
<script charset="utf-8" src="//cdn.iframe.ly/embed.js?api_key={API KEY}"></script>
...
</head>
You can convert all {@link module:media-embed/mediaembed~MediaEmbedConfig#semanticDataOutput semantic media} like the following Twitter post produced by CKEditor
<figure class="media">
<oembed url="https://twitter.com/ckeditor/status/1021777799844126720"></oembed>
</figure>
using this short code snippet
<script>
document.querySelectorAll( 'oembed[url]' ).forEach( element => {
iframely.load( element, element.attributes.url.value ) ;
} );
</script>
Despite including the media preview, the {@link module:media-embed/mediaembed~MediaEmbedConfig#semanticDataOutput non–semantic} data like the following one
<figure class="media">
<div data-oembed-url="https://twitter.com/ckeditor/status/1021777799844126720">
[Media preview]
</div>
</figure>
can still be converted by Iframely with just a few extra lines of code. To do that, use a slightly longer code snippet which discards the media preview saved in the database before using iframely.load():
<script>
document.querySelectorAll( 'div[data-oembed-url]' ).forEach( element => {
// Discard the static media preview from the database (empty the <div data-oembed-url="...">).
while ( element.firstChild ) {
element.removeChild( element.firstChild );
}
// Generate the media preview using Iframely.
iframely.load( element, element.dataset.oembedUrl ) ;
} );
</script>
Just like Iframely, Embedly offers the client–side API which converts media URLs into rich previews.
To start using it, load the library from the CDN into your website:
<head>
...
<script async charset="utf-8" src="//cdn.embedly.com/widgets/platform.js"></script>
...
</head>
You can convert all {@link module:media-embed/mediaembed~MediaEmbedConfig#semanticDataOutput semantic media} like the following Twitter post produced by CKEditor
<figure class="media">
<oembed url="https://twitter.com/ckeditor/status/1021777799844126720"></oembed>
</figure>
using this code snippet
<script>
document.querySelectorAll( 'oembed[url]' ).forEach( element => {
// Create the <a href="..." class="embedly-card"></a> element that Embedly uses
// to discover the media.
const anchor = document.createElement( 'a' );
anchor.setAttribute( 'href', element.getAttribute( 'url ') );
anchor.className = 'embedly-card';
element.appendChild( anchor );
} );
</script>
Embedly discovers links like <a href="..." class="embedly-card"></a> and replaces them with rich media previews.
The code is almost the same as with the semantic data but you should discard the media preview saved in the database before using embedly to avoid code duplication:
<script>
document.querySelectorAll( 'div[data-oembed-url]' ).forEach( element => {
// Discard the static media preview from the database (empty the <div data-oembed-url="...">).
while ( element.firstChild ) {
element.removeChild( element.firstChild );
}
// Create the <a href="..." class="embedly-card"></a> element that Embedly uses
// to discover the media.
const anchor = document.createElement( 'a' );
anchor.setAttribute( 'href', element.dataset.oembedUrl );
anchor.className = 'embedly-card';
element.appendChild( anchor );
} );
</script>
The {@link module:media-embed/mediaembed~MediaEmbed} plugin registers:
'mediaEmbed' UI button component,the 'mediaEmbed' command implemented by {@link module:media-embed/mediaembedcommand~MediaEmbedCommand}.
You can insert a new media or update the selected media URL by executing the following code:
editor.execute( 'mediaEmbed', { url: 'http://url.to.the/media' } );
The source code of the feature is available on GitHub in https://github.com/ckeditor/ckeditor5-media-embed.