Explorar el Código

Used the <oembed> element in data for embeds without preview or when the semantic mode is on.

Aleksander Nowodzinski hace 7 años
padre
commit
219340e148

+ 11 - 13
packages/ckeditor5-media-embed/src/converters.js

@@ -74,31 +74,29 @@ export function modelToViewUrlAttributeConverter( mediaRegistry, options ) {
 			return;
 		}
 
+		const url = data.attributeNewValue;
 		const viewWriter = conversionApi.writer;
 		const figure = conversionApi.mapper.toViewElement( data.item );
-		const attributes = {};
-		let mediaHtml = null;
-
-		if ( renderMediaHtml ) {
-			mediaHtml = mediaRegistry.getHtml( data.attributeNewValue, {
-				usePlaceholderAsFallback: options.isViewPipeline
-			} );
-		}
 
 		// TODO: removing it and creating it from scratch is a hack. We can do better than that.
 		viewWriter.remove( ViewRange.createIn( figure ) );
 
-		if ( data.attributeNewValue !== null ) {
-			attributes[ 'data-oembed-url' ] = data.attributeNewValue;
+		const wrapperAttributes = {};
+		const useSemanticWrapper = !renderMediaHtml ||
+			( options.renderMediaHtml && !mediaRegistry.hasRenderer( url ) );
+
+		if ( url !== null ) {
+			wrapperAttributes[ renderMediaHtml ? 'data-oembed-url' : 'url' ] = url;
 		}
 
 		if ( options.isViewPipeline ) {
-			attributes.class = 'ck-media__wrapper';
+			wrapperAttributes.class = 'ck-media__wrapper';
 		}
 
 		addMediaWrapperElementToFigure( viewWriter, figure, {
-			mediaHtml,
-			attributes,
+			mediaHtml: renderMediaHtml ? mediaRegistry.getHtml( url ) : null,
+			attributes: wrapperAttributes,
+			useSemanticWrapper
 		} );
 	}
 }

+ 27 - 8
packages/ckeditor5-media-embed/src/mediaembedediting.js

@@ -146,24 +146,24 @@ export default class MediaEmbedEditing extends Plugin {
 		conversion.for( 'dataDowncast' ).add( downcastElementToElement( {
 			model: 'media',
 			view: ( modelElement, viewWriter ) => {
+				const url = modelElement.getAttribute( 'url' );
+
 				return createMediaFigureElement( viewWriter, {
-					renderMediaHtml: !semanticDataOutput
+					useSemanticWrapper: semanticDataOutput || !this.mediaRegistry.hasRenderer( url )
 				} );
 			}
 		} ) );
 
 		// Model -> Data (url -> data-oembed-url)
 		conversion.for( 'dataDowncast' ).add( modelToViewUrlAttributeConverter( this.mediaRegistry, {
-			renderMediaHtml: !semanticDataOutput
+			renderMediaHtml: !semanticDataOutput,
 		} ) );
 
 		// Model -> View (element)
 		conversion.for( 'editingDowncast' ).add( downcastElementToElement( {
 			model: 'media',
 			view: ( modelElement, viewWriter ) => {
-				const figure = createMediaFigureElement( viewWriter, {
-					renderMediaHtml: true
-				} );
+				const figure = createMediaFigureElement( viewWriter );
 
 				return toMediaWidget( figure, viewWriter, t( 'media widget' ) );
 			}
@@ -176,6 +176,23 @@ export default class MediaEmbedEditing extends Plugin {
 
 		// View -> Model (data-oembed-url -> url)
 		conversion.for( 'upcast' )
+			// Upcast semantic media.
+			.add( upcastElementToElement( {
+				view: {
+					name: 'oembed',
+					attributes: {
+						'url': true
+					}
+				},
+				model: ( viewMedia, modelWriter ) => {
+					const url = viewMedia.getAttribute( 'url' );
+
+					if ( this.mediaRegistry.has( url ) ) {
+						return modelWriter.createElement( 'media', { url } );
+					}
+				}
+			} ) )
+			// Upcast non-semantic media.
 			.add( upcastElementToElement( {
 				view: {
 					name: 'div',
@@ -184,9 +201,11 @@ export default class MediaEmbedEditing extends Plugin {
 					}
 				},
 				model: ( viewMedia, modelWriter ) => {
-					return modelWriter.createElement( 'media', {
-						url: viewMedia.getAttribute( 'data-oembed-url' )
-					} );
+					const url = viewMedia.getAttribute( 'data-oembed-url' );
+
+					if ( this.mediaRegistry.has( url ) ) {
+						return modelWriter.createElement( 'media', { url } );
+					}
 				}
 			} ) )
 			.add( viewFigureToModel() );

+ 9 - 7
packages/ckeditor5-media-embed/src/mediaregistry.js

@@ -12,11 +12,17 @@ export class MediaRegistry {
 	}
 
 	has( url ) {
+		return !!this._getMedia( url );
+	}
+
+	hasRenderer( url ) {
 		if ( !url ) {
 			return null;
 		}
 
-		return !!this._getMedia( url );
+		const media = this._getMedia( url );
+
+		return !!media.renderer;
 	}
 
 	getHtml( url, options ) {
@@ -62,15 +68,11 @@ class Media {
 		this.renderer = renderer;
 	}
 
-	getHtml( options ) {
+	getHtml() {
 		if ( this.renderer ) {
 			return this.renderer( this.match.pop() );
 		} else {
-			if ( options.usePlaceholderAsFallback ) {
-				return this._getPlaceholderHtml();
-			} else {
-				return '';
-			}
+			return this._getPlaceholderHtml();
 		}
 	}
 

+ 7 - 1
packages/ckeditor5-media-embed/src/utils.js

@@ -62,7 +62,13 @@ export function addMediaWrapperElementToFigure( writer, figure, options ) {
 		};
 	}
 
-	const wrapper = writer.createUIElement( 'div', options.attributes, renderFunction );
+	let wrapper;
+
+	if ( options.useSemanticWrapper ) {
+		wrapper = writer.createEmptyElement( 'oembed', options.attributes, renderFunction );
+	} else {
+		wrapper = writer.createUIElement( 'div', options.attributes, renderFunction );
+	}
 
 	writer.insert( ViewPosition.createAt( figure ), wrapper );
 }

+ 10 - 10
packages/ckeditor5-media-embed/tests/manual/mediaembed.html

@@ -13,42 +13,42 @@
 <h2>Test editor</h2>
 <div id="editor">
 	<h2>Media with previews</h2>
+
 		<figure class="media">
-			<div data-oembed-url="https://www.youtube.com/watch?v=ZVv7UMQPEWk"></div>
+			<oembed url="https://www.youtube.com/watch?v=ZVv7UMQPEWk" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://vimeo.com/1084537"></div>
+			<oembed url="https://vimeo.com/1084537" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://open.spotify.com/artist/7GaxyUddsPok8BuhxN6OUW?si=LM7Q50vqQ4-NYnAIcMTNuQ"></div>
+			<oembed url="https://open.spotify.com/artist/7GaxyUddsPok8BuhxN6OUW?si=LM7Q50vqQ4-NYnAIcMTNuQ" />
 		</figure>
 
-
 	<h2>Generic media</h2>
 
 		<figure class="media">
-			<div data-oembed-url="https://twitter.com/ckeditor/status/1021777799844126720"></div>
+			<oembed url="https://twitter.com/ckeditor/status/1021777799844126720" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.flickr.com/photos/nasahqphoto/28396473968/"></div>
+			<oembed url="https://www.flickr.com/photos/nasahqphoto/28396473968/" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.instagram.com/p/BmMZgokAGGQ/?taken-by=nasa"></div>
+			<oembed url="https://www.instagram.com/p/BmMZgokAGGQ/?taken-by=nasa" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.google.com/maps/place/Poland/@51.9537505,19.1343786,6z/data=!3m1!4b1!4m5!3m4!1s0x47009964a4640bbb:0x97573ca49cc55ea!8m2!3d51.919438!4d19.145136?hl=en"></div>
+			<oembed url="https://www.google.com/maps/place/Poland/@51.9537505,19.1343786,6z/data=!3m1!4b1!4m5!3m4!1s0x47009964a4640bbb:0x97573ca49cc55ea!8m2!3d51.919438!4d19.145136?hl=en" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.facebook.com/ckeditor/posts/1885390224856207"></div>
+			<oembed url="https://www.facebook.com/ckeditor/posts/1885390224856207" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://ckeditor.com"></div>
+			<oembed url="https://ckeditor.com" />
 		</figure>
 </div>

+ 9 - 10
packages/ckeditor5-media-embed/tests/manual/semanticmediaembed.html

@@ -14,41 +14,40 @@
 <div id="editor">
 	<h2>Media with previews</h2>
 		<figure class="media">
-			<div data-oembed-url="https://www.youtube.com/watch?v=ZVv7UMQPEWk"></div>
+			<oembed url="https://www.youtube.com/watch?v=ZVv7UMQPEWk" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://vimeo.com/1084537"></div>
+			<oembed url="https://vimeo.com/1084537" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://open.spotify.com/artist/7GaxyUddsPok8BuhxN6OUW?si=LM7Q50vqQ4-NYnAIcMTNuQ"></div>
+			<oembed url="https://open.spotify.com/artist/7GaxyUddsPok8BuhxN6OUW?si=LM7Q50vqQ4-NYnAIcMTNuQ" />
 		</figure>
 
-
 		<h2>Generic media</h2>
 
 		<figure class="media">
-			<div data-oembed-url="https://twitter.com/ckeditor/status/1021777799844126720"></div>
+			<oembed url="https://twitter.com/ckeditor/status/1021777799844126720" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.flickr.com/photos/nasahqphoto/28396473968/"></div>
+			<oembed url="https://www.flickr.com/photos/nasahqphoto/28396473968/" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.instagram.com/p/BmMZgokAGGQ/?taken-by=nasa"></div>
+			<oembed url="https://www.instagram.com/p/BmMZgokAGGQ/?taken-by=nasa" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.google.com/maps/place/Poland/@51.9537505,19.1343786,6z/data=!3m1!4b1!4m5!3m4!1s0x47009964a4640bbb:0x97573ca49cc55ea!8m2!3d51.919438!4d19.145136?hl=en"></div>
+			<oembed url="https://www.google.com/maps/place/Poland/@51.9537505,19.1343786,6z/data=!3m1!4b1!4m5!3m4!1s0x47009964a4640bbb:0x97573ca49cc55ea!8m2!3d51.919438!4d19.145136?hl=en" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://www.facebook.com/ckeditor/posts/1885390224856207"></div>
+			<oembed url="https://www.facebook.com/ckeditor/posts/1885390224856207" />
 		</figure>
 
 		<figure class="media">
-			<div data-oembed-url="https://ckeditor.com"></div>
+			<oembed url="https://ckeditor.com" />
 		</figure>
 </div>

+ 84 - 8
packages/ckeditor5-media-embed/tests/mediaembedediting.js

@@ -205,7 +205,7 @@ describe( 'MediaEmbedEditing', () => {
 
 						expect( editor.getData() ).to.equal(
 							'<figure class="media">' +
-								'<div data-oembed-url="http://ckeditor.com"></div>' +
+								'<oembed url="http://ckeditor.com"></oembed>' +
 							'</figure>' );
 					} );
 
@@ -214,14 +214,14 @@ describe( 'MediaEmbedEditing', () => {
 
 						expect( editor.getData() ).to.equal(
 							'<figure class="media">' +
-								'<div></div>' +
+								'<oembed></oembed>' +
 							'</figure>' );
 					} );
 				} );
 
 				describe( 'view to model', () => {
 					it( 'should convert media figure', () => {
-						editor.setData( '<figure class="media"><div data-oembed-url="http://ckeditor.com"></div></figure>' );
+						editor.setData( '<figure class="media"><oembed url="http://ckeditor.com"></oembed></figure>' );
 
 						expect( getModelData( model, { withoutSelection: true } ) )
 							.to.equal( '<media url="http://ckeditor.com"></media>' );
@@ -266,7 +266,7 @@ describe( 'MediaEmbedEditing', () => {
 						editor.conversion.elementToElement( { model: 'blockquote', view: 'blockquote' } );
 
 						editor.setData(
-							'<blockquote><figure class="media"><div data-oembed-url="http://ckeditor.com"></div></figure></blockquote>' );
+							'<blockquote><figure class="media"><oembed url="http://ckeditor.com"></oembed></figure></blockquote>' );
 
 						expect( getModelData( model, { withoutSelection: true } ) )
 							.to.equal( '<blockquote></blockquote>' );
@@ -278,7 +278,7 @@ describe( 'MediaEmbedEditing', () => {
 							conversionApi.consumable.consume( img, { name: true } );
 						}, { priority: 'high' } );
 
-						editor.setData( '<figure class="media"><div data-oembed-url="http://ckeditor.com"></div></figure>' );
+						editor.setData( '<figure class="media"><oembed url="http://ckeditor.com"></oembed></figure>' );
 
 						expect( getModelData( model, { withoutSelection: true } ) )
 							.to.equal( '' );
@@ -289,11 +289,44 @@ describe( 'MediaEmbedEditing', () => {
 							conversionApi.consumable.consume( data.viewItem, { name: true, class: 'image' } );
 						}, { priority: 'high' } );
 
-						editor.setData( '<figure class="media"><div data-oembed-url="http://ckeditor.com"></div></figure>' );
+						editor.setData( '<figure class="media"><oembed url="http://ckeditor.com"></oembed></figure>' );
 
 						expect( getModelData( model, { withoutSelection: true } ) )
 							.to.equal( '' );
 					} );
+
+					it( 'should discard the contents of the media', () => {
+						editor.setData( '<figure class="media"><oembed url="http://ckeditor.com">foo bar</oembed></figure>' );
+
+						expect( getModelData( model, { withoutSelection: true } ) )
+							.to.equal( '<media url="http://ckeditor.com"></media>' );
+					} );
+
+					it( 'should not convert unknown media', () => {
+						return VirtualTestEditor
+							.create( {
+								plugins: [ MediaEmbedEditing ],
+								mediaEmbed: {
+									semanticDataOutput: true,
+									media: [
+										{
+											url: /^http:\/\/known\.media/,
+											html: () => 'known-media'
+										}
+									]
+								}
+							} )
+							.then( newEditor => {
+								newEditor.setData(
+									'<figure class="media"><oembed url="http://unknown.media"></oembed></figure>' +
+									'<figure class="media"><oembed url="http://known.media"></oembed></figure>' );
+
+								expect( getModelData( newEditor.model, { withoutSelection: true } ) )
+									.to.equal( '<media url="http://known.media"></media>' );
+
+								return newEditor.destroy();
+							} );
+					} );
 				} );
 			} );
 
@@ -332,8 +365,8 @@ describe( 'MediaEmbedEditing', () => {
 
 							expect( editor.getData() ).to.equal(
 								'<figure class="media">' +
-									'<div>' +
-									'</div>' +
+									'<oembed>' +
+									'</oembed>' +
 								'</figure>' );
 						} );
 					} );
@@ -424,6 +457,49 @@ describe( 'MediaEmbedEditing', () => {
 							expect( getModelData( model, { withoutSelection: true } ) )
 								.to.equal( '' );
 						} );
+
+						it( 'should discard the contents of the media', () => {
+							editor.setData(
+								'<figure class="media">' +
+									'<div data-oembed-url="http://ckeditor.com">' +
+										'foo bar baz' +
+									'</div>' +
+								'</figure>' );
+
+							expect( getModelData( model, { withoutSelection: true } ) )
+								.to.equal( '<media url="http://ckeditor.com"></media>' );
+						} );
+
+						it( 'should not convert unknown media', () => {
+							return VirtualTestEditor
+								.create( {
+									plugins: [ MediaEmbedEditing ],
+									mediaEmbed: {
+										media: [
+											{
+												url: /^http:\/\/known\.media/,
+												html: () => 'known-media'
+											}
+										]
+									}
+								} )
+								.then( newEditor => {
+									newEditor.setData(
+										'<figure class="media">' +
+											'<div data-oembed-url="http://known.media">' +
+											'</div>' +
+										'</figure>' +
+										'<figure class="media">' +
+											'<div data-oembed-url="http://unknown.media">' +
+											'</div>' +
+										'</figure>' );
+
+									expect( getModelData( newEditor.model, { withoutSelection: true } ) )
+										.to.equal( '<media url="http://known.media"></media>' );
+
+									return newEditor.destroy();
+								} );
+						} );
 					} );
 				} );
 			} );