8
0
Aleksander Nowodzinski 7 лет назад
Родитель
Сommit
64fb5ec608

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

@@ -9,7 +9,7 @@
 
 import ViewRange from '@ckeditor/ckeditor5-engine/src/view/range';
 import first from '@ckeditor/ckeditor5-utils/src/first';
-import { getMediaContent, addMediaWrapperElementToFigure } from './utils';
+import { addMediaWrapperElementToFigure } from './utils';
 
 /**
  * Returns a function that converts the media wrapper view representation:
@@ -62,7 +62,9 @@ export function viewFigureToModel() {
 	}
 }
 
-export function modelToViewUrlAttributeConverter( editor, options ) {
+export function modelToViewUrlAttributeConverter( mediaRegistry, options ) {
+	const renderMediaHtml = options.isViewPipeline || options.renderMediaHtml;
+
 	return dispatcher => {
 		dispatcher.on( 'attribute:url:media', converter );
 	};
@@ -75,8 +77,13 @@ export function modelToViewUrlAttributeConverter( editor, options ) {
 		const viewWriter = conversionApi.writer;
 		const figure = conversionApi.mapper.toViewElement( data.item );
 		const attributes = {};
-		const withAspectWrapper = options.isEditingPipeline || options.shouldRenderContent;
-		const wrapperContent = withAspectWrapper ? getMediaContent( editor, data.attributeNewValue ) : null;
+		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 ) );
@@ -85,13 +92,12 @@ export function modelToViewUrlAttributeConverter( editor, options ) {
 			attributes[ 'data-oembed-url' ] = data.attributeNewValue;
 		}
 
-		if ( options.isEditingPipeline ) {
+		if ( options.isViewPipeline ) {
 			attributes.class = 'ck-media__wrapper';
 		}
 
 		addMediaWrapperElementToFigure( viewWriter, figure, {
-			withAspectWrapper,
-			wrapperContent,
+			mediaHtml,
 			attributes,
 		} );
 	}

+ 15 - 10
packages/ckeditor5-media-embed/src/mediaembedediting.js

@@ -16,6 +16,7 @@ import {
 
 import InsertMediaCommand from './insertmediacommand';
 import { toMediaWidget, createMediaFigureElement } from './utils';
+import { MediaRegistry } from './mediaregistry';
 import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
 import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 
@@ -127,6 +128,8 @@ export default class MediaEmbedEditing extends Plugin {
 		const conversion = editor.conversion;
 		const semanticDataOutput = editor.config.get( 'mediaEmbed.semanticDataOutput' );
 
+		this.mediaRegistry = new MediaRegistry( this.editor );
+
 		editor.commands.add( 'insertMedia', new InsertMediaCommand( editor ) );
 
 		// Configure the schema.
@@ -142,30 +145,32 @@ export default class MediaEmbedEditing extends Plugin {
 			model: 'media',
 			view: ( modelElement, viewWriter ) => {
 				return createMediaFigureElement( viewWriter, {
-					withAspectWrapper: !semanticDataOutput
+					renderMediaHtml: !semanticDataOutput
 				} );
 			}
 		} ) );
 
 		// Model -> Data (url -> data-oembed-url)
-		conversion.for( 'dataDowncast' )
-			.add( modelToViewUrlAttributeConverter( editor, {
-				shouldRenderContent: !semanticDataOutput
-			} ) );
+		conversion.for( 'dataDowncast' ).add( modelToViewUrlAttributeConverter( this.mediaRegistry, {
+			renderMediaHtml: !semanticDataOutput
+		} ) );
 
 		// Model -> View (element)
 		conversion.for( 'editingDowncast' ).add( downcastElementToElement( {
 			model: 'media',
 			view: ( modelElement, viewWriter ) => {
-				return toMediaWidget( createMediaFigureElement( viewWriter ), viewWriter, t( 'media widget' ) );
+				const figure = createMediaFigureElement( viewWriter, {
+					renderMediaHtml: true
+				} );
+
+				return toMediaWidget( figure, viewWriter, t( 'media widget' ) );
 			}
 		} ) );
 
 		// Model -> View (url -> data-oembed-url)
-		conversion.for( 'editingDowncast' )
-			.add( modelToViewUrlAttributeConverter( editor, {
-				isEditingPipeline: true
-			} ) );
+		conversion.for( 'editingDowncast' ).add( modelToViewUrlAttributeConverter( this.mediaRegistry, {
+			isViewPipeline: true
+		} ) );
 
 		// View -> Model (data-oembed-url -> url)
 		conversion.for( 'upcast' )

+ 5 - 7
packages/ckeditor5-media-embed/src/mediaembedui.js

@@ -10,8 +10,7 @@
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import { createDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';
 import MediaFormView from './ui/mediaformview';
-import { hasMediaContent } from './utils';
-
+import MediaEmbedEditing from './mediaembedediting';
 import mediaIcon from '../theme/icons/media.svg';
 
 /**
@@ -26,10 +25,11 @@ export default class MediaEmbedUI extends Plugin {
 	init() {
 		const editor = this.editor;
 		const command = editor.commands.get( 'insertMedia' );
+		const mediaRegistry = this.editor.plugins.get( MediaEmbedEditing ).mediaRegistry;
 
 		// Setup `imageUpload` button.
 		editor.ui.componentFactory.add( 'insertMedia', locale => {
-			const form = new MediaFormView( getFormValidators( editor ), locale );
+			const form = new MediaFormView( getFormValidators( editor.t, mediaRegistry ), locale );
 			const dropdown = createDropdown( locale );
 
 			this._setUpDropdown( dropdown, form, command, editor );
@@ -93,9 +93,7 @@ export default class MediaEmbedUI extends Plugin {
 	}
 }
 
-function getFormValidators( editor ) {
-	const t = editor.t;
-
+function getFormValidators( t, mediaRegistry ) {
 	return [
 		form => {
 			if ( !form.url.length ) {
@@ -103,7 +101,7 @@ function getFormValidators( editor ) {
 			}
 		},
 		form => {
-			if ( !hasMediaContent( editor, form.url ) ) {
+			if ( !mediaRegistry.has( form.url ) ) {
 				return t( 'This media URL is not supported.' );
 			}
 		}

+ 87 - 0
packages/ckeditor5-media-embed/src/mediaregistry.js

@@ -0,0 +1,87 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import mediaPlaceholderIcon from '../theme/icons/media-placeholder.svg';
+
+export class MediaRegistry {
+	constructor( editor ) {
+		this.editor = editor;
+		this.mediaProviders = editor.config.get( 'mediaEmbed.media' );
+	}
+
+	has( url ) {
+		if ( !url ) {
+			return null;
+		}
+
+		return !!this._getMedia( url );
+	}
+
+	getHtml( url, options ) {
+		if ( !url ) {
+			return null;
+		}
+
+		const media = this._getMedia( url );
+
+		if ( media ) {
+			return media.getHtml( options );
+		}
+	}
+
+	_getMedia( url ) {
+		const mediaProviders = this.mediaProviders;
+
+		url = url.trim();
+
+		for ( const name in mediaProviders ) {
+			let { url: pattern, html: renderer } = mediaProviders[ name ];
+
+			if ( !Array.isArray( pattern ) ) {
+				pattern = [ pattern ];
+			}
+
+			for ( const subPattern of pattern ) {
+				const match = url.match( subPattern );
+
+				if ( match ) {
+					return new Media( this.editor.t, url, match, renderer );
+				}
+			}
+		}
+
+		return null;
+	}
+}
+
+class Media {
+	constructor( t, url, match, renderer ) {
+		this.t = t;
+		this.url = url;
+		this.match = match;
+		this.renderer = renderer;
+	}
+
+	getHtml( options ) {
+		if ( this.renderer ) {
+			return this.renderer( this.match.pop() );
+		} else {
+			if ( options.usePlaceholderAsFallback ) {
+				return this._getPlaceholderHtml();
+			} else {
+				return '';
+			}
+		}
+	}
+
+	_getPlaceholderHtml() {
+		return '<div class="ck-media__placeholder">' +
+			`<div class="ck-media__placeholder__icon">${ mediaPlaceholderIcon }</div>` +
+			`<a class="ck-media__placeholder__url" target="new" href="${ this.url }" title="${ this.t( 'Open media in new tab' ) }">` +
+				this.url +
+			'</a>' +
+		'</div>';
+	}
+}

+ 2 - 58
packages/ckeditor5-media-embed/src/utils.js

@@ -10,8 +10,6 @@
 import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';
 import { toWidget } from '@ckeditor/ckeditor5-widget/src/utils';
 
-import mediaPlaceholderIcon from '../theme/icons/media-placeholder.svg';
-
 const mediaSymbol = Symbol( 'isMedia' );
 
 /**
@@ -54,11 +52,11 @@ export function createMediaFigureElement( writer, options = {} ) {
 export function addMediaWrapperElementToFigure( writer, figure, options ) {
 	let renderFunction;
 
-	if ( options.withAspectWrapper ) {
+	if ( options.mediaHtml ) {
 		renderFunction = function( domDocument ) {
 			const domElement = this.toDomElement( domDocument );
 
-			domElement.innerHTML = options.wrapperContent || '';
+			domElement.innerHTML = options.mediaHtml;
 
 			return domElement;
 		};
@@ -79,60 +77,6 @@ export function getSelectedMediaElement( selection ) {
 	return null;
 }
 
-export function getMediaContent( editor, url ) {
-	const data = getContentMatchAndRenderer( editor, url );
-
-	if ( data ) {
-		return data.contentViewRenderer( data.contentUrlMatch.pop() );
-	} else {
-		return '<p>No embeddable media found for given URL.</p>';
-	}
-}
-
-export function hasMediaContent( editor, url ) {
-	return !!getContentMatchAndRenderer( editor, url );
-}
-
-function getContentMatchAndRenderer( editor, url ) {
-	if ( !url ) {
-		return null;
-	}
-
-	const contentDefinitions = editor.config.get( 'mediaEmbed.media' );
-
-	url = url.trim();
-
-	for ( const name in contentDefinitions ) {
-		let { url: pattern, html: contentViewRenderer } = contentDefinitions[ name ];
-
-		if ( !Array.isArray( pattern ) ) {
-			pattern = [ pattern ];
-		}
-
-		for ( const subPattern of pattern ) {
-			const contentUrlMatch = url.match( subPattern );
-
-			if ( contentUrlMatch ) {
-				contentViewRenderer = contentViewRenderer || getDefaultContentRenderer( editor, url );
-
-				return { contentUrlMatch, contentViewRenderer };
-			}
-		}
-	}
-
-	return null;
-}
-
-function getDefaultContentRenderer( editor, url ) {
-	return () =>
-		'<div class="ck-media__placeholder">' +
-			`<div class="ck-media__placeholder__icon">${ mediaPlaceholderIcon }</div>` +
-			`<a class="ck-media__placeholder__url" target="new" href="${ url }" title="${ editor.t( 'Open media in new tab' ) }">` +
-				url +
-			'</a>' +
-		'</div>';
-}
-
 function getFillerOffset() {
 	return null;
 }

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

@@ -12,21 +12,43 @@
 
 <h2>Test editor</h2>
 <div id="editor">
-	<figure class="media">
-		<div data-oembed-url="https://www.youtube.com/watch?v=ZVv7UMQPEWk">
-			<iframe src="https://www.youtube.com/embed/ZVv7UMQPEWk" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen=""></iframe>
-		</div>
-	</figure>
-
-	<figure class="media">
-		<div data-oembed-url="https://vimeo.com/1084537"></div>
-	</figure>
-
-	<figure class="media">
-		<div data-oembed-url="https://open.spotify.com/artist/7GaxyUddsPok8BuhxN6OUW?si=LM7Q50vqQ4-NYnAIcMTNuQ"></div>
-	</figure>
-
-	<figure class="media">
-		<div data-oembed-url="https://ckeditor.com"></div>
-	</figure>
+	<h2>Media with previews</h2>
+		<figure class="media">
+			<div data-oembed-url="https://www.youtube.com/watch?v=ZVv7UMQPEWk"></div>
+		</figure>
+
+		<figure class="media">
+			<div data-oembed-url="https://vimeo.com/1084537"></div>
+		</figure>
+
+		<figure class="media">
+			<div data-oembed-url="https://open.spotify.com/artist/7GaxyUddsPok8BuhxN6OUW?si=LM7Q50vqQ4-NYnAIcMTNuQ"></div>
+		</figure>
+
+
+	<h2>Generic media</h2>
+
+		<figure class="media">
+			<div data-oembed-url="https://twitter.com/ckeditor/status/1021777799844126720"></div>
+		</figure>
+
+		<figure class="media">
+			<div data-oembed-url="https://www.flickr.com/photos/nasahqphoto/28396473968/"></div>
+		</figure>
+
+		<figure class="media">
+			<div data-oembed-url="https://www.instagram.com/p/BmMZgokAGGQ/?taken-by=nasa"></div>
+		</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>
+		</figure>
+
+		<figure class="media">
+			<div data-oembed-url="https://www.facebook.com/ckeditor/posts/1885390224856207"></div>
+		</figure>
+
+		<figure class="media">
+			<div data-oembed-url="https://ckeditor.com"></div>
+		</figure>
 </div>

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

@@ -10,7 +10,7 @@ import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 import normalizeHtml from '@ckeditor/ckeditor5-utils/tests/_utils/normalizehtml';
 
-describe( 'MediaEmbedEditing', () => {
+describe.only( 'MediaEmbedEditing', () => {
 	let editor, model, doc, view;
 	const mediaDefinitions = {
 		test: {
@@ -323,9 +323,7 @@ describe( 'MediaEmbedEditing', () => {
 							expect( editor.getData() ).to.equal(
 								'<figure class="media">' +
 									'<div data-oembed-url="http://ckeditor.com">' +
-										'<div class="ck-media__wrapper__aspect">' +
-											'<iframe src="http://ckeditor.com"></iframe>' +
-										'</div>' +
+										'<iframe src="http://ckeditor.com"></iframe>' +
 									'</div>' +
 								'</figure>' );
 						} );
@@ -336,7 +334,6 @@ describe( 'MediaEmbedEditing', () => {
 							expect( editor.getData() ).to.equal(
 								'<figure class="media">' +
 									'<div>' +
-										'<div class="ck-media__wrapper__aspect"></div>' +
 									'</div>' +
 								'</figure>' );
 						} );
@@ -347,9 +344,7 @@ describe( 'MediaEmbedEditing', () => {
 							editor.setData(
 								'<figure class="media">' +
 									'<div data-oembed-url="http://ckeditor.com">' +
-										'<div class="ck-media__wrapper__aspect">' +
-											'<iframe src="http://cksource.com"></iframe>' +
-										'</div>' +
+										'<iframe src="http://cksource.com"></iframe>' +
 									'</div>' +
 								'</figure>' );
 
@@ -392,9 +387,7 @@ describe( 'MediaEmbedEditing', () => {
 								'<div>' +
 									'<figure class="media">' +
 										'<div data-oembed-url="http://ckeditor.com">' +
-											'<div class="ck-media__wrapper__aspect">' +
-												'<iframe src="http://cksource.com"></iframe>' +
-											'</div>' +
+											'<iframe src="http://cksource.com"></iframe>' +
 										'</div>' +
 									'</figure>' +
 								'</div>' );
@@ -413,9 +406,7 @@ describe( 'MediaEmbedEditing', () => {
 								'<div>' +
 									'<figure class="media">' +
 										'<div data-oembed-url="http://ckeditor.com">' +
-											'<div class="ck-media__wrapper__aspect">' +
-												'<iframe src="http://cksource.com"></iframe>' +
-											'</div>' +
+											'<iframe src="http://cksource.com"></iframe>' +
 										'</div>' +
 									'</figure>' +
 								'</div>' );
@@ -489,9 +480,7 @@ describe( 'MediaEmbedEditing', () => {
 						expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
 							'<figure class="ck-widget media" contenteditable="false">' +
 								'<div class="ck-media__wrapper" data-oembed-url="http://ckeditor.com">' +
-									'<div class="ck-media__wrapper__aspect">' +
-										'<iframe src="http://ckeditor.com"></iframe>' +
-									'</div>' +
+									'<iframe src="http://ckeditor.com"></iframe>' +
 								'</div>' +
 							'</figure>'
 						);
@@ -508,9 +497,7 @@ describe( 'MediaEmbedEditing', () => {
 						expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
 							'<figure class="ck-widget media" contenteditable="false">' +
 								'<div class="ck-media__wrapper" data-oembed-url="http://cksource.com">' +
-									'<div class="ck-media__wrapper__aspect">' +
-										'<iframe src="http://cksource.com"></iframe>' +
-									'</div>' +
+									'<iframe src="http://cksource.com"></iframe>' +
 								'</div>' +
 							'</figure>'
 						);
@@ -528,9 +515,6 @@ describe( 'MediaEmbedEditing', () => {
 							.to.equal(
 								'<figure class="ck-widget media" contenteditable="false">' +
 									'<div class="ck-media__wrapper">' +
-										'<div class="ck-media__wrapper__aspect">' +
-											'<p>No embeddable media found for given URL.</p>' +
-										'</div>' +
 									'</div>' +
 								'</figure>'
 							);
@@ -551,9 +535,7 @@ describe( 'MediaEmbedEditing', () => {
 						expect( getViewData( view, { withoutSelection: true } ) ).to.equal(
 							'<figure class="ck-widget media" contenteditable="false">' +
 								'<div class="ck-media__wrapper" data-oembed-url="http://ckeditor.com">' +
-									'<div class="ck-media__wrapper__aspect">' +
-										'<iframe src="http://ckeditor.com"></iframe>' +
-									'</div>' +
+									'<iframe src="http://ckeditor.com"></iframe>' +
 								'</div>' +
 							'</figure>'
 						);