|
|
@@ -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>).
|