8
0
Просмотр исходного кода

Merge branch 'master' into i/6122-table-paste-spans

Maciej Gołaszewski 5 лет назад
Родитель
Сommit
b6e540fed0

+ 31 - 0
.github/workflows/merge-stable.yml

@@ -0,0 +1,31 @@
+name: Stable branch auto merge
+
+on:
+  push:
+    branches: [ stable ]
+
+jobs:
+  merge:
+    runs-on: ubuntu-latest
+    steps:
+      # First: merge
+      - uses: octokit/request-action@v2.x
+        id: merge_action
+        with:
+          route: POST /repos/:repository/merges
+          repository: ${{ github.repository }}
+          base: master
+          head: stable
+        env:
+          GITHUB_TOKEN: ${{ secrets.STABLE_MERGE_GITHUB_TOKEN }}
+      # Report errors if any
+      - uses: rtCamp/action-slack-notify@v2.0.2
+        id: error_message_slack
+        name: Slack notification
+        if: (steps.merge_action.outputs.status != 201) && (steps.merge_action.outputs.status != 204)
+        env:
+          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
+          SLACK_CHANNEL: "cke5-ci"
+          SLACK_ICON: https://github.com/ckeditor.png?size=48
+          SLACK_USERNAME: "stable auto merge action"
+          SLACK_MESSAGE: ${{ format('💥 Error, merge call returned code {0}, see {1} for a list of codes with explanation. 💥', steps.merge_action.outputs.status, 'https://developer.github.com/v3/repos/merging/#perform-a-merge' ) }}

+ 33 - 27
packages/ckeditor5-engine/tests/view/view/view.js

@@ -17,6 +17,7 @@ import CompositionObserver from '../../../src/view/observer/compositionobserver'
 import ViewRange from '../../../src/view/range';
 import ViewElement from '../../../src/view/element';
 import ViewContainerElement from '../../../src/view/containerelement';
+import ViewText from '../../../src/view/text';
 import ViewPosition from '../../../src/view/position';
 import ViewSelection from '../../../src/view/selection';
 import { StylesProcessor } from '../../../src/view/stylesmap';
@@ -516,7 +517,7 @@ describe( 'view', () => {
 	} );
 
 	describe( 'hasDomSelection', () => {
-		let domElement, domP, domSelection;
+		let domElement, domP, domText, viewP, viewText, domSelection;
 
 		// Focus tests are too unstable on Firefox to run them.
 		if ( env.isGecko ) {
@@ -528,10 +529,12 @@ describe( 'view', () => {
 
 			view.attachDomRoot( domRoot );
 
-			// It must be a container element to be rendered with the bogus <br> inside which ensures
-			// that the browser sees a selection position inside (empty <p> may not be selectable).
-			// May help resolving https://github.com/ckeditor/ckeditor5/issues/6655.
-			viewRoot._appendChild( new ViewContainerElement( viewDocument, 'p' ) );
+			viewP = new ViewContainerElement( viewDocument, 'p' );
+			viewText = new ViewText( viewDocument, 'ab' );
+
+			viewRoot._appendChild( viewP );
+			viewP._appendChild( viewText );
+
 			view.forceRender();
 
 			domElement = createElement( document, 'div', { contenteditable: 'true' } );
@@ -539,6 +542,7 @@ describe( 'view', () => {
 
 			domSelection = document.getSelection();
 			domP = domRoot.childNodes[ 0 ];
+			domText = domP.childNodes[ 0 ];
 		} );
 
 		afterEach( () => {
@@ -548,38 +552,40 @@ describe( 'view', () => {
 		it( 'should be true if selection is inside a DOM root element', done => {
 			domRoot.focus();
 
-			setTimeout( () => {
-				domSelection.collapse( domP, 0 );
+			// Both selection need to stay in sync to avoid inf selection loops
+			// as there's no editing pipeline that would ensure that the view selection
+			// gets changed based on the selectionChange event. See https://github.com/ckeditor/ckeditor5/issues/6655.
+			viewDocument.selection._setTo( viewText, 1 );
+			domSelection.collapse( domText, 1 );
 
-				// Wait for async selectionchange event on DOM document.
-				setTimeout( () => {
-					expect( view.hasDomSelection ).to.be.true;
+			// Wait for async selectionchange event on DOM document.
+			setTimeout( () => {
+				expect( view.hasDomSelection ).to.be.true;
 
-					done();
-				}, 10 );
-			}, 10 );
+				done();
+			}, 1000 );
 		} );
 
 		it( 'should be true if selection is inside a DOM root element - no focus', done => {
 			domRoot.focus();
 
+			// See the previous test.
+			viewDocument.selection._setTo( viewText, 1 );
+			domSelection.collapse( domText, 1 );
+
 			setTimeout( () => {
-				domSelection.collapse( domP, 0 );
+				// We could also do domRoot.blur() here but it's always better to know where the focus went.
+				// E.g. if it went to some <input>, the selection would disappear from the editor and the test would fail.
+				domRoot.blur();
 
+				// Wait for async selectionchange event on DOM document.
 				setTimeout( () => {
-					// We could also do domRoot.blur() here but it's always better to know where the focus went.
-					// E.g. if it went to some <input>, the selection would disappear from the editor and the test would fail.
-					domRoot.blur();
-
-					// Wait for async selectionchange event on DOM document.
-					setTimeout( () => {
-						expect( view.hasDomSelection ).to.be.true;
-						expect( view.document.isFocused ).to.be.false;
-
-						done();
-					}, 10 );
-				}, 10 );
-			}, 10 );
+					expect( view.hasDomSelection ).to.be.true;
+					expect( view.document.isFocused ).to.be.false;
+
+					done();
+				}, 100 );
+			}, 100 );
 		} );
 
 		it( 'should be false if selection is outside DOM root element', done => {

+ 2 - 1
packages/ckeditor5-media-embed/package.json

@@ -26,7 +26,8 @@
     "@ckeditor/ckeditor5-link": "^19.0.0",
     "@ckeditor/ckeditor5-list": "^19.0.0",
     "@ckeditor/ckeditor5-paragraph": "^19.0.0",
-    "@ckeditor/ckeditor5-typing": "^19.0.0"
+    "@ckeditor/ckeditor5-typing": "^19.0.0",
+    "@ckeditor/ckeditor5-table": "^19.0.0"
   },
   "engines": {
     "node": ">=8.0.0",

+ 7 - 0
packages/ckeditor5-media-embed/src/automediaembed.js

@@ -129,11 +129,15 @@ export default class AutoMediaEmbed extends Plugin {
 
 		// If the URL does not match to universal URL regexp, let's skip that.
 		if ( !url.match( URL_REGEXP ) ) {
+			urlRange.detach();
+
 			return;
 		}
 
 		// If the URL represents a media, let's use it.
 		if ( !mediaRegistry.hasMedia( url ) ) {
+			urlRange.detach();
+
 			return;
 		}
 
@@ -141,6 +145,8 @@ export default class AutoMediaEmbed extends Plugin {
 
 		// Do not anything if media element cannot be inserted at the current position (#47).
 		if ( !mediaEmbedCommand.isEnabled ) {
+			urlRange.detach();
+
 			return;
 		}
 
@@ -153,6 +159,7 @@ export default class AutoMediaEmbed extends Plugin {
 				this._timeoutId = null;
 
 				writer.remove( urlRange );
+				urlRange.detach();
 
 				let insertionPosition;
 

+ 34 - 0
packages/ckeditor5-media-embed/tests/automediaembed.js

@@ -17,6 +17,7 @@ import Undo from '@ckeditor/ckeditor5-undo/src/undo';
 import Typing from '@ckeditor/ckeditor5-typing/src/typing';
 import Image from '@ckeditor/ckeditor5-image/src/image';
 import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
+import Table from '@ckeditor/ckeditor5-table/src/table';
 import global from '@ckeditor/ckeditor5-utils/src/dom/global';
 import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
@@ -573,6 +574,39 @@ describe( 'AutoMediaEmbed - integration', () => {
 		} );
 	} );
 
+	it( 'should detach LiveRange', async () => {
+		const editor = await ClassicTestEditor.create( editorElement, {
+			plugins: [ MediaEmbed, AutoMediaEmbed, Link, List, Bold, Typing, Image, ImageCaption, Table ]
+		} );
+
+		setData(
+			editor.model,
+			'<table>' +
+				'<tableRow>' +
+					'[<tableCell><paragraph>foo</paragraph></tableCell>]' +
+					'[<tableCell><paragraph>bar</paragraph></tableCell>]' +
+				'</tableRow>' +
+			'</table>'
+		);
+
+		pasteHtml( editor, '<table><tr><td>one</td><td>two</td></tr></table>' );
+
+		expect( getData( editor.model, { withoutSelection: true } ) ).to.equal(
+			'<table>' +
+				'<tableRow>' +
+					'<tableCell><paragraph>one</paragraph></tableCell>' +
+					'<tableCell><paragraph>two</paragraph></tableCell>' +
+				'</tableRow>' +
+			'</table>'
+		);
+
+		expect( () => {
+			editor.setData( '' );
+		} ).not.to.throw();
+
+		await editor.destroy();
+	} );
+
 	function simulateTyping( text ) {
 		// While typing, every character is an atomic change.
 		text.split( '' ).forEach( character => {

+ 0 - 1
packages/ckeditor5-theme-lark/theme/ckeditor5-widget/widgettypearound.css

@@ -18,7 +18,6 @@
 	 * Styles of the type around buttons
 	 */
 	& .ck-widget__type-around__button {
-		cursor: pointer;
 		width: var(--ck-widget-type-around-button-size);
 		height: var(--ck-widget-type-around-button-size);
 		background: var(--ck-color-widget-type-around-button);