浏览代码

Added: Introduced paste fixer for list items that adjusts indent of pasted list items.

Szymon Cofalik 8 年之前
父节点
当前提交
0baf429739
共有 2 个文件被更改,包括 68 次插入1 次删除
  1. 64 1
      packages/ckeditor5-list/src/converters.js
  2. 4 0
      packages/ckeditor5-list/src/listengine.js

+ 64 - 1
packages/ckeditor5-list/src/converters.js

@@ -46,7 +46,10 @@ export function modelViewInsertion( evt, data, consumable, conversionApi ) {
 	const modelItem = data.item;
 	const viewItem = generateLiInUl( modelItem, conversionApi.mapper );
 
-	injectViewList( modelItem, viewItem, conversionApi.mapper );
+	// Providing kind of "default" insert position in case of converting incorrect model.
+	const insertPosition = conversionApi.mapper.toViewPosition( ModelPosition.createBefore( modelItem ) );
+
+	injectViewList( modelItem, viewItem, conversionApi.mapper, insertPosition );
 }
 
 /**
@@ -691,6 +694,66 @@ function _fixItemsType( changePosition, fixPrevious, document, batch ) {
 	} );
 }
 
+/**
+ * Fixer for pasted content that includes list items.
+ *
+ * Fixes indent of pasted list items so the pasted items match correctly to the context they are pasted into.
+ *
+ * Example:
+ *
+ *		<listItem type="bulleted" indent=0>A</listItem>
+ *		<listItem type="bulleted" indent=1>B^</listItem>
+ *		// At ^ paste:  <listItem type="bulleted" indent=4>X</listItem>
+ *		//              <listItem type="bulleted" indent=5>Y</listItem>
+ *		<listItem type="bulleted" indent=2>C</listItem>
+ *
+ * Should become:
+ *
+ *		<listItem type="bulleted" indent=0>A</listItem>
+ *		<listItem type="bulleted" indent=1>BX</listItem>
+ *		<listItem type="bulleted" indent=2>Y/listItem>
+ *		<listItem type="bulleted" indent=2>C</listItem>
+ *
+ * @param {module:engine/model/document~Document} document Document to observe.
+ * @returns {Function} Callback to be attached to {@link module:engine/model/document~Document#event:change document change event}.
+ */
+export function modelIndentPasteFixer( evt, data ) {
+	// Check whether inserted content starts from a `listItem`. If it does not, it means that there are some other
+	// elements before it and there is no need to fix indents, because even if we insert that content into a list,
+	// that list will be broken.
+	let item = data.content.getChild( 0 );
+
+	if ( item.is( 'listItem' ) ) {
+		// Get a reference list item. Inserted list items will be fixed according to that item.
+		const pos = data.selection.getFirstPosition();
+		let refItem = null;
+
+		if ( pos.parent.is( 'listItem' ) ) {
+			refItem = pos.parent;
+		} else if ( pos.nodeBefore && pos.nodeBefore.is( 'listItem' ) ) {
+			refItem = pos.nodeBefore;
+		}
+
+		// If there is `refItem` it means that we do insert list items into an existing list.
+		if ( refItem ) {
+			// First list item in `data` has indent equal to 0 (it is a first list item). It should have indent equal
+			// to the indent of reference item. We have to fix the first item and all of it's children and following siblings.
+			// Indent of all those items has to be adjusted to reference item.
+			const indentChange = refItem.getAttribute( 'indent' );
+
+			// Fix only if there is anything to fix.
+			if ( indentChange > 0 ) {
+				// Adjust indent of all "first" list items in inserted data.
+				while ( item && item.is( 'listItem' ) ) {
+					item.setAttribute( 'indent', item.getAttribute( 'indent' ) + indentChange );
+
+					item = item.nextSibling;
+				}
+			}
+		}
+	}
+}
+
 // Helper function that creates a `<ul><li></li></ul>` or (`<ol>`) structure out of given `modelItem` model `listItem` element.
 // Then, it binds created view list item (<li>) with model `listItem` element.
 // The function then returns created view list item (<li>).

+ 4 - 0
packages/ckeditor5-list/src/listengine.js

@@ -23,6 +23,7 @@ import {
 	modelViewSplitOnInsert,
 	modelViewChangeIndent,
 	modelChangePostFixer,
+	modelIndentPasteFixer,
 	viewModelConverter,
 	modelToViewPosition,
 	viewToModelPosition
@@ -109,6 +110,9 @@ export default class ListEngine extends Plugin {
 		data.viewToModel.on( 'element:li', cleanListItem, { priority: 'high' } );
 		data.viewToModel.on( 'element:li', viewModelConverter );
 
+		// Fix indentation of pasted items.
+		data.on( 'insertContent', modelIndentPasteFixer, { priority: 'high' } );
+
 		// Register commands for numbered and bulleted list.
 		editor.commands.set( 'numberedList', new ListCommand( editor, 'numbered' ) );
 		editor.commands.set( 'bulletedList', new ListCommand( editor, 'bulleted' ) );