Przeglądaj źródła

Merge branch 'master' into t/ckeditor5/479

Aleksander Nowodzinski 7 lat temu
rodzic
commit
4d132d2b0c

+ 1 - 1
packages/ckeditor5-editor-inline/.eslintrc.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-editor-inline/LICENSE.md

@@ -2,7 +2,7 @@ Software License Agreement
 ==========================
 
 **Inline Editor** – https://github.com/ckeditor/ckeditor5-editor-inline <br>
-Copyright (c) 2003-2018, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
+Copyright (c) 2003-2019, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
 
 Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
 

+ 1 - 10
packages/ckeditor5-editor-inline/src/inlineeditor.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -17,7 +17,6 @@ import InlineEditorUIView from './inlineeditoruiview';
 import setDataInElement from '@ckeditor/ckeditor5-utils/src/dom/setdatainelement';
 import getDataFromElement from '@ckeditor/ckeditor5-utils/src/dom/getdatafromelement';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
-import log from '@ckeditor/ckeditor5-utils/src/log';
 import { isElement } from 'lodash-es';
 
 /**
@@ -77,14 +76,6 @@ export default class InlineEditor extends Editor {
 		attachToForm( this );
 	}
 
-	/**
-	 * @inheritDoc
-	 */
-	get element() {
-		log.warn( 'deprecated-editor-element: The editor#element is deprecated.' );
-		return this.ui.element;
-	}
-
 	/**
 	 * Destroys the editor instance, releasing all resources used by it.
 	 *

+ 11 - 10
packages/ckeditor5-editor-inline/src/inlineeditorui.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -75,11 +75,15 @@ export default class InlineEditorUI extends EditorUI {
 
 		// The editable UI element in DOM is available for sure only after the editor UI view has been rendered.
 		// But it can be available earlier if a DOM element has been passed to InlineEditor.create().
-		const editableElement = editable.editableElement;
+		const editableElement = editable.element;
+
+		// The editable UI and editing root should share the same name. Then name is used
+		// to recognize the particular editable, for instance in ARIA attributes.
+		editable.name = editingRoot.rootName;
 
 		// Register the editable UI view in the editor. A single editor instance can aggregate multiple
 		// editable areas (roots) but the inline editor has only one.
-		this._editableElements.push( editable );
+		this._editableElements.set( editable.name, editableElement );
 
 		// Let the global focus tracker know that the editable UI element is focusable and
 		// belongs to the editor. From now on, the focus tracker will sustain the editor focus
@@ -95,10 +99,6 @@ export default class InlineEditorUI extends EditorUI {
 		// toolbar gets focused.
 		editable.bind( 'isFocused' ).to( this.focusTracker );
 
-		// The editable UI and editing root should share the same name. Then name is used
-		// to recognize the particular editable, for instance in ARIA attributes.
-		editable.name = editingRoot.rootName;
-
 		// Bind the editable UI element to the editing view, making it an end– and entry–point
 		// of the editor's engine. This is where the engine meets the UI.
 		editingView.attachDomRoot( editableElement );
@@ -120,18 +120,19 @@ export default class InlineEditorUI extends EditorUI {
 		} );
 
 		this._initToolbar();
-		this.ready();
+		this.fire( 'ready' );
 	}
 
 	/**
 	 * @inheritDoc
 	 */
 	destroy() {
-		const view = this.view;
+		const view = this._view;
 		const editingView = this.editor.editing.view;
 
 		view.editable.disableEditingRootListeners();
 		editingView.detachDomRoot( view.editable.name );
+		view.destroy();
 
 		super.destroy();
 	}
@@ -144,7 +145,7 @@ export default class InlineEditorUI extends EditorUI {
 	_initToolbar() {
 		const editor = this.editor;
 		const view = this.view;
-		const editableElement = view.editable.editableElement;
+		const editableElement = view.editable.element;
 		const editingView = editor.editing.view;
 		const toolbar = view.toolbar;
 

+ 3 - 21
packages/ckeditor5-editor-inline/src/inlineeditoruiview.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -12,8 +12,6 @@ import InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/i
 import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';
 import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
 
-import log from '@ckeditor/ckeditor5-utils/src/log';
-
 /**
  * Inline editor UI view. Uses an nline editable and a floating toolbar.
  *
@@ -74,7 +72,7 @@ export default class InlineEditorUIView extends EditorUIView {
 
 		/**
 		 * A set of positioning functions used by the {@link #panel} to float around
-		 * {@link #editableElement}.
+		 * {@link #element editableElement}.
 		 *
 		 * The positioning functions are as follows:
 		 *
@@ -145,27 +143,11 @@ export default class InlineEditorUIView extends EditorUIView {
 		this.panel.content.add( this.toolbar );
 	}
 
-	/**
-	 * **Deprecated** since `v12.0.0`. The {@link module:ui/editableui/editableuiview~EditableUIView#editableElement
-	 * `EditableUIView editableElement`} could be used instead.
-	 *
-	 * The element which is the main editable element (usually the one with `contentEditable="true"`).
-	 *
-	 * @deprecated v12.0.0 The {@link module:ui/editableui/editableuiview~EditableUIView#editableElement
-	 * `EditableUIView editableElement`} could be used instead.
-	 * @readonly
-	 * @member {HTMLElement} #editableElement
-	 */
-	get editableElement() {
-		log.warn( 'deprecated-ui-view-editableElement: The InlineEditorUIView#editableElement property is deprecated.' );
-		return this.editable.editableElement;
-	}
-
 	/**
 	 * Determines the panel top position of the {@link #panel} in {@link #panelPositions}.
 	 *
 	 * @private
-	 * @param {module:utils/dom/rect~Rect} editableRect Rect of the {@link #editableElement}.
+	 * @param {module:utils/dom/rect~Rect} editableRect Rect of the {@link #element}.
 	 * @param {module:utils/dom/rect~Rect} panelRect Rect of the {@link #panel}.
 	 */
 	_getPanelPositionTop( editableRect, panelRect ) {

+ 18 - 33
packages/ckeditor5-editor-inline/tests/inlineeditor.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -21,6 +21,9 @@ import RootElement from '@ckeditor/ckeditor5-engine/src/model/rootelement';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 
+import ArticlePluginSet from '@ckeditor/ckeditor5-core/tests/_utils/articlepluginset';
+import { describeMemoryUsage, testMemoryUsage } from '@ckeditor/ckeditor5-core/tests/_utils/memory';
+
 describe( 'InlineEditor', () => {
 	let editor, editorElement;
 
@@ -112,14 +115,6 @@ describe( 'InlineEditor', () => {
 			} );
 		} );
 
-		it( 'editor.element should contain the whole editor (with UI) element', () => {
-			return InlineEditor.create( '<p>Hello world!</p>', {
-				plugins: [ Paragraph ]
-			} ).then( editor => {
-				expect( editor.editing.view.getDomRoot() ).to.equal( editor.element );
-			} );
-		} );
-
 		it( 'editor.ui.element should contain the whole editor (with UI) element', () => {
 			return InlineEditor.create( '<p>Hello world!</p>', {
 				plugins: [ Paragraph ]
@@ -204,7 +199,6 @@ describe( 'InlineEditor', () => {
 				init() {
 					this.editor.on( 'pluginsReady', spy );
 					this.editor.ui.on( 'ready', spy );
-					this.editor.on( 'uiReady', spy );
 					this.editor.on( 'dataReady', spy );
 					this.editor.on( 'ready', spy );
 				}
@@ -215,7 +209,7 @@ describe( 'InlineEditor', () => {
 					plugins: [ EventWatcher ]
 				} )
 				.then( newEditor => {
-					expect( fired ).to.deep.equal( [ 'pluginsReady', 'ready', 'uiReady', 'dataReady', 'ready' ] );
+					expect( fired ).to.deep.equal( [ 'pluginsReady', 'ready', 'dataReady', 'ready' ] );
 
 					editor = newEditor;
 				} );
@@ -243,28 +237,6 @@ describe( 'InlineEditor', () => {
 				} );
 		} );
 
-		it( 'fires uiReady once UI is ready', () => {
-			let isReady;
-
-			class EventWatcher extends Plugin {
-				init() {
-					this.editor.on( 'uiReady', () => {
-						isReady = this.editor.ui.view.isRendered;
-					} );
-				}
-			}
-
-			return InlineEditor
-				.create( editorElement, {
-					plugins: [ EventWatcher ]
-				} )
-				.then( newEditor => {
-					expect( isReady ).to.be.true;
-
-					editor = newEditor;
-				} );
-		} );
-
 		it( 'fires ready once UI is ready', () => {
 			let isReady;
 
@@ -328,4 +300,17 @@ describe( 'InlineEditor', () => {
 				.then( newEditor => newEditor.destroy() );
 		} );
 	} );
+
+	describeMemoryUsage( () => {
+		testMemoryUsage(
+			'should not grow on multiple create/destroy',
+			() => InlineEditor
+				.create( document.querySelector( '#mem-editor' ), {
+					plugins: [ ArticlePluginSet ],
+					toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote' ],
+					image: {
+						toolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ]
+					}
+				} ) );
+	} );
 } );

+ 12 - 7
packages/ckeditor5-editor-inline/tests/inlineeditorui.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -17,7 +17,7 @@ import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 import utils from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
 
 describe( 'InlineEditorUI', () => {
-	let editor, view, ui;
+	let editor, view, ui, viewElement;
 
 	testUtils.createSinonSandbox();
 
@@ -31,6 +31,7 @@ describe( 'InlineEditorUI', () => {
 
 				ui = editor.ui;
 				view = ui.view;
+				viewElement = view.editable.element;
 			} );
 	} );
 
@@ -93,7 +94,7 @@ describe( 'InlineEditorUI', () => {
 				editor.ui.fire( 'update' );
 				sinon.assert.calledOnce( spy );
 				sinon.assert.calledWithExactly( spy, {
-					target: view.editable.editableElement,
+					target: view.editable.element,
 					positions: sinon.match.array
 				} );
 			} );
@@ -199,6 +200,12 @@ describe( 'InlineEditorUI', () => {
 		} );
 	} );
 
+	describe( 'element()', () => {
+		it( 'returns correct element instance', () => {
+			expect( ui.element ).to.equal( viewElement );
+		} );
+	} );
+
 	describe( 'getEditableElement()', () => {
 		it( 'returns editable element (default)', () => {
 			expect( ui.getEditableElement() ).to.equal( view.editable.element );
@@ -208,8 +215,8 @@ describe( 'InlineEditorUI', () => {
 			expect( ui.getEditableElement( 'main' ) ).to.equal( view.editable.element );
 		} );
 
-		it( 'returns null if editable with the given name is absent', () => {
-			expect( ui.getEditableElement( 'absent' ) ).to.null;
+		it( 'returns undefined if editable with the given name is absent', () => {
+			expect( ui.getEditableElement( 'absent' ) ).to.be.undefined;
 		} );
 	} );
 } );
@@ -250,8 +257,6 @@ class VirtualInlineTestEditor extends VirtualTestEditor {
 				editor.initPlugins()
 					.then( () => {
 						editor.ui.init();
-						editor.ui.ready();
-						editor.fire( 'uiReady' );
 						editor.fire( 'dataReady' );
 						editor.fire( 'ready' );
 					} )

+ 1 - 12
packages/ckeditor5-editor-inline/tests/inlineeditoruiview.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 
@@ -10,7 +10,6 @@ import InlineEditableUIView from '@ckeditor/ckeditor5-ui/src/editableui/inline/i
 import Locale from '@ckeditor/ckeditor5-utils/src/locale';
 
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
-import log from '@ckeditor/ckeditor5-utils/src/log';
 
 describe( 'InlineEditorUIView', () => {
 	let locale, view;
@@ -122,16 +121,6 @@ describe( 'InlineEditorUIView', () => {
 		} );
 	} );
 
-	describe( 'editableElement', () => {
-		it( 'returns editable\'s view element', () => {
-			testUtils.sinon.stub( log, 'warn' ).callsFake( () => {} );
-
-			view.render();
-			expect( view.editableElement.getAttribute( 'contentEditable' ) ).to.equal( 'true' );
-			view.destroy();
-		} );
-	} );
-
 	describe( 'panelPositions', () => {
 		it( 'returns the positions in the right order', () => {
 			const positions = view.panelPositions;

+ 1 - 1
packages/ckeditor5-editor-inline/tests/manual/inlineeditor-data.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-editor-inline/tests/manual/inlineeditor.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 28 - 0
packages/ckeditor5-editor-inline/tests/manual/memory.html

@@ -0,0 +1,28 @@
+<p>
+	<button id="destroyEditors">Destroy editor</button>
+	<button id="initEditors">Init editors</button>
+</p>
+
+<div id="editor-1" contenteditable="true" class="custom-class" custom-attr="foo">
+	<h2>Editor 1</h2>
+	<p>This is an editor instance. And there's <a href="http://ckeditor.com">some link</a>.</p>
+</div>
+
+<div id="editor-2" class="custom-class" custom-attr="foo">
+	<h2>Editor 2</h2>
+	<p>This is another editor instance.</p>
+	<img src="sample.jpg" />
+	<p>
+		Unlike Editor 1 it doesn't have contenteditable=true initially.
+		Check if it's editable after initializing the editors and back to non-editable after destroying them.
+	</p>
+</div>
+
+<style>
+	.custom-class {
+		margin-top: 100px;
+		margin-left: 100px;
+		margin-bottom: 100px;
+		width: 450px;
+	}
+</style>

+ 80 - 0
packages/ckeditor5-editor-inline/tests/manual/memory.js

@@ -0,0 +1,80 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals console:false, document, window */
+
+import InlineEditor from '../../src/inlineeditor';
+import ArticlePluginSet from '@ckeditor/ckeditor5-core/tests/_utils/articlepluginset';
+
+window.editors = {};
+
+/*
+ * Memory-leak safe version of inline editor manual test does not:
+ * - define global variables (such as let editor; in main file scope)
+ * - console.log() objects
+ * - add event listeners with () => {} methods which reference other
+ */
+function initEditors() {
+	init( '#editor-1' );
+	init( '#editor-2' );
+
+	document.getElementById( 'destroyEditors' ).addEventListener( 'click', destroyEditors );
+
+	function init( selector ) {
+		InlineEditor
+			.create( document.querySelector( selector ), {
+				plugins: [ ArticlePluginSet ],
+				toolbar: {
+					items: [
+						'heading',
+						'|',
+						'bold',
+						'italic',
+						'link',
+						'bulletedList',
+						'numberedList',
+						'blockQuote',
+						'insertTable',
+						'mediaEmbed',
+						'undo',
+						'redo'
+					]
+				},
+				image: {
+					toolbar: [
+						'imageStyle:full',
+						'imageStyle:side',
+						'|',
+						'imageTextAlternative'
+					]
+				},
+				table: {
+					contentToolbar: [
+						'tableColumn',
+						'tableRow',
+						'mergeTableCells'
+					]
+				}
+			} )
+			.then( editor => {
+				window.editors[ selector ] = editor;
+			} )
+			.catch( err => {
+				console.error( err.stack );
+			} );
+	}
+
+	function destroyEditors() {
+		for ( const selector in window.editors ) {
+			window.editors[ selector ].destroy().then( () => {
+				window.editors[ selector ] = undefined;
+			} );
+		}
+
+		document.getElementById( 'destroyEditors' ).removeEventListener( 'click', destroyEditors );
+	}
+}
+
+document.getElementById( 'initEditors' ).addEventListener( 'click', initEditors );

+ 31 - 0
packages/ckeditor5-editor-inline/tests/manual/memory.md

@@ -0,0 +1,31 @@
+1. Open DevTools on Chrome.
+2. Go to Memory tab.
+3. Select "Heap snapshot" profiling type.
+4. Click "Collect Garbage" (trash icon) and "Clear all profiles" (don't go icon).
+5. Record heap snapshot ("Take heap snapshot" a record icon).
+6. Repeat multiple times:
+    - click "Init editor",
+    - wait to editor show up ,
+    - click "Destroy editor".
+7. Record heap snapshot again.
+8. Compare Snapshot 1 with Snapshot 2 and look for:
+    - "detached" - HTML Elements/DOM nodes
+    - "EventListener" - there should be only 1
+    - Any CKEditor5 classes instances like "Editor" or "LivePosition"
+
+## Notes:
+
+* Browser extensions might attach event listeners to the DOM so the safest way to run this test is by running Chrome from command line:
+
+    ```
+    google-chrome \
+        --enable-precise-memory-info \
+        --disable-extensions \
+        --disable-plugins \
+        --incognito \
+        http://localhost:8125 
+    ```
+
+    The above will run Chrome without extensions or plugins in incognito mode and open manual tests page.
+
+* Close any running Chrome instance beforehand because otherwise it will open a tab in currently opened Chrome (look for "Opening in existing browser session." in command line).

BIN
packages/ckeditor5-editor-inline/tests/manual/sample.jpg


+ 1 - 1
packages/ckeditor5-editor-inline/tests/manual/tickets/23/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */
 

+ 1 - 1
packages/ckeditor5-editor-inline/tests/manual/tickets/4/1.js

@@ -1,5 +1,5 @@
 /**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  * For licensing, see LICENSE.md.
  */