Browse Source

Docs: Extended docs and refactored the code.

Aleksander Nowodzinski 7 years ago
parent
commit
f9c1c87bbb

+ 35 - 6
packages/ckeditor5-media-embed/src/converters.js

@@ -12,9 +12,11 @@ import first from '@ckeditor/ckeditor5-utils/src/first';
 import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';
 
 /**
- * Returns a function that converts the media wrapper view representation:
+ * Returns a function that converts the view media:
  *
- *		<figure class="media"><div data-oembed-url="..."></div></figure>
+ *		<figure class="media">
+ *			<div data-oembed-url="...">[ media content ]</div>
+ *		</figure>
  *
  * to the model representation:
  *
@@ -35,11 +37,12 @@ export function viewFigureToModel() {
 
 		// Find a div wrapper element inside the figure element.
 		const viewWrapper = Array.from( data.viewItem.getChildren() )
-			.find( viewChild => {
-				return viewChild.is( 'div' );
-			} );
+			.find( viewChild => viewChild.is( 'div' ) );
 
-		// Do not convert if the div wrapper element is absent, is missing data-oembed-url attribute or was already converted.
+		// Do not convert if:
+		// * the div wrapper element is absent,
+		// * the wrapper is missing the "data-oembed-url" attribute,
+		// * or the wrapper has already been converted.
 		if ( !viewWrapper ||
 			!viewWrapper.hasAttribute( 'data-oembed-url' ) ||
 			!conversionApi.consumable.test( viewWrapper, { name: true } ) ) {
@@ -65,6 +68,32 @@ export function viewFigureToModel() {
 	}
 }
 
+/**
+ * Returns a function that converts the model "url" attribute to the view representation.
+ *
+ * Depending on the configuration the view representation can be "sementaic" (for data pipeline):
+ *
+ *		<figure class="media">
+ *			<oembed url="foo"></div>
+ *		</figure>
+ *
+ * or "non-semantic" (for editing view pipeline):
+ *
+ *		<figure class="media">
+ *			<div data-oembed-url="foo">[ non-semantic media preview for "foo" ]</div>
+ *		</figure>
+ *
+ * **Note:** Changing the model "url" attribute replaces the entire content of the
+ * `<figure>` in the view.
+ *
+ * @param {module:media-embed/mediaregistry~MediaRegistry} mediaRegistry The registry providing
+ * the media and their content.
+ * @param {Object} options
+ * @param {String} [options.semanticDataOutput] When `true`, the converter will create view in the semantic form.
+ * @param {String} [options.renderForEditingView] When `true`, the converter will create a view specific for the
+ * editing pipeline (e.g. including CSS classes, content placeholders).
+ * @returns {Function}
+ */
 export function modelToViewUrlAttributeConverter( mediaRegistry, options ) {
 	const mediaViewElementOptions = {
 		useSemanticWrapper: options.semanticDataOutput,

+ 1 - 1
packages/ckeditor5-media-embed/src/insertmediacommand.js

@@ -47,7 +47,7 @@ export default class InsertMediaCommand extends Command {
 	 * Executes the command, which either:
 	 *
 	 * * updates the URL of a selected media,
-	 * * inserts the new media into the editor and selects it as a whole
+	 * * inserts the new media into the editor and puts the selection around it.
 	 *
 	 * @fires execute
 	 * @param {String} url The URL of the media.

+ 2 - 2
packages/ckeditor5-media-embed/src/mediaembed.js

@@ -18,8 +18,8 @@ import '../theme/mediaembed.css';
 /**
  * The media embed plugin.
  *
- * It loads the {@link module:table/mediaembedediting~MediaEmbedEditing media embed editing feature}
- * and {@link module:table/mediaembedui~TableUI media embed UI feature}.
+ * It loads the {@link module:media-embed/mediaembedediting~MediaEmbedEditing media embed editing feature}
+ * and {@link module:media-embed/mediaembedui~MediaEmbedUI media embed UI feature}.
  *
  * For a detailed overview, check the {@glink features/mediaembed Media Embed feature documentation}.
  *

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

@@ -115,13 +115,16 @@ export default class MediaEmbedEditing extends Plugin {
 
 				{
 					url: /^(https:\/\/)?(www\.)?facebook\.com/
-				},
-
-				{
-					url: /.*/
 				}
 			]
 		} );
+
+		/**
+		 * The media registry managing the media providers in the editor.
+		 *
+		 * @member {module:media-embed/mediaregistry~MediaRegistry} #mediaRegistry
+		 */
+		this.mediaRegistry = new MediaRegistry( editor.locale, editor.config.get( 'mediaEmbed.media' ) );
 	}
 
 	/**
@@ -133,7 +136,7 @@ export default class MediaEmbedEditing extends Plugin {
 		const t = editor.t;
 		const conversion = editor.conversion;
 		const semanticDataOutput = editor.config.get( 'mediaEmbed.semanticDataOutput' );
-		const mediaRegistry = this.mediaRegistry = new MediaRegistry( this.editor );
+		const mediaRegistry = this.mediaRegistry;
 
 		editor.commands.add( 'insertMedia', new InsertMediaCommand( editor ) );
 

+ 140 - 40
packages/ckeditor5-media-embed/src/mediaregistry.js

@@ -3,37 +3,86 @@
  * For licensing, see LICENSE.md.
  */
 
+/**
+ * @module media-embed/mediaregistry
+ */
+
 import mediaPlaceholderIcon from '../theme/icons/media-placeholder.svg';
 
+/**
+ * A bridge between the raw media content provider definitions and editor view content.
+ *
+ * It helps translating media URLs to corresponding {@link module:engine/view/element~Element view elements}.
+ *
+ * Mostly used by the {@link module:media-embed/mediaembedediting~MediaEmbedEditing} plugin.
+ */
 export class MediaRegistry {
-	constructor( editor ) {
-		this.editor = editor;
-		this.mediaProviders = editor.config.get( 'mediaEmbed.media' );
+	/**
+	 * Creates an instance of the {@link media-embed/mediaregistry~MediaRegistry} class.
+	 *
+	 * @param {module:utils/locale~Locale} locale The localization services instance.
+	 * @param {Array} providerDefinitions The provider definitions available in this registry.
+	 */
+	constructor( locale, providerDefinitions ) {
+		/**
+		 * The locale {@link module:utils/locale~Locale} instance.
+		 *
+		 * @member {module:utils/locale~Locale}
+		 */
+		this.locale = locale;
+
+		/**
+		 * The media provider definitions available for the registry. Usually corresponding with the
+		 * {@link module:media-embed/mediaembed~MediaEmbedConfig media configuration}.
+		 *
+		 * @member {Array}
+		 */
+		this.providerDefinitions = providerDefinitions;
 	}
 
+	/**
+	 * Checks whether the passed URL is representing a certain media type allowed in the editor.
+	 *
+	 * @param {String} url The url to be checked
+	 * @returns {Boolean}
+	 */
 	hasMedia( url ) {
 		return !!this._getMedia( url );
 	}
 
+	/**
+	 * For the given media URL string and options, it returns the {@link module:engine/view/element~Element view element}
+	 * representing that media.
+	 *
+	 * **Note:** If no URL is specified, an empty view element is returned.
+	 *
+	 * @param {module:engine/view/writer~Writer} writer The view writer used to produce a view element.
+	 * @param {String} url The url to be translated into a view element.
+	 * @param {Object} options
+	 * @param {String} [options.renderContent]
+	 * @param {String} [options.useSemanticWrapper]
+	 * @param {String} [options.renderForEditingView]
+	 * @returns {module:engine/view/element~Element}
+	 */
 	getMediaViewElement( writer, url, options ) {
-		let media;
-
-		if ( url ) {
-			media = this._getMedia( url );
-		} else {
-			// Generate a view for a renderer–less media. It will render as an empty media.
-			media = new Media( this.editor.t, url );
-		}
-
-		return media.getViewElement( writer, options );
+		return this._getMedia( url ).getViewElement( writer, options );
 	}
 
+	/**
+	 * Returns a `Media` instance for the given URL.
+	 *
+	 * @private
+	 * @param {String} url The url of the media.
+	 * @returns {module:media-embed/mediaregistry~Media|null} The `Media` instance or `null` when there's none.
+	 */
 	_getMedia( url ) {
-		const mediaProviders = this.mediaProviders;
+		if ( !url ) {
+			return new Media( this.locale );
+		}
 
 		url = url.trim();
 
-		for ( let { url: pattern, html: rendererFunction } of mediaProviders ) {
+		for ( let { url: pattern, html: contentRenderer } of this.providerDefinitions ) {
 			if ( !Array.isArray( pattern ) ) {
 				pattern = [ pattern ];
 			}
@@ -42,7 +91,7 @@ export class MediaRegistry {
 				const match = url.match( subPattern );
 
 				if ( match ) {
-					return new Media( this.editor.t, url, match, rendererFunction );
+					return new Media( this.locale, url, match, contentRenderer );
 				}
 			}
 		}
@@ -51,37 +100,67 @@ export class MediaRegistry {
 	}
 }
 
+/**
+ * Represents a media defined by the provider configuration.
+ *
+ * It can be rendered to the {@link module:engine/view/element~Element view element} and used in editing or data pipeline.
+ *
+ * @private
+ */
 class Media {
-	constructor( t, url, match, rendererFunction ) {
-		this.t = t;
+	constructor( locale, url, match, contentRenderer ) {
+		/**
+		 * The URL this Media instance represents.
+		 *
+		 * @member {String}
+		 */
 		this.url = url;
-		this.match = match;
-		this.rendererFunction = rendererFunction;
+
+		/**
+		 * Shorthand for {@link module:utils/locale~Locale#t}.
+		 *
+		 * Note: If {@link #locale} instance hasn't been passed to the view this method may not
+		 * be available.
+		 *
+		 * @see module:utils/locale~Locale#t
+		 * @method
+		 */
+		this._t = locale.t;
+
+		/**
+		 * The output of the `RegExp.match` which validated the {@link #url} of this media.
+		 *
+		 * @member {Object}
+		 */
+		this._match = match;
+
+		/**
+		 * The function returning the HTML string preview of this media.
+		 *
+		 * @member {Function}
+		 */
+		this._contentRenderer = contentRenderer;
 	}
 
+	/**
+	 * Returns view element representation of the media.
+	 *
+	 * @param {module:engine/view/writer~Writer} writer The view writer used to produce a view element.
+	 * @param {Object} options
+	 * @param {String} [options.renderContent]
+	 * @param {String} [options.useSemanticWrapper]
+	 * @param {String} [options.renderForEditingView]
+	 * @returns {module:engine/view/element~Element}
+	 */
 	getViewElement( writer, options ) {
-		let renderFunction;
-
-		if ( options.renderContent ) {
-			const mediaHtml = this._getContentHtml( options );
-
-			renderFunction = function( domDocument ) {
-				const domElement = this.toDomElement( domDocument );
-
-				domElement.innerHTML = mediaHtml;
-
-				return domElement;
-			};
-		}
-
 		const attributes = {};
 
-		if ( options.useSemanticWrapper || ( this.url && !this.rendererFunction && !options.renderForEditingView ) ) {
+		if ( options.useSemanticWrapper || ( this.url && !this._contentRenderer && !options.renderForEditingView ) ) {
 			if ( this.url ) {
 				attributes.url = this.url;
 			}
 
-			return writer.createEmptyElement( 'oembed', attributes, renderFunction );
+			return writer.createEmptyElement( 'oembed', attributes );
 		} else {
 			if ( this.url ) {
 				attributes[ 'data-oembed-url' ] = this.url;
@@ -91,13 +170,29 @@ class Media {
 				attributes.class = 'ck-media__wrapper';
 			}
 
-			return writer.createUIElement( 'div', attributes, renderFunction );
+			const mediaHtml = this._getContentHtml( options );
+
+			return writer.createUIElement( 'div', attributes, function( domDocument ) {
+				const domElement = this.toDomElement( domDocument );
+
+				domElement.innerHTML = mediaHtml;
+
+				return domElement;
+			} );
 		}
 	}
 
+	/**
+	 * Returns the HTML string of the media content preview.
+	 *
+	 * @param {module:engine/view/writer~Writer} writer The view writer used to produce a view element.
+	 * @param {Object} options
+	 * @param {String} [options.renderForEditingView]
+	 * @returns {String}
+	 */
 	_getContentHtml( options ) {
-		if ( this.rendererFunction ) {
-			return this.rendererFunction( this.match.pop() );
+		if ( this._contentRenderer ) {
+			return this._contentRenderer( this._match.pop() );
 		} else {
 			// The placeholder only makes sense for editing view and media which have URLs.
 			// Placeholder is never displayed in data and URL-less media have no content.
@@ -109,10 +204,15 @@ class Media {
 		}
 	}
 
+	/**
+	 * Returns the placeholder HTML when media has no content preview.
+	 *
+	 * @returns {String}
+	 */
 	_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' ) }">` +
+			`<a class="ck-media__placeholder__url" target="new" href="${ this.url }" title="${ this._t( 'Open media in new tab' ) }">` +
 				this.url +
 			'</a>' +
 		'</div>';

+ 29 - 8
packages/ckeditor5-media-embed/src/utils.js

@@ -28,20 +28,35 @@ export function toMediaWidget( viewElement, writer, label ) {
 	return toWidget( viewElement, writer, { label } );
 }
 
-// Creates a view element representing the media.
-//
-//		<figure class="media"></figure>
-//
-// @private
-// @param {module:engine/view/writer~Writer} writer
-// @returns {module:engine/view/containerelement~ContainerElement}
+/**
+ * Creates a view element representing the media. Either "semantic" one for the data pipeline:
+ *
+ *		<figure class="media">
+ *			<oembed url="foo"></div>
+ *		</figure>
+ *
+ * or "non-semantic" (for editing view pipeline):
+ *
+ *		<figure class="media">
+ *			<div data-oembed-url="foo">[ non-semantic media preview for "foo" ]</div>
+ *		</figure>
+ *
+ * @param {module:engine/view/writer~Writer} writer
+ * @param {module:media-embed/mediaregistry~MediaRegistry} mediaRegistry
+ * @param {String} url
+ * @param {Object} options
+ * @param {String} [options.renderContent]
+ * @param {String} [options.useSemanticWrapper]
+ * @param {String} [options.renderForEditingView]
+ * @returns {module:engine/view/containerelement~ContainerElement}
+ */
 export function createMediaFigureElement( writer, mediaRegistry, url, options ) {
 	const figure = writer.createContainerElement( 'figure', { class: 'media' } );
 
 	// TODO: This is a hack. Without it, the figure in the data pipeline will contain &nbsp; because
 	// its only child is the UIElement (wrapper).
 	//
-	// Note: The hack comes from widget utils; it makes the figure act like it's a widget.
+	// Note: The hack is a copy&paste from widget utils; it makes the figure act like it's a widget.
 	figure.getFillerOffset = getFillerOffset;
 
 	writer.insert( ViewPosition.createAt( figure ), mediaRegistry.getMediaViewElement( writer, url, options ) );
@@ -49,6 +64,12 @@ export function createMediaFigureElement( writer, mediaRegistry, url, options )
 	return figure;
 }
 
+/**
+ * Returns a selected media element in model, if any.
+ *
+ * @param {module:engine/model/selection~Selection} selection
+ * @returns {module:engine/model/element~Element|null}
+ */
 export function getSelectedMediaElement( selection ) {
 	const selectedElement = selection.getSelectedElement();