|
@@ -36,32 +36,42 @@ export function transformListItemLikeElementsIntoLists( documentFragment, styles
|
|
|
let currentList = null;
|
|
let currentList = null;
|
|
|
|
|
|
|
|
itemLikeElements.forEach( ( itemLikeElement, i ) => {
|
|
itemLikeElements.forEach( ( itemLikeElement, i ) => {
|
|
|
- const isDifferentList = isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement );
|
|
|
|
|
- const previousListItem = isDifferentList ? null : itemLikeElements[ i - 1 ];
|
|
|
|
|
- const indentationDifference = getIndentationDifference( previousListItem, itemLikeElement );
|
|
|
|
|
|
|
+ const isDifferentList = belongsToTheSameList( itemLikeElements[ i - 1 ], itemLikeElement );
|
|
|
|
|
+ const previousItemLikeElement = isDifferentList ? null : itemLikeElements[ i - 1 ];
|
|
|
|
|
+ const indentationDifference = getIndentationDifference( previousItemLikeElement, itemLikeElement );
|
|
|
|
|
|
|
|
|
|
+ // If item from a new list is encountered, reset "currentList" which points to a previous list element.
|
|
|
if ( isDifferentList ) {
|
|
if ( isDifferentList ) {
|
|
|
currentList = null;
|
|
currentList = null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if ( !currentList || isDifferentList || indentationDifference !== 0 ) {
|
|
|
|
|
|
|
+ if ( !currentList || indentationDifference !== 0 ) {
|
|
|
const listStyle = detectListStyle( itemLikeElement, stylesString );
|
|
const listStyle = detectListStyle( itemLikeElement, stylesString );
|
|
|
|
|
|
|
|
|
|
+ // Current list item has indentation level lower than the previous item.
|
|
|
|
|
+ // Find the list element with correct indentation level where current list item should be inserted.
|
|
|
if ( indentationDifference < 0 ) {
|
|
if ( indentationDifference < 0 ) {
|
|
|
currentList = findParentListAtLevel( currentList, indentationDifference );
|
|
currentList = findParentListAtLevel( currentList, indentationDifference );
|
|
|
|
|
|
|
|
|
|
+ // List might have been inserted with different list style (triggered by the item nested inside
|
|
|
|
|
+ // it with different list style) so it should be adjusted to the current list item style.
|
|
|
if ( !currentList.is( listStyle.type ) ) {
|
|
if ( !currentList.is( listStyle.type ) ) {
|
|
|
currentList = writer.rename( listStyle.type, currentList );
|
|
currentList = writer.rename( listStyle.type, currentList );
|
|
|
}
|
|
}
|
|
|
|
|
+ // Current list item has indentation level greater than the previous item. Insert correctly nested new list.
|
|
|
} else if ( indentationDifference > 0 ) {
|
|
} else if ( indentationDifference > 0 ) {
|
|
|
if ( currentList ) {
|
|
if ( currentList ) {
|
|
|
const lastListItem = currentList.getChild( currentList.childCount - 1 );
|
|
const lastListItem = currentList.getChild( currentList.childCount - 1 );
|
|
|
const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 );
|
|
const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 );
|
|
|
- currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference );
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Insert new list element on the end of the last list item in the current list. Since new list element
|
|
|
|
|
+ // will be inserted inside list item we need one level less of nesting ("indentationDifference - 1").
|
|
|
|
|
+ currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference - 1 );
|
|
|
} else {
|
|
} else {
|
|
|
// First item in the list has indentation.
|
|
// First item in the list has indentation.
|
|
|
- currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer, indentationDifference + 1 );
|
|
|
|
|
|
|
+ currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer, indentationDifference );
|
|
|
}
|
|
}
|
|
|
|
|
+ // Current list item (itemLikeElement) has indentation level the same as previous item.
|
|
|
} else {
|
|
} else {
|
|
|
currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer );
|
|
currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer );
|
|
|
}
|
|
}
|
|
@@ -180,10 +190,11 @@ function detectListStyle( listLikeItem, stylesString ) {
|
|
|
//
|
|
//
|
|
|
// @param {Object} listStyle List style object which determines the type of newly created list.
|
|
// @param {Object} listStyle List style object which determines the type of newly created list.
|
|
|
// Usually a result of `detectListStyle()` function.
|
|
// Usually a result of `detectListStyle()` function.
|
|
|
-// @param {module:engine/view/element~Element} element Element before which list is inserted.
|
|
|
|
|
|
|
+// @param {module:engine/view/element~Element} element Element after which list is inserted.
|
|
|
// @param {module:engine/view/upcastwriter~UpcastWriter} writer
|
|
// @param {module:engine/view/upcastwriter~UpcastWriter} writer
|
|
|
|
|
+// @param {Number} [wrap=0] How many times new empty list element should be wrapped into another list to created nested structure.
|
|
|
// @returns {module:engine/view/element~Element} Newly created list element.
|
|
// @returns {module:engine/view/element~Element} Newly created list element.
|
|
|
-function insertNewEmptyList( listStyle, element, writer, indentLevel = 0 ) {
|
|
|
|
|
|
|
+function insertNewEmptyList( listStyle, element, writer, wrap = 0 ) {
|
|
|
const parent = element.parent;
|
|
const parent = element.parent;
|
|
|
const list = writer.createElement( listStyle.type );
|
|
const list = writer.createElement( listStyle.type );
|
|
|
const position = parent.getChildIndex( element ) + 1;
|
|
const position = parent.getChildIndex( element ) + 1;
|
|
@@ -191,8 +202,8 @@ function insertNewEmptyList( listStyle, element, writer, indentLevel = 0 ) {
|
|
|
let currentList = list;
|
|
let currentList = list;
|
|
|
|
|
|
|
|
// Wrap new list into li's depending on indentation level.
|
|
// Wrap new list into li's depending on indentation level.
|
|
|
- if ( indentLevel > 1 ) {
|
|
|
|
|
- for ( let i = 1; i < indentLevel; i++ ) {
|
|
|
|
|
|
|
+ if ( wrap > 0 ) {
|
|
|
|
|
+ for ( let i = 0; i < wrap; i++ ) {
|
|
|
const parentList = new Element( listStyle.type );
|
|
const parentList = new Element( listStyle.type );
|
|
|
const parentLi = new Element( 'li' );
|
|
const parentLi = new Element( 'li' );
|
|
|
writer.appendChild( currentList, parentLi );
|
|
writer.appendChild( currentList, parentLi );
|
|
@@ -281,7 +292,7 @@ function removeBulletElement( element, writer ) {
|
|
|
// @param {Object} previousItem
|
|
// @param {Object} previousItem
|
|
|
// @param {Object} currentItem
|
|
// @param {Object} currentItem
|
|
|
// @returns {Boolean}
|
|
// @returns {Boolean}
|
|
|
-function isNewListNeeded( previousItem, currentItem ) {
|
|
|
|
|
|
|
+function belongsToTheSameList( previousItem, currentItem ) {
|
|
|
if ( !previousItem ) {
|
|
if ( !previousItem ) {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
@@ -304,7 +315,8 @@ function isList( element ) {
|
|
|
return element.is( 'ol' ) || element.is( 'ul' );
|
|
return element.is( 'ol' ) || element.is( 'ul' );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Calculates the indentation difference between two given list items.
|
|
|
|
|
|
|
+// Calculates the indentation difference between two given list items (based on indent attribute
|
|
|
|
|
+// extracted from `mso-list` style, see #getListItemData).
|
|
|
//
|
|
//
|
|
|
// @param {Object} previousItem
|
|
// @param {Object} previousItem
|
|
|
// @param {Object} currentItem
|
|
// @param {Object} currentItem
|
|
@@ -313,13 +325,13 @@ function getIndentationDifference( previousItem, currentItem ) {
|
|
|
return previousItem ? currentItem.indent - previousItem.indent : currentItem.indent - 1;
|
|
return previousItem ? currentItem.indent - previousItem.indent : currentItem.indent - 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Finds parent list of a given list with indentation level lower by a given value.
|
|
|
|
|
|
|
+// Finds parent list element (ul/ol) of a given list element with indentation level lower by a given value.
|
|
|
//
|
|
//
|
|
|
-// @param {module:engine/view/element~Element} currentList List element from which to start looking for a parent list.
|
|
|
|
|
-// @param {Number} levelDifference Level difference between lists.
|
|
|
|
|
-// @returns {module:engine/view/element~Element} Found list.
|
|
|
|
|
-function findParentListAtLevel( currentList, levelDifference ) {
|
|
|
|
|
- const ancestors = currentList.getAncestors( { parentFirst: true } );
|
|
|
|
|
|
|
+// @param {module:engine/view/element~Element} listElement List element from which to start looking for a parent list.
|
|
|
|
|
+// @param {Number} indentationDifference Indentation difference between lists.
|
|
|
|
|
+// @returns {module:engine/view/element~Element} Found list element with indentation level lower by a given value.
|
|
|
|
|
+function findParentListAtLevel( listElement, indentationDifference ) {
|
|
|
|
|
+ const ancestors = listElement.getAncestors( { parentFirst: true } );
|
|
|
|
|
|
|
|
let parentList = null;
|
|
let parentList = null;
|
|
|
let levelChange = 0;
|
|
let levelChange = 0;
|
|
@@ -329,7 +341,7 @@ function findParentListAtLevel( currentList, levelDifference ) {
|
|
|
levelChange--;
|
|
levelChange--;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if ( levelChange === levelDifference ) {
|
|
|
|
|
|
|
+ if ( levelChange === indentationDifference ) {
|
|
|
parentList = ancestor;
|
|
parentList = ancestor;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|