瀏覽代碼

Ensure exception marker is flat.

Maciej Gołaszewski 6 年之前
父節點
當前提交
96ef2b2fae

+ 24 - 14
packages/ckeditor5-restricted-editing/src/restrictededitingmodeediting.js

@@ -162,20 +162,7 @@ export default class RestrictedEditingModeEditing extends Plugin {
 
 		doc.registerPostFixer( extendMarkerOnTypingPostFixer( editor ) );
 		doc.registerPostFixer( resurrectCollapsedMarkerPostFixer( editor ) );
-
-		// Naive post-fixer.
-		model.markers.on( 'update:restrictedEditingException', ( evt, marker, oldRange, newRange ) => {
-			if ( !newRange.isFlat ) {
-				model.change( writer => {
-					writer.updateMarker( marker, {
-						range: writer.createRange(
-							writer.createPositionAt( newRange.end.parent, 0 ),
-							newRange.end
-						)
-					} );
-				} );
-			}
-		} );
+		model.markers.on( 'update:restrictedEditingException', ensureNewMarkerIsFlat( editor ) );
 
 		setupExceptionHighlighting( editor );
 	}
@@ -385,3 +372,26 @@ function isRangeInsideSingleMarker( editor, range ) {
 
 	return markerAtStart && markerAtEnd && markerAtEnd === markerAtStart;
 }
+
+// Checks if new marker range is flat. Non-flat ranges might appear during upcast conversion in nested structures, ie tables.
+function ensureNewMarkerIsFlat( editor ) {
+	const model = editor.model;
+
+	return ( evt, marker, oldRange, newRange ) => {
+		if ( !oldRange && !newRange.isFlat ) {
+			model.change( writer => {
+				const start = newRange.start;
+				const end = newRange.end;
+
+				const startIsHigherInTree = start.path.length > end.path.length;
+
+				const fixedStart = startIsHigherInTree ? newRange.start : writer.createPositionAt( end.parent, 0 );
+				const fixedEnd = startIsHigherInTree ? writer.createPositionAt( start.parent, 'end' ) : newRange.end;
+
+				writer.updateMarker( marker, {
+					range: writer.createRange( fixedStart, fixedEnd )
+				} );
+			} );
+		}
+	};
+}

+ 50 - 2
packages/ckeditor5-restricted-editing/tests/restrictededitingmodeediting.js

@@ -59,8 +59,8 @@ describe( 'RestrictedEditingModeEditing', () => {
 			model = editor.model;
 		} );
 
-		afterEach( () => {
-			return editor.destroy();
+		afterEach( async () => {
+			await editor.destroy();
 		} );
 
 		describe( 'upcast', () => {
@@ -208,6 +208,54 @@ describe( 'RestrictedEditingModeEditing', () => {
 				);
 			} );
 		} );
+
+		describe( 'flattening exception markers', () => {
+			it( 'should fix non-flat marker range (start is higher in tree)', () => {
+				setModelData( model, '<table><tableRow><tableCell><paragraph>foo bar baz</paragraph></tableCell></tableRow></table>' );
+				const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] );
+				const paragraph = model.document.getRoot().getNodeByPath( [ 0, 0, 0, 0 ] );
+
+				model.change( writer => {
+					writer.addMarker( `restrictedEditingException:${ 1 }`, {
+						range: writer.createRange(
+							writer.createPositionAt( paragraph, 0 ),
+							writer.createPositionAt( tableCell, 'end' )
+						),
+						usingOperation: true,
+						affectsData: true
+					} );
+				} );
+
+				const marker = model.markers.get( 'restrictedEditingException:1' );
+
+				expect( marker.getStart().parent ).to.equal( marker.getEnd().parent );
+				expect( marker.getStart().path ).to.deep.equal( [ 0, 0, 0, 0, 0 ] );
+				expect( marker.getEnd().path ).to.deep.equal( [ 0, 0, 0, 0, 11 ] );
+			} );
+
+			it( 'should fix non-flat marker range (end is higher in tree)', () => {
+				setModelData( model, '<table><tableRow><tableCell><paragraph>foo bar baz</paragraph></tableCell></tableRow></table>' );
+				const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] );
+				const paragraph = model.document.getRoot().getNodeByPath( [ 0, 0, 0, 0 ] );
+
+				model.change( writer => {
+					writer.addMarker( `restrictedEditingException:${ 1 }`, {
+						range: writer.createRange(
+							writer.createPositionAt( tableCell, 0 ),
+							writer.createPositionAt( paragraph, 'end' )
+						),
+						usingOperation: true,
+						affectsData: true
+					} );
+				} );
+
+				const marker = model.markers.get( 'restrictedEditingException:1' );
+
+				expect( marker.getStart().parent ).to.equal( marker.getEnd().parent );
+				expect( marker.getStart().path ).to.deep.equal( [ 0, 0, 0, 0, 0 ] );
+				expect( marker.getEnd().path ).to.deep.equal( [ 0, 0, 0, 0, 11 ] );
+			} );
+		} );
 	} );
 
 	describe( 'editing behavior', () => {