Browse Source

Merge branch 'master' into ckeditor5-engine/t/643

Szymon Cofalik 9 years ago
parent
commit
4c762a183b

+ 3 - 4
packages/ckeditor5-list/.travis.yml

@@ -12,7 +12,6 @@ node_js:
 cache:
   - node_modules
 before_install:
-  - export CHROME_BIN=chromium-browser
   - export DISPLAY=:99.0
   - sh -e /etc/init.d/xvfb start
 install:
@@ -20,7 +19,7 @@ install:
   - npm install @ckeditor/ckeditor5-dev-tests
   - npm install codeclimate-test-reporter
 script:
-  - node_modules/.bin/ckeditor5-dev-tests --coverage --ignore-duplicates
+  - node_modules/.bin/ckeditor5-dev-tests-travis
 after_success:
-  - sed -i.backup 's/build\/\.automated-tests\/ckeditor5\/[^\/]*/src/g' build/.automated-tests/coverage/lcov.info
-  - node_modules/.bin/codeclimate-test-reporter < .build/coverage/lcov.info
+  - node_modules/.bin/codeclimate-test-reporter < build/.automated-tests/coverage/lcov.info
+

+ 2 - 3
packages/ckeditor5-list/README.md

@@ -4,9 +4,8 @@ CKEditor 5 Lists Feature
 [![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-list.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-list)
 [![Build Status](https://travis-ci.org/ckeditor/ckeditor5-list.svg?branch=master)](https://travis-ci.org/ckeditor/ckeditor5-list)
 [![Test Coverage](https://codeclimate.com/github/ckeditor/ckeditor5-list/badges/coverage.svg)](https://codeclimate.com/github/ckeditor/ckeditor5-list/coverage)
-[![Code Climate](https://codeclimate.com/github/ckeditor/ckeditor5-list/badges/gpa.svg)](https://codeclimate.com/github/ckeditor/ckeditor5-list)
-[![Dependency Status](https://david-dm.org/ckeditor/ckeditor5-list/status.svg)](https://david-dm.org/ckeditor/ckeditor5-list#info=dependencies)
-[![devDependency Status](https://david-dm.org/ckeditor/ckeditor5-list/dev-status.svg)](https://david-dm.org/ckeditor/ckeditor5-list#info=devDependencies)
+[![Dependency Status](https://david-dm.org/ckeditor/ckeditor5-list/status.svg)](https://david-dm.org/ckeditor/ckeditor5-list)
+[![devDependency Status](https://david-dm.org/ckeditor/ckeditor5-list/dev-status.svg)](https://david-dm.org/ckeditor/ckeditor5-list?type=dev)
 
 Introduces ordered and unordered lists feature to CKEditor 5. More information about the project can be found at the following URL: <https://github.com/ckeditor/ckeditor5-list>.
 

+ 1 - 1
packages/ckeditor5-list/package.json

@@ -1,6 +1,6 @@
 {
   "name": "ckeditor5-list",
-  "version": "0.2.0",
+  "version": "0.3.0",
   "description": "Introduces ordered and unordered lists feature to CKEditor 5.",
   "keywords": [],
   "dependencies": {

+ 156 - 154
packages/ckeditor5-list/src/converters.js

@@ -1,8 +1,10 @@
 /**
- * The list indent command. It is used by the {@link list.List list feature}.
- *
- * @memberOf list
- * @namespace list.converters
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module list/converters
  */
 
 import ViewListItemElement from './viewlistitemelement.js';
@@ -15,130 +17,16 @@ import ViewPosition from '../engine/view/position.js';
 import ViewRange from '../engine/view/range.js';
 import viewWriter from '../engine/view/writer.js';
 
-// Helper function that creates a `<ul><li></li></ul>` 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).
-function generateLiInUl( modelItem, mapper ) {
-	const listType = modelItem.getAttribute( 'type' ) == 'numbered' ? 'ol' : 'ul';
-	const viewItem = new ViewListItemElement();
-
-	const viewList = new ViewContainerElement( listType, null );
-	viewList.appendChildren( viewItem );
-
-	mapper.bindElements( modelItem, viewItem );
-
-	return viewItem;
-}
-
-// Helper function that seeks for a sibling of given `modelItem` that is a `listItem` element and meets given criteria.
-// `options` object may contain one or more of given values (by default they are `false`):
-// `options.getNext` - whether next or previous siblings should be checked (default = previous)
-// `options.checkAllSiblings` - whether all siblings or just the first one should be checked (default = only one),
-// `options.sameIndent` - whether sought sibling should have same indent (default = no),
-// `options.biggerIndent` - whether sought sibling should have bigger indent (default = no).
-// Either `options.sameIndent` or `options.biggerIndent` should be set to `true`.
-function getSiblingListItem( modelItem, options ) {
-	const direction = options.getNext ? 'nextSibling' : 'previousSibling';
-	const checkAllSiblings = !!options.checkAllSiblings;
-	const sameIndent = !!options.sameIndent;
-	const biggerIndent = !!options.biggerIndent;
-
-	const indent = modelItem.getAttribute( 'indent' );
-
-	let item = modelItem[ direction ];
-
-	while ( item && item.name == 'listItem' ) {
-		let itemIndent = item.getAttribute( 'indent' );
-
-		if ( sameIndent && indent == itemIndent || biggerIndent && indent < itemIndent ) {
-			return item;
-		} else if ( !checkAllSiblings || indent > itemIndent ) {
-			return null;
-		}
-
-		item = item[ direction ];
-	}
-
-	return null;
-}
-
-// Helper function that takes two parameters, that are expected to be view list elements, and merges them.
-// The merge happen only if both parameters are UL or OL elements.
-function mergeViewLists( firstList, secondList ) {
-	if ( firstList && secondList && ( firstList.name == 'ul' || firstList.name == 'ol' ) && firstList.name == secondList.name ) {
-		viewWriter.mergeContainers( ViewPosition.createAfter( firstList ) );
-	}
-}
-
-// Helper function that takes model list item element `modelItem`, corresponding view list item element `injectedItem`
-// that is not added to the view and is inside a view list element (`ul` or `ol`) and is that's list only child.
-// The list is inserted at correct position (element breaking may be needed) and then merged with it's siblings.
-// See comments below to better understand the algorithm.
-function injectViewList( modelItem, injectedItem, mapper ) {
-	const injectedList = injectedItem.parent;
-
-	// 1. Break after previous `listItem` if it has same or bigger indent.
-	const prevModelItem = getSiblingListItem( modelItem, { sameIndent: true, biggerIndent: true } );
-
-	if ( prevModelItem ) {
-		let viewItem = mapper.toViewElement( prevModelItem );
-		let viewPosition = ViewPosition.createAfter( viewItem );
-		viewWriter.breakContainer( viewPosition );
-	}
-
-	// 2. Break after closest previous `listItem` sibling with same indent.
-	const sameIndentModelItem = getSiblingListItem( modelItem, { sameIndent: true, checkAllSiblings: true } );
-	// Position between broken lists will be a place where new list is inserted.
-	// If there is nothing to break (`sameIndentModelItem` is falsy) it means that converted list item
-	// is (will be) the first list item.
-	let insertionPosition;
-
-	if ( sameIndentModelItem ) {
-		let viewItem = mapper.toViewElement( sameIndentModelItem );
-		let viewPosition = ViewPosition.createAfter( viewItem );
-		insertionPosition = viewWriter.breakContainer( viewPosition );
-	} else {
-		// If there is a list item before converted list item, it means that that list item has lower indent.
-		// In such case the created view list should be appended as a child of that item.
-		const prevSibling = modelItem.previousSibling;
-
-		if ( prevSibling && prevSibling.name == 'listItem' ) {
-			insertionPosition = ViewPosition.createAt( mapper.toViewElement( prevSibling ), 'end' );
-		} else {
-			// This is the very first list item, use position mapping to get correct insertion position.
-			insertionPosition = mapper.toViewPosition( ModelPosition.createBefore( modelItem ) );
-		}
-	}
-
-	// 3. Append new UL/OL in position after breaking in step 2.
-	viewWriter.insert( insertionPosition, injectedList );
-
-	// 4. If next sibling is list item with bigger indent, append it's UL/OL to new LI.
-	const nextModelItem = getSiblingListItem( modelItem, { getNext: true, biggerIndent: true } );
-	const nextViewItem = mapper.toViewElement( nextModelItem );
-
-	/* istanbul ignore if */ // Part of code connected with indenting that is not yet complete.
-	if ( nextViewItem ) {
-		let sourceRange = ViewRange.createOn( nextViewItem.parent );
-		let targetPosition = ViewPosition.createAt( injectedItem, 'end' );
-		viewWriter.move( sourceRange, targetPosition );
-	}
-
-	// 5. Merge new UL/OL with above and below items (ULs/OLs or LIs).
-	mergeViewLists( injectedList, injectedList.nextSibling );
-	mergeViewLists( injectedList.previousSibling, injectedList );
-}
-
 /**
  * Model to view converter for `listItem` model element insertion.
  *
  * It creates `<ul><li></li><ul>` (or `<ol>`) view structure out of `listItem` model element, inserts it at correct
  * position, and merges the list with surrounding lists (if able).
  *
- * @see engine.conversion.ModelConversionDispatcher#event:insert
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:insert
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Additional information about the change.
- * @param {engine.conversion.ModelConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface.
  */
 export function modelViewInsertion( evt, data, consumable, conversionApi ) {
@@ -165,10 +53,10 @@ export function modelViewInsertion( evt, data, consumable, conversionApi ) {
  * This change means that `<li>`s parent changes from `<ul>` to `<ol>` (or vice versa). This is accomplished by breaking
  * view elements, changing their name and merging them.
  *
- * @see engine.conversion.ModelConversionDispatcher#event:changeAttribute
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:changeAttribute
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Additional information about the change.
- * @param {engine.conversion.ModelConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface.
  */
 export function modelViewChangeType( evt, data, consumable, conversionApi ) {
@@ -197,10 +85,10 @@ export function modelViewChangeType( evt, data, consumable, conversionApi ) {
 /**
  * Model to view converter for `listItem` model element remove.
  *
- * @see engine.conversion.ModelConversionDispatcher#event:remove
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:remove
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Additional information about the change.
- * @param {engine.conversion.ModelConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface.
  */
 export function modelViewRemove( evt, data, consumable, conversionApi ) {
@@ -223,10 +111,10 @@ export function modelViewRemove( evt, data, consumable, conversionApi ) {
 /**
  * Model to view converter for `listItem` model element move.
  *
- * @see engine.conversion.ModelConversionDispatcher#event:move
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:move
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Additional information about the change.
- * @param {engine.conversion.ModelConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface.
  */
 export function modelViewMove( evt, data, consumable, conversionApi ) {
@@ -263,10 +151,10 @@ export function modelViewMove( evt, data, consumable, conversionApi ) {
 /**
  * Model to view converter for `indent` attribute change on `listItem` model element.
  *
- * @see engine.conversion.ModelConversionDispatcher#event:changeAttribute
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:changeAttribute
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Additional information about the change.
- * @param {engine.conversion.ModelConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface.
  */
 export function modelViewChangeIndent( evt, data, consumable, conversionApi ) {
@@ -296,7 +184,7 @@ export function modelViewChangeIndent( evt, data, consumable, conversionApi ) {
 }
 
 /**
- * A special model to view converter introduced by {@link list.List List feature}. This converter is fired for
+ * A special model to view converter introduced by {@link module:list/list~List List feature}. This converter is fired for
  * insert change of every model item, and should be fired before actual converter. The converter checks whether inserted
  * model item is a non-`listItem` element. If it is, and it is inserted inside a view list, the converter breaks the
  * list so the model element is inserted to the view parent element corresponding to its model parent element.
@@ -314,10 +202,10 @@ export function modelViewChangeIndent( evt, data, consumable, conversionApi ) {
  *		<paragraph>xxx</paragraph>       // Instead of this wrong view state:
  *		<listItem>bar</listItem>         <ul><li>foo</li><p>xxx</p><li>bar</li></ul>
  *
- * @see engine.conversion.ModelConversionDispatcher#event:insert
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:insert
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Additional information about the change.
- * @param {engine.conversion.ModelConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface.
  */
 export function modelViewSplitOnInsert( evt, data, consumable, conversionApi ) {
@@ -340,7 +228,7 @@ export function modelViewSplitOnInsert( evt, data, consumable, conversionApi ) {
 }
 
 /**
- * A special model to view converter introduced by {@link list.List List feature}. This converter takes care of
+ * A special model to view converter introduced by {@link module:list/list~List List feature}. This converter takes care of
  * merging view lists after something is removed or moved from near them.
  *
  * Example:
@@ -356,11 +244,11 @@ export function modelViewSplitOnInsert( evt, data, consumable, conversionApi ) {
  *		                                     <li>bar</li>
  *		                                 </ul>
  *
- * @see engine.conversion.ModelConversionDispatcher#event:remove
- * @see engine.conversion.ModelConversionDispatcher#event:move
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:remove
+ * @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:move
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Additional information about the change.
- * @param {engine.conversion.ModelConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface.
  */
 export function modelViewMergeAfter( evt, data, consumable, conversionApi ) {
@@ -381,10 +269,10 @@ export function modelViewMergeAfter( evt, data, consumable, conversionApi ) {
  * * checks `<li>`'s parent,
  * * passes `data.indent` value when `<li>`'s sub-items are converted.
  *
- * @see engine.conversion.ViewConversionDispatcher#event:element
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:element
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Object containing conversion input and a placeholder for conversion output and possibly other values.
- * @param {engine.conversion.ViewConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/viewconsumable~ViewConsumable} consumable Values to consume.
  * @param {Object} conversionApi Conversion interface to be used by callback.
  */
 export function viewModelConverter( evt, data, consumable, conversionApi ) {
@@ -439,10 +327,10 @@ export function viewModelConverter( evt, data, consumable, conversionApi ) {
  * This is mostly to clean white spaces from between `<li>` view elements inside the view list element, however also
  * incorrect data can be cleared if the view was incorrect.
  *
- * @see engine.conversion.ViewConversionDispatcher#event:element
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:element
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Object containing conversion input and a placeholder for conversion output and possibly other values.
- * @param {engine.conversion.ViewConsumable} consumable Values to consume.
+ * @param {module:engine/conversion/viewconsumable~ViewConsumable} consumable Values to consume.
  */
 export function cleanList( evt, data, consumable ) {
 	if ( consumable.test( data.input, { name: true } ) ) {
@@ -458,12 +346,12 @@ export function cleanList( evt, data, consumable ) {
 }
 
 /**
- * Callback for model position to view position mapping for {@link engine.conversion.Mapper}. The callback fixes positions
+ * Callback for model position to view position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes positions
  * between `listItem` elements, that would be incorrectly mapped because of how list items are represented in model
  * and view.
  *
- * @see engine.conversion.Mapper#event:modelToViewPosition
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/mapper~Mapper#event:modelToViewPosition
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Object containing additional data and placeholder for mapping result.
  */
 export function modelToViewPosition( evt, data ) {
@@ -475,12 +363,12 @@ export function modelToViewPosition( evt, data ) {
 }
 
 /**
- * Callback for view position to model position mapping for {@link engine.conversion.Mapper}. The callback fixes positions
+ * Callback for view position to model position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes positions
  * between `<li>` elements, that would be incorrectly mapped because of how list items are represented in model
  * and view.
  *
- * @see engine.conversion.Mapper#event:viewToModelPosition
- * @param {utils.EventInfo} evt Object containing information about the fired event.
+ * @see module:engine/conversion/mapper~Mapper#event:viewToModelPosition
+ * @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event.
  * @param {Object} data Object containing additional data and placeholder for mapping result.
  */
 export function viewToModelPosition( evt, data ) {
@@ -537,3 +425,117 @@ export function viewToModelPosition( evt, data ) {
 		evt.stop();
 	}
 }
+
+// Helper function that creates a `<ul><li></li></ul>` 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).
+function generateLiInUl( modelItem, mapper ) {
+	const listType = modelItem.getAttribute( 'type' ) == 'numbered' ? 'ol' : 'ul';
+	const viewItem = new ViewListItemElement();
+
+	const viewList = new ViewContainerElement( listType, null );
+	viewList.appendChildren( viewItem );
+
+	mapper.bindElements( modelItem, viewItem );
+
+	return viewItem;
+}
+
+// Helper function that seeks for a sibling of given `modelItem` that is a `listItem` element and meets given criteria.
+// `options` object may contain one or more of given values (by default they are `false`):
+// `options.getNext` - whether next or previous siblings should be checked (default = previous)
+// `options.checkAllSiblings` - whether all siblings or just the first one should be checked (default = only one),
+// `options.sameIndent` - whether sought sibling should have same indent (default = no),
+// `options.biggerIndent` - whether sought sibling should have bigger indent (default = no).
+// Either `options.sameIndent` or `options.biggerIndent` should be set to `true`.
+function getSiblingListItem( modelItem, options ) {
+	const direction = options.getNext ? 'nextSibling' : 'previousSibling';
+	const checkAllSiblings = !!options.checkAllSiblings;
+	const sameIndent = !!options.sameIndent;
+	const biggerIndent = !!options.biggerIndent;
+
+	const indent = modelItem.getAttribute( 'indent' );
+
+	let item = modelItem[ direction ];
+
+	while ( item && item.name == 'listItem' ) {
+		let itemIndent = item.getAttribute( 'indent' );
+
+		if ( sameIndent && indent == itemIndent || biggerIndent && indent < itemIndent ) {
+			return item;
+		} else if ( !checkAllSiblings || indent > itemIndent ) {
+			return null;
+		}
+
+		item = item[ direction ];
+	}
+
+	return null;
+}
+
+// Helper function that takes two parameters, that are expected to be view list elements, and merges them.
+// The merge happen only if both parameters are UL or OL elements.
+function mergeViewLists( firstList, secondList ) {
+	if ( firstList && secondList && ( firstList.name == 'ul' || firstList.name == 'ol' ) && firstList.name == secondList.name ) {
+		viewWriter.mergeContainers( ViewPosition.createAfter( firstList ) );
+	}
+}
+
+// Helper function that takes model list item element `modelItem`, corresponding view list item element `injectedItem`
+// that is not added to the view and is inside a view list element (`ul` or `ol`) and is that's list only child.
+// The list is inserted at correct position (element breaking may be needed) and then merged with it's siblings.
+// See comments below to better understand the algorithm.
+function injectViewList( modelItem, injectedItem, mapper ) {
+	const injectedList = injectedItem.parent;
+
+	// 1. Break after previous `listItem` if it has same or bigger indent.
+	const prevModelItem = getSiblingListItem( modelItem, { sameIndent: true, biggerIndent: true } );
+
+	if ( prevModelItem ) {
+		let viewItem = mapper.toViewElement( prevModelItem );
+		let viewPosition = ViewPosition.createAfter( viewItem );
+		viewWriter.breakContainer( viewPosition );
+	}
+
+	// 2. Break after closest previous `listItem` sibling with same indent.
+	const sameIndentModelItem = getSiblingListItem( modelItem, { sameIndent: true, checkAllSiblings: true } );
+	// Position between broken lists will be a place where new list is inserted.
+	// If there is nothing to break (`sameIndentModelItem` is falsy) it means that converted list item
+	// is (will be) the first list item.
+	let insertionPosition;
+
+	if ( sameIndentModelItem ) {
+		let viewItem = mapper.toViewElement( sameIndentModelItem );
+		let viewPosition = ViewPosition.createAfter( viewItem );
+		insertionPosition = viewWriter.breakContainer( viewPosition );
+	} else {
+		// If there is a list item before converted list item, it means that that list item has lower indent.
+		// In such case the created view list should be appended as a child of that item.
+		const prevSibling = modelItem.previousSibling;
+
+		if ( prevSibling && prevSibling.name == 'listItem' ) {
+			insertionPosition = ViewPosition.createAt( mapper.toViewElement( prevSibling ), 'end' );
+		} else {
+			// This is the very first list item, use position mapping to get correct insertion position.
+			insertionPosition = mapper.toViewPosition( ModelPosition.createBefore( modelItem ) );
+		}
+	}
+
+	// 3. Append new UL/OL in position after breaking in step 2.
+	viewWriter.insert( insertionPosition, injectedList );
+
+	// 4. If next sibling is list item with bigger indent, append it's UL/OL to new LI.
+	const nextModelItem = getSiblingListItem( modelItem, { getNext: true, biggerIndent: true } );
+	const nextViewItem = mapper.toViewElement( nextModelItem );
+
+	/* istanbul ignore if */ // Part of code connected with indenting that is not yet complete.
+	if ( nextViewItem ) {
+		let sourceRange = ViewRange.createOn( nextViewItem.parent );
+		let targetPosition = ViewPosition.createAt( injectedItem, 'end' );
+		viewWriter.move( sourceRange, targetPosition );
+	}
+
+	// 5. Merge new UL/OL with above and below items (ULs/OLs or LIs).
+	mergeViewLists( injectedList, injectedList.nextSibling );
+	mergeViewLists( injectedList.previousSibling, injectedList );
+}

+ 7 - 4
packages/ckeditor5-list/src/indentcommand.js

@@ -3,20 +3,23 @@
  * For licensing, see LICENSE.md.
  */
 
+/**
+ * @module list/indentcommand
+ */
+
 import Command from '../core/command/command.js';
 import { getClosestListItem } from './utils.js';
 
 /**
- * The list indent command. It is used by the {@link list.List list feature}.
+ * The list indent command. It is used by the {@link module:list/list~List list feature}.
  *
- * @memberOf list
  * @extends core.command.Command
  */
 export default class IndentCommand extends Command {
 	/**
 	 * Creates an instance of the command.
 	 *
-	 * @param {core.editor.Editor} editor Editor instance.
+	 * @param {module:core/editor/editor~Editor} editor Editor instance.
 	 * @param {'forward'|'backward'} indentDirection Direction of indent. If it is equal to `backward`, the command
 	 * will outdent a list item.
 	 */
@@ -28,7 +31,7 @@ export default class IndentCommand extends Command {
 		 *
 		 * @readonly
 		 * @private
-		 * @member {Number} list.IndentCommand#_indentBy
+		 * @member {Number}
 		 */
 		this._indentBy = indentDirection == 'forward' ? 1 : -1;
 

+ 6 - 3
packages/ckeditor5-list/src/list.js

@@ -3,6 +3,10 @@
  * For licensing, see LICENSE.md.
  */
 
+/**
+ * @module list/list
+ */
+
 import Plugin from '../core/plugin.js';
 import ListEngine from './listengine.js';
 import ButtonView from '../ui/button/buttonview.js';
@@ -12,10 +16,9 @@ import { parseKeystroke } from '../utils/keyboard.js';
  * The lists feature. It introduces the `numberedList` and `bulletedList` buttons which
  * allows to convert paragraphs to/from list items and indent/outdent them.
  *
- * See also {@link list.ListEngine}.
+ * See also {@link module:list/listengine~ListEngine}.
  *
- * @memberOf list
- * @extends core.Plugin
+ * @extends module:core/plugin~Plugin
  */
 export default class List extends Plugin {
 	/**

+ 10 - 7
packages/ckeditor5-list/src/listcommand.js

@@ -3,20 +3,23 @@
  * For licensing, see LICENSE.md.
  */
 
+/**
+ * @module list/listcommand
+ */
+
 import Command from '../core/command/command.js';
 import { getClosestListItem, getSelectedBlocks, getPositionBeforeBlock } from './utils.js';
 
 /**
- * The list command. It is used by the {@link list.List list feature}.
+ * The list command. It is used by the {@link module:list/list~List list feature}.
  *
- * @memberOf list
- * @extends core.command.Command
+ * @extends module:core/command/command~Command
  */
 export default class ListCommand extends Command {
 	/**
 	 * Creates an instance of the command.
 	 *
-	 * @param {core.editor.Editor} editor Editor instance.
+	 * @param {module:core/editor/editor~Editor} editor Editor instance.
 	 * @param {'numbered'|'bulleted'} type List type that will be handled by this command.
 	 */
 	constructor( editor, type ) {
@@ -26,7 +29,7 @@ export default class ListCommand extends Command {
 		 * The type of list created by the command.
 		 *
 		 * @readonly
-		 * @member {'numbered'|'bulleted'} list.ListCommand#type
+		 * @member {'numbered'|'bulleted'}
 		 */
 		this.type = type == 'bulleted' ? 'bulleted' : 'numbered';
 
@@ -34,7 +37,7 @@ export default class ListCommand extends Command {
 		 * Flag indicating whether the command is active, which means that selection starts in a list of the same type.
 		 *
 		 * @observable
-		 * @member {Boolean} list.ListCommand#value
+		 * @member {Boolean}
 		 */
 		this.set( 'value', false );
 
@@ -64,7 +67,7 @@ export default class ListCommand extends Command {
 	 *
 	 * @protected
 	 * @param {Object} [options] Options for executed command.
-	 * @param {engine.model.Batch} [options.batch] Batch to collect all the change steps.
+	 * @param {module:engine/model/batch~Batch} [options.batch] Batch to collect all the change steps.
 	 * New batch will be created if this option is not set.
 	 */
 	_doExecute( options = {} ) {

+ 5 - 2
packages/ckeditor5-list/src/listengine.js

@@ -3,6 +3,10 @@
  * For licensing, see LICENSE.md.
  */
 
+/**
+ * @module list/listengine
+ */
+
 import Plugin from '../core/plugin.js';
 import ListCommand from './listcommand.js';
 import IndentCommand from './indentcommand.js';
@@ -25,8 +29,7 @@ import {
  * The engine of the lists feature. It handles creating, editing and removing lists and list items.
  * It registers the `numberedList`, `bulletedList`, `indentList` and `outdentList` commands.
  *
- * @memberOf list
- * @extends core.Plugin
+ * @extends module:core/plugin~Plugin
  */
 export default class ListEngine extends Plugin {
 	/**

+ 11 - 14
packages/ckeditor5-list/src/utils.js

@@ -4,21 +4,19 @@
  */
 
 /**
- * Utilities used in modules from {@link list list} package.
+ * Utilities used in modules from {@link module:list/list list} package.
  *
- * @memberOf list
- * @namespace list.utils
+ * @module list/utils
  */
 
 import Position from '../engine/model/position.js';
 
 /**
- * For given {@link engine.model.Position position}, returns the closest ancestor of that position which is a
+ * For given {@link module:engine/model/position~Position position}, returns the closest ancestor of that position which is a
  * `listItem` element.
  *
- * @function list.utils.getClosestListItem
- * @param {engine.model.Position} position Position which ancestor should be check looking for `listItem` element.
- * @returns {engine.model.Element|null} Element with `listItem` name that is a closest ancestor of given `position`, or
+ * @param {module:engine/model/position~Position} position Position which ancestor should be check looking for `listItem` element.
+ * @returns {module:engine/model/element~Element|null} Element with `listItem` name that is a closest ancestor of given `position`, or
  * `null` if neither of `position` ancestors is a `listItem`.
  */
 export function getClosestListItem( position ) {
@@ -26,13 +24,12 @@ export function getClosestListItem( position ) {
 }
 
 /**
- * For given {@link engine.model.Selection selection} and {@link engine.model.Schema schema}, returns an array with
- * all elements that are in the selection and are extending `$block` schema item.
+ * For given {@link module:engine/model/selection~Selection selection} and {@link module:engine/model/schema~Schema schema},
+ * returns an array with all elements that are in the selection and are extending `$block` schema item.
  *
- * @function list.utils.getSelectedBlocks
- * @param {engine.model.Selection} selection Selection from which blocks will be taken.
- * @param {engine.model.Schema} schema Schema which will be used to check if a model element extends `$block`.
- * @returns {Array.<engine.model.Element>} All blocks from the selection.
+ * @param {module:engine/model/selection~Selection} selection Selection from which blocks will be taken.
+ * @param {module:engine/model/schema~Schema} schema Schema which will be used to check if a model element extends `$block`.
+ * @returns {Array.<module:engine/model/element~Element>} All blocks from the selection.
  */
 export function getSelectedBlocks( selection, schema ) {
 	let position = getPositionBeforeBlock( selection.getFirstPosition(), schema );
@@ -53,7 +50,7 @@ export function getSelectedBlocks( selection, schema ) {
 }
 
 /**
- * For given {@link engine.model.Position position}, finds a model element extending `$block` schema item which is
+ * For given {@link module:engine/model/position~Position position}, finds a model element extending `$block` schema item which is
  * closest element to that position. First node after the position is checked and then the position's ancestors. `null`
  * is returned if such element has not been found or found element is a root element.
  *

+ 10 - 5
packages/ckeditor5-list/src/viewlistitemelement.js

@@ -3,21 +3,26 @@
  * For licensing, see LICENSE.md.
  */
 
+/**
+ * @module list/viewlistitemelement
+ */
+
 import ViewContainerElement from '../engine/view/containerelement.js';
 
 /**
- * View element class representing list item (`<li>`). It extends {@link engine.view.ContainerElement} and overwrites
- * {@link list.ViewListItemElement#getFillerOffset evaluating whether filler offset} is needed.
+ * View element class representing list item (`<li>`). It extends {@link module:engine/view/containerelement~ContainerElement}
+ * and overwrites {@link module:list/viewlistitemelement~ViewListItemElement#getFillerOffset evaluating whether filler offset}
+ * is needed.
  *
- * @memberOf list
- * @extends engine.view.ContainerElement
+ * @extends module:engine/view/containerelement~ContainerElement
  */
 export default class ViewListItemElement extends ViewContainerElement {
 	/**
 	 * Creates `<li>` view item.
 	 *
 	 * @param {Object|Iterable} [attrs] Collection of attributes.
-	 * @param {engine.view.Node|Iterable.<engine.view.Node>} [children] List of nodes to be inserted into created element.
+	 * @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children] List of nodes to be inserted
+	 * into created element.
 	 */
 	constructor( attrs, children ) {
 		super( 'li', attrs, children );

+ 162 - 160
packages/ckeditor5-list/tests/indentcommand.js

@@ -10,197 +10,199 @@ import Range from 'ckeditor5/engine/model/range.js';
 import Position from 'ckeditor5/engine/model/position.js';
 import { setData, getData } from 'ckeditor5/engine/dev-utils/model.js';
 
-let editor, doc, root;
-
-beforeEach( () => {
-	editor = new Editor();
-	editor.document = new Document();
-
-	doc = editor.document;
-	root = doc.createRoot();
-
-	doc.schema.registerItem( 'listItem', '$block' );
-
-	doc.schema.allow( { name: '$block', inside: '$root' } );
-	doc.schema.allow( { name: 'listItem', attributes: [ 'type', 'indent' ], inside: '$root' } );
-
-	setData(
-		doc,
-		'<listItem indent="0" type="bulleted">a</listItem>' +
-		'<listItem indent="0" type="bulleted">b</listItem>' +
-		'<listItem indent="1" type="bulleted">c</listItem>' +
-		'<listItem indent="2" type="bulleted">d</listItem>' +
-		'<listItem indent="2" type="bulleted">e</listItem>' +
-		'<listItem indent="1" type="bulleted">f</listItem>' +
-		'<listItem indent="0" type="bulleted">g</listItem>'
-	);
-} );
-
 describe( 'IndentCommand', () => {
-	let command;
+	let editor, doc, root;
 
 	beforeEach( () => {
-		command = new IndentCommand( editor, 'forward' );
-	} );
-
-	afterEach( () => {
-		command.destroy();
+		editor = new Editor();
+		editor.document = new Document();
+
+		doc = editor.document;
+		root = doc.createRoot();
+
+		doc.schema.registerItem( 'listItem', '$block' );
+
+		doc.schema.allow( { name: '$block', inside: '$root' } );
+		doc.schema.allow( { name: 'listItem', attributes: [ 'type', 'indent' ], inside: '$root' } );
+
+		setData(
+			doc,
+			'<listItem indent="0" type="bulleted">a</listItem>' +
+			'<listItem indent="0" type="bulleted">b</listItem>' +
+			'<listItem indent="1" type="bulleted">c</listItem>' +
+			'<listItem indent="2" type="bulleted">d</listItem>' +
+			'<listItem indent="2" type="bulleted">e</listItem>' +
+			'<listItem indent="1" type="bulleted">f</listItem>' +
+			'<listItem indent="0" type="bulleted">g</listItem>'
+		);
 	} );
 
-	describe( 'isEnabled', () => {
-		it( 'should be true if selection starts in list item', () => {
-			doc.selection.collapse( root.getChild( 5 ) );
+	describe( 'IndentCommand', () => {
+		let command;
 
-			expect( command.isEnabled ).to.be.true;
+		beforeEach( () => {
+			command = new IndentCommand( editor, 'forward' );
 		} );
 
-		it( 'should be false if selection starts in first list item', () => {
-			doc.selection.collapse( root.getChild( 0 ) );
-
-			expect( command.isEnabled ).to.be.false;
+		afterEach( () => {
+			command.destroy();
 		} );
 
-		it( 'should be false if selection starts in a list item that has bigger indent than it\'s previous sibling', () => {
-			doc.selection.collapse( root.getChild( 2 ) );
-
-			expect( command.isEnabled ).to.be.false;
-		} );
-	} );
+		describe( 'isEnabled', () => {
+			it( 'should be true if selection starts in list item', () => {
+				doc.selection.collapse( root.getChild( 5 ) );
 
-	describe( '_doExecute', () => {
-		it( 'should increment indent attribute by 1', () => {
-			doc.selection.collapse( root.getChild( 5 ) );
-
-			command._doExecute();
-
-			expect( getData( doc, { withoutSelection: true } ) ).to.equal(
-				'<listItem indent="0" type="bulleted">a</listItem>' +
-				'<listItem indent="0" type="bulleted">b</listItem>' +
-				'<listItem indent="1" type="bulleted">c</listItem>' +
-				'<listItem indent="2" type="bulleted">d</listItem>' +
-				'<listItem indent="2" type="bulleted">e</listItem>' +
-				'<listItem indent="2" type="bulleted">f</listItem>' +
-				'<listItem indent="0" type="bulleted">g</listItem>'
-			);
-		} );
+				expect( command.isEnabled ).to.be.true;
+			} );
 
-		it( 'should increment indent of only first selected item when multiple items are selected', () => {
-			doc.selection.setRanges( [ new Range(
-				new Position( root.getChild( 4 ), [ 0 ] ),
-				new Position( root.getChild( 6 ), [ 0 ] )
-			) ] );
-
-			command._doExecute();
-
-			expect( getData( doc, { withoutSelection: true } ) ).to.equal(
-				'<listItem indent="0" type="bulleted">a</listItem>' +
-				'<listItem indent="0" type="bulleted">b</listItem>' +
-				'<listItem indent="1" type="bulleted">c</listItem>' +
-				'<listItem indent="2" type="bulleted">d</listItem>' +
-				'<listItem indent="3" type="bulleted">e</listItem>' +
-				'<listItem indent="1" type="bulleted">f</listItem>' +
-				'<listItem indent="0" type="bulleted">g</listItem>'
-			);
-		} );
+			it( 'should be false if selection starts in first list item', () => {
+				doc.selection.collapse( root.getChild( 0 ) );
 
-		it( 'should increment indent of all sub-items of indented item', () => {
-			doc.selection.collapse( root.getChild( 1 ) );
+				expect( command.isEnabled ).to.be.false;
+			} );
 
-			command._doExecute();
+			it( 'should be false if selection starts in a list item that has bigger indent than it\'s previous sibling', () => {
+				doc.selection.collapse( root.getChild( 2 ) );
 
-			expect( getData( doc, { withoutSelection: true } ) ).to.equal(
-				'<listItem indent="0" type="bulleted">a</listItem>' +
-				'<listItem indent="1" type="bulleted">b</listItem>' +
-				'<listItem indent="2" type="bulleted">c</listItem>' +
-				'<listItem indent="3" type="bulleted">d</listItem>' +
-				'<listItem indent="3" type="bulleted">e</listItem>' +
-				'<listItem indent="2" type="bulleted">f</listItem>' +
-				'<listItem indent="0" type="bulleted">g</listItem>'
-			);
+				expect( command.isEnabled ).to.be.false;
+			} );
 		} );
-	} );
-} );
 
-describe( 'IndentCommand - backward (outdent)', () => {
-	let command;
-
-	beforeEach( () => {
-		command = new IndentCommand( editor, 'backward' );
-	} );
-
-	afterEach( () => {
-		command.destroy();
+		describe( '_doExecute', () => {
+			it( 'should increment indent attribute by 1', () => {
+				doc.selection.collapse( root.getChild( 5 ) );
+
+				command._doExecute();
+
+				expect( getData( doc, { withoutSelection: true } ) ).to.equal(
+					'<listItem indent="0" type="bulleted">a</listItem>' +
+					'<listItem indent="0" type="bulleted">b</listItem>' +
+					'<listItem indent="1" type="bulleted">c</listItem>' +
+					'<listItem indent="2" type="bulleted">d</listItem>' +
+					'<listItem indent="2" type="bulleted">e</listItem>' +
+					'<listItem indent="2" type="bulleted">f</listItem>' +
+					'<listItem indent="0" type="bulleted">g</listItem>'
+				);
+			} );
+
+			it( 'should increment indent of only first selected item when multiple items are selected', () => {
+				doc.selection.setRanges( [ new Range(
+					new Position( root.getChild( 4 ), [ 0 ] ),
+					new Position( root.getChild( 6 ), [ 0 ] )
+				) ] );
+
+				command._doExecute();
+
+				expect( getData( doc, { withoutSelection: true } ) ).to.equal(
+					'<listItem indent="0" type="bulleted">a</listItem>' +
+					'<listItem indent="0" type="bulleted">b</listItem>' +
+					'<listItem indent="1" type="bulleted">c</listItem>' +
+					'<listItem indent="2" type="bulleted">d</listItem>' +
+					'<listItem indent="3" type="bulleted">e</listItem>' +
+					'<listItem indent="1" type="bulleted">f</listItem>' +
+					'<listItem indent="0" type="bulleted">g</listItem>'
+				);
+			} );
+
+			it( 'should increment indent of all sub-items of indented item', () => {
+				doc.selection.collapse( root.getChild( 1 ) );
+
+				command._doExecute();
+
+				expect( getData( doc, { withoutSelection: true } ) ).to.equal(
+					'<listItem indent="0" type="bulleted">a</listItem>' +
+					'<listItem indent="1" type="bulleted">b</listItem>' +
+					'<listItem indent="2" type="bulleted">c</listItem>' +
+					'<listItem indent="3" type="bulleted">d</listItem>' +
+					'<listItem indent="3" type="bulleted">e</listItem>' +
+					'<listItem indent="2" type="bulleted">f</listItem>' +
+					'<listItem indent="0" type="bulleted">g</listItem>'
+				);
+			} );
+		} );
 	} );
 
-	describe( 'isEnabled', () => {
-		it( 'should be true if selection starts in list item', () => {
-			doc.selection.collapse( root.getChild( 5 ) );
+	describe( 'IndentCommand - backward (outdent)', () => {
+		let command;
 
-			expect( command.isEnabled ).to.be.true;
+		beforeEach( () => {
+			command = new IndentCommand( editor, 'backward' );
 		} );
 
-		it( 'should be true if selection starts in first list item', () => {
-			// This is in contrary to forward indent command.
-			doc.selection.collapse( root.getChild( 0 ) );
-
-			expect( command.isEnabled ).to.be.true;
+		afterEach( () => {
+			command.destroy();
 		} );
 
-		it( 'should be true if selection starts in a list item that has bigger indent than it\'s previous sibling', () => {
-			// This is in contrary to forward indent command.
-			doc.selection.collapse( root.getChild( 2 ) );
+		describe( 'isEnabled', () => {
+			it( 'should be true if selection starts in list item', () => {
+				doc.selection.collapse( root.getChild( 5 ) );
 
-			expect( command.isEnabled ).to.be.true;
-		} );
-	} );
+				expect( command.isEnabled ).to.be.true;
+			} );
 
-	describe( '_doExecute', () => {
-		it( 'should decrement indent attribute by 1 (if it is bigger than 0)', () => {
-			doc.selection.collapse( root.getChild( 5 ) );
-
-			command._doExecute();
-
-			expect( getData( doc, { withoutSelection: true } ) ).to.equal(
-				'<listItem indent="0" type="bulleted">a</listItem>' +
-				'<listItem indent="0" type="bulleted">b</listItem>' +
-				'<listItem indent="1" type="bulleted">c</listItem>' +
-				'<listItem indent="2" type="bulleted">d</listItem>' +
-				'<listItem indent="2" type="bulleted">e</listItem>' +
-				'<listItem indent="0" type="bulleted">f</listItem>' +
-				'<listItem indent="0" type="bulleted">g</listItem>'
-			);
-		} );
+			it( 'should be true if selection starts in first list item', () => {
+				// This is in contrary to forward indent command.
+				doc.selection.collapse( root.getChild( 0 ) );
 
-		it( 'should rename listItem to paragraph (if indent is equal to 0)', () => {
-			doc.selection.collapse( root.getChild( 0 ) );
+				expect( command.isEnabled ).to.be.true;
+			} );
 
-			command._doExecute();
+			it( 'should be true if selection starts in a list item that has bigger indent than it\'s previous sibling', () => {
+				// This is in contrary to forward indent command.
+				doc.selection.collapse( root.getChild( 2 ) );
 
-			expect( getData( doc, { withoutSelection: true } ) ).to.equal(
-				'<paragraph>a</paragraph>' +
-				'<listItem indent="0" type="bulleted">b</listItem>' +
-				'<listItem indent="1" type="bulleted">c</listItem>' +
-				'<listItem indent="2" type="bulleted">d</listItem>' +
-				'<listItem indent="2" type="bulleted">e</listItem>' +
-				'<listItem indent="1" type="bulleted">f</listItem>' +
-				'<listItem indent="0" type="bulleted">g</listItem>'
-			);
+				expect( command.isEnabled ).to.be.true;
+			} );
 		} );
 
-		it( 'should decrement indent of all sub-items of outdented item', () => {
-			doc.selection.collapse( root.getChild( 1 ) );
-
-			command._doExecute();
-
-			expect( getData( doc, { withoutSelection: true } ) ).to.equal(
-				'<listItem indent="0" type="bulleted">a</listItem>' +
-				'<paragraph>b</paragraph>' +
-				'<listItem indent="0" type="bulleted">c</listItem>' +
-				'<listItem indent="1" type="bulleted">d</listItem>' +
-				'<listItem indent="1" type="bulleted">e</listItem>' +
-				'<listItem indent="0" type="bulleted">f</listItem>' +
-				'<listItem indent="0" type="bulleted">g</listItem>'
-			);
+		describe( '_doExecute', () => {
+			it( 'should decrement indent attribute by 1 (if it is bigger than 0)', () => {
+				doc.selection.collapse( root.getChild( 5 ) );
+
+				command._doExecute();
+
+				expect( getData( doc, { withoutSelection: true } ) ).to.equal(
+					'<listItem indent="0" type="bulleted">a</listItem>' +
+					'<listItem indent="0" type="bulleted">b</listItem>' +
+					'<listItem indent="1" type="bulleted">c</listItem>' +
+					'<listItem indent="2" type="bulleted">d</listItem>' +
+					'<listItem indent="2" type="bulleted">e</listItem>' +
+					'<listItem indent="0" type="bulleted">f</listItem>' +
+					'<listItem indent="0" type="bulleted">g</listItem>'
+				);
+			} );
+
+			it( 'should rename listItem to paragraph (if indent is equal to 0)', () => {
+				doc.selection.collapse( root.getChild( 0 ) );
+
+				command._doExecute();
+
+				expect( getData( doc, { withoutSelection: true } ) ).to.equal(
+					'<paragraph>a</paragraph>' +
+					'<listItem indent="0" type="bulleted">b</listItem>' +
+					'<listItem indent="1" type="bulleted">c</listItem>' +
+					'<listItem indent="2" type="bulleted">d</listItem>' +
+					'<listItem indent="2" type="bulleted">e</listItem>' +
+					'<listItem indent="1" type="bulleted">f</listItem>' +
+					'<listItem indent="0" type="bulleted">g</listItem>'
+				);
+			} );
+
+			it( 'should decrement indent of all sub-items of outdented item', () => {
+				doc.selection.collapse( root.getChild( 1 ) );
+
+				command._doExecute();
+
+				expect( getData( doc, { withoutSelection: true } ) ).to.equal(
+					'<listItem indent="0" type="bulleted">a</listItem>' +
+					'<paragraph>b</paragraph>' +
+					'<listItem indent="0" type="bulleted">c</listItem>' +
+					'<listItem indent="1" type="bulleted">d</listItem>' +
+					'<listItem indent="1" type="bulleted">e</listItem>' +
+					'<listItem indent="0" type="bulleted">f</listItem>' +
+					'<listItem indent="0" type="bulleted">g</listItem>'
+				);
+			} );
 		} );
 	} );
 } );

+ 289 - 286
packages/ckeditor5-list/tests/listcommand.js

@@ -10,323 +10,326 @@ import Range from 'ckeditor5/engine/model/range.js';
 import Position from 'ckeditor5/engine/model/position.js';
 import { setData, getData } from 'ckeditor5/engine/dev-utils/model.js';
 
-let editor, command, doc, root;
-
-beforeEach( () => {
-	editor = new Editor();
-	editor.document = new Document();
-
-	doc = editor.document;
-	root = doc.createRoot();
-
-	command = new ListCommand( editor, 'bulleted' );
-
-	doc.schema.registerItem( 'listItem', '$block' );
-	doc.schema.registerItem( 'paragraph', '$block' );
-	doc.schema.registerItem( 'widget', '$block' );
-
-	doc.schema.allow( { name: '$block', inside: '$root' } );
-	doc.schema.allow( { name: 'listItem', attributes: [ 'type', 'indent' ], inside: '$root' } );
-	doc.schema.disallow( { name: 'listItem', attributes: [ 'type', 'indent' ], inside: 'widget' } );
-
-	setData(
-		doc,
-		'<paragraph>foo</paragraph>' +
-		'<listItem type="bulleted" indent="0">bulleted</listItem>' +
-		'<listItem type="numbered" indent="0">numbered</listItem>' +
-		'<paragraph>bar</paragraph>' +
-		'<widget>' +
-			'<paragraph>xyz</paragraph>' +
-		'</widget>'
-	);
-
-	doc.selection.collapse( doc.getRoot().getChild( 0 ) );
-} );
-
-afterEach( () => {
-	command.destroy();
-} );
-
 describe( 'ListCommand', () => {
-	describe( 'constructor()', () => {
-		it( 'should create list command with given type and value set to false', () => {
-			expect( command.type ).to.equal( 'bulleted' );
-			expect( command.value ).to.be.false;
-
-			const numberedList = new ListCommand( editor, 'numbered' );
-			expect( numberedList.type ).to.equal( 'numbered' );
-		} );
+	let editor, command, doc, root;
+
+	beforeEach( () => {
+		editor = new Editor();
+		editor.document = new Document();
+
+		doc = editor.document;
+		root = doc.createRoot();
+
+		command = new ListCommand( editor, 'bulleted' );
+
+		doc.schema.registerItem( 'listItem', '$block' );
+		doc.schema.registerItem( 'paragraph', '$block' );
+		doc.schema.registerItem( 'widget', '$block' );
+
+		doc.schema.allow( { name: '$block', inside: '$root' } );
+		doc.schema.allow( { name: 'paragraph', inside: 'widget' } );
+		doc.schema.allow( { name: 'listItem', attributes: [ 'type', 'indent' ], inside: '$root' } );
+		doc.schema.disallow( { name: 'listItem', attributes: [ 'type', 'indent' ], inside: 'widget' } );
+
+		setData(
+			doc,
+			'<paragraph>foo</paragraph>' +
+			'<listItem type="bulleted" indent="0">bulleted</listItem>' +
+			'<listItem type="numbered" indent="0">numbered</listItem>' +
+			'<paragraph>bar</paragraph>' +
+			'<widget>' +
+				'<paragraph>xyz</paragraph>' +
+			'</widget>'
+		);
+
+		doc.selection.collapse( doc.getRoot().getChild( 0 ) );
 	} );
 
-	describe( 'value', () => {
-		it( 'should be false if first position in selection is not in a list item', () => {
-			doc.selection.collapse( doc.getRoot().getChild( 3 ) );
-			expect( command.value ).to.be.false;
-		} );
-
-		it( 'should be false if first position in selection is in a list item of different type', () => {
-			doc.selection.collapse( doc.getRoot().getChild( 2 ) );
-			expect( command.value ).to.be.false;
-		} );
-
-		it( 'should be true if first position in selection is in a list item of same type', () => {
-			doc.selection.collapse( doc.getRoot().getChild( 1 ) );
-			expect( command.value ).to.be.true;
-		} );
+	afterEach( () => {
+		command.destroy();
 	} );
 
-	describe( 'isEnabled', () => {
-		it( 'should be true if command value is true', () => {
-			command.value = true;
-			command.refreshState();
-
-			expect( command.isEnabled ).to.be.true;
+	describe( 'ListCommand', () => {
+		describe( 'constructor()', () => {
+			it( 'should create list command with given type and value set to false', () => {
+				expect( command.type ).to.equal( 'bulleted' );
+				expect( command.value ).to.be.false;
 
-			command.value = false;
-			doc.selection.collapse( doc.getRoot().getChild( 1 ) );
-
-			expect( command.value ).to.be.true;
-			expect( command.isEnabled ).to.be.true;
-		} );
-
-		it( 'should be true if selection first position is in a place where listItem can be inserted', () => {
-			doc.selection.collapse( doc.getRoot(), 2 );
-			expect( command.isEnabled ).to.be.true;
-
-			doc.selection.collapse( doc.getRoot().getChild( 0 ) );
-			expect( command.isEnabled ).to.be.true;
-
-			doc.selection.collapse( doc.getRoot().getChild( 2 ) );
-			expect( command.isEnabled ).to.be.true;
-		} );
-
-		it( 'should be false if selection first position is in a place where listItem cannot be inserted', () => {
-			doc.selection.collapse( doc.getRoot().getChild( 4 ) );
-			expect( command.isEnabled ).to.be.false;
+				const numberedList = new ListCommand( editor, 'numbered' );
+				expect( numberedList.type ).to.equal( 'numbered' );
+			} );
 		} );
-	} );
 
-	describe( '_doExecute', () => {
-		describe( 'custom options', () => {
-			it( 'should use provided batch', () => {
-				const batch = editor.document.batch();
-
-				expect( batch.deltas.length ).to.equal( 0 );
+		describe( 'value', () => {
+			it( 'should be false if first position in selection is not in a list item', () => {
+				doc.selection.collapse( doc.getRoot().getChild( 3 ) );
+				expect( command.value ).to.be.false;
+			} );
 
-				command._doExecute( { batch } );
+			it( 'should be false if first position in selection is in a list item of different type', () => {
+				doc.selection.collapse( doc.getRoot().getChild( 2 ) );
+				expect( command.value ).to.be.false;
+			} );
 
-				expect( batch.deltas.length ).to.be.above( 0 );
+			it( 'should be true if first position in selection is in a list item of same type', () => {
+				doc.selection.collapse( doc.getRoot().getChild( 1 ) );
+				expect( command.value ).to.be.true;
 			} );
 		} );
 
-		describe( 'collapsed selection', () => {
-			it( 'should rename closest block to listItem and set correct attributes', () => {
-				setData( doc, '<paragraph>fo[]o</paragraph>' );
+		describe( 'isEnabled', () => {
+			it( 'should be true if command value is true', () => {
+				command.value = true;
+				command.refreshState();
 
-				command._doExecute();
-
-				expect( getData( doc ) ).to.equal( '<listItem indent="0" type="bulleted">fo[]o</listItem>' );
-			} );
+				expect( command.isEnabled ).to.be.true;
 
-			it( 'should rename closest listItem to paragraph and remove attributes', () => {
-				setData( doc, '<listItem indent="0" type="bulleted">fo[]o</listItem>' );
+				command.value = false;
+				doc.selection.collapse( doc.getRoot().getChild( 1 ) );
 
-				command._doExecute();
-
-				expect( getData( doc ) ).to.equal( '<paragraph>fo[]o</paragraph>' );
+				expect( command.value ).to.be.true;
+				expect( command.isEnabled ).to.be.true;
 			} );
 
-			it( 'should change closest listItem\' type', () => {
-				setData( doc, '<listItem indent="0" type="numbered">fo[]o</listItem>' );
+			it( 'should be true if selection first position is in a place where listItem can be inserted', () => {
+				doc.selection.collapse( doc.getRoot(), 2 );
+				expect( command.isEnabled ).to.be.true;
 
-				command._doExecute();
+				doc.selection.collapse( doc.getRoot().getChild( 0 ) );
+				expect( command.isEnabled ).to.be.true;
 
-				expect( getData( doc ) ).to.equal( '<listItem indent="0" type="bulleted">fo[]o</listItem>' );
+				doc.selection.collapse( doc.getRoot().getChild( 2 ) );
+				expect( command.isEnabled ).to.be.true;
 			} );
 
-			it( 'should handle outdenting sub-items when list item is turned off', () => {
-				// Taken from docs.
-				//
-				// 1  * --------
-				// 2     * --------
-				// 3        * -------- <- this is turned off.
-				// 4           * -------- <- this has to become indent = 0, because it will be first item on a new list.
-				// 5              * -------- <- this should be still be a child of item above, so indent = 1.
-				// 6        * -------- <- this also has to become indent = 0, because it shouldn't end up as a child of any of items above.
-				// 7           * -------- <- this should be still be a child of item above, so indent = 1.
-				// 8     * -------- <- this has to become indent = 0.
-				// 9        * -------- <- this should still be a child of item above, so indent = 1.
-				// 10          * -------- <- this should still be a child of item above, so indent = 2.
-				// 11          * -------- <- this should still be at the same level as item above, so indent = 2.
-				// 12 * -------- <- this and all below are left unchanged.
-				// 13    * --------
-				// 14       * --------
-				//
-				// After turning off "3", the list becomes:
-				//
-				// 1  * --------
-				// 2     * --------
-				//
-				// 3  --------
-				//
-				// 4  * --------
-				// 5     * --------
-				// 6  * --------
-				// 7     * --------
-				// 8  * --------
-				// 9     * --------
-				// 10       * --------
-				// 11       * --------
-				// 12 * --------
-				// 13    * --------
-				// 14       * --------
-
-				setData(
-					doc,
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">[]---</listItem>' +
-					'<listItem indent="3" type="bulleted">---</listItem>' +
-					'<listItem indent="4" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>' +
-					'<listItem indent="3" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>' +
-					'<listItem indent="3" type="bulleted">---</listItem>' +
-					'<listItem indent="3" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>'
-				);
-
-				command._doExecute();
-
-				const expectedData =
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<paragraph>[]---</paragraph>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>';
-
-				expect( getData( doc ) ).to.equal( expectedData );
+			it( 'should be false if selection first position is in a place where listItem cannot be inserted', () => {
+				doc.selection.collapse( doc.getRoot().getChild( 4 ) );
+				expect( command.isEnabled ).to.be.false;
 			} );
 		} );
 
-		describe( 'non-collapsed selection', () => {
-			beforeEach( () => {
-				setData(
-					doc,
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<paragraph>---</paragraph>' +
-					'<paragraph>---</paragraph>' +
-					'<listItem indent="0" type="numbered">---</listItem>' +
-					'<listItem indent="0" type="numbered">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>'
-				);
-			} );
+		describe( '_doExecute', () => {
+			describe( 'custom options', () => {
+				it( 'should use provided batch', () => {
+					const batch = editor.document.batch();
 
-			it( 'should rename closest block to listItem and set correct attributes', () => {
-				// From first paragraph to second paragraph.
-				// Command value=false, we are turning on list items.
-				doc.selection.setRanges( [ new Range(
-					Position.createAt( root.getChild( 2 ) ),
-					Position.createAt( root.getChild( 3 ) )
-				) ] );
-
-				command._doExecute();
-
-				const expectedData =
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">[---</listItem>' +
-					'<listItem indent="0" type="bulleted">]---</listItem>' +
-					'<listItem indent="0" type="numbered">---</listItem>' +
-					'<listItem indent="0" type="numbered">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>';
-
-				expect( getData( doc ) ).to.equal( expectedData );
-			} );
+					expect( batch.deltas.length ).to.equal( 0 );
+
+					command._doExecute( { batch } );
 
-			it( 'should rename closest listItem to paragraph and remove attributes', () => {
-				// From second bullet list item to first numbered list item.
-				// Command value=true, we are turning off list items.
-				doc.selection.setRanges( [ new Range(
-					Position.createAt( root.getChild( 1 ) ),
-					Position.createAt( root.getChild( 4 ) )
-				) ] );
-
-				// Convert paragraphs, leave numbered list items.
-				command._doExecute();
-
-				const expectedData =
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<paragraph>[---</paragraph>' +
-					'<paragraph>---</paragraph>' +
-					'<paragraph>---</paragraph>' +
-					'<paragraph>]---</paragraph>' +
-					'<listItem indent="0" type="numbered">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>';
-
-				expect( getData( doc ) ).to.equal( expectedData );
+					expect( batch.deltas.length ).to.be.above( 0 );
+				} );
 			} );
 
-			it( 'should change closest listItem\'s type', () => {
-				// From first numbered lsit item to third bulleted list item.
-				doc.selection.setRanges( [ new Range(
-					Position.createAt( root.getChild( 4 ) ),
-					Position.createAt( root.getChild( 6 ) )
-				) ] );
-
-				// Convert paragraphs, leave numbered list items.
-				command._doExecute();
-
-				const expectedData =
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<paragraph>---</paragraph>' +
-					'<paragraph>---</paragraph>' +
-					'<listItem indent="0" type="bulleted">[---</listItem>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">]---</listItem>' +
-					'<listItem indent="2" type="bulleted">---</listItem>';
-
-				expect( getData( doc ) ).to.equal( expectedData );
+			describe( 'collapsed selection', () => {
+				it( 'should rename closest block to listItem and set correct attributes', () => {
+					setData( doc, '<paragraph>fo[]o</paragraph>' );
+
+					command._doExecute();
+
+					expect( getData( doc ) ).to.equal( '<listItem indent="0" type="bulleted">fo[]o</listItem>' );
+				} );
+
+				it( 'should rename closest listItem to paragraph and remove attributes', () => {
+					setData( doc, '<listItem indent="0" type="bulleted">fo[]o</listItem>' );
+
+					command._doExecute();
+
+					expect( getData( doc ) ).to.equal( '<paragraph>fo[]o</paragraph>' );
+				} );
+
+				it( 'should change closest listItem\' type', () => {
+					setData( doc, '<listItem indent="0" type="numbered">fo[]o</listItem>' );
+
+					command._doExecute();
+
+					expect( getData( doc ) ).to.equal( '<listItem indent="0" type="bulleted">fo[]o</listItem>' );
+				} );
+
+				it( 'should handle outdenting sub-items when list item is turned off', () => {
+					// Taken from docs.
+					//
+					// 1  * --------
+					// 2     * --------
+					// 3        * -------- <- this is turned off.
+					// 4           * -------- <- this has to become indent = 0, because it will be first item on a new list.
+					// 5              * -------- <- this should be still be a child of item above, so indent = 1.
+					// 6        * -------- <- this also has to become indent = 0, because it shouldn't end up as a child of any of items above.
+					// 7           * -------- <- this should be still be a child of item above, so indent = 1.
+					// 8     * -------- <- this has to become indent = 0.
+					// 9        * -------- <- this should still be a child of item above, so indent = 1.
+					// 10          * -------- <- this should still be a child of item above, so indent = 2.
+					// 11          * -------- <- this should still be at the same level as item above, so indent = 2.
+					// 12 * -------- <- this and all below are left unchanged.
+					// 13    * --------
+					// 14       * --------
+					//
+					// After turning off "3", the list becomes:
+					//
+					// 1  * --------
+					// 2     * --------
+					//
+					// 3  --------
+					//
+					// 4  * --------
+					// 5     * --------
+					// 6  * --------
+					// 7     * --------
+					// 8  * --------
+					// 9     * --------
+					// 10       * --------
+					// 11       * --------
+					// 12 * --------
+					// 13    * --------
+					// 14       * --------
+
+					setData(
+						doc,
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">[]---</listItem>' +
+						'<listItem indent="3" type="bulleted">---</listItem>' +
+						'<listItem indent="4" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>' +
+						'<listItem indent="3" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>' +
+						'<listItem indent="3" type="bulleted">---</listItem>' +
+						'<listItem indent="3" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>'
+					);
+
+					command._doExecute();
+
+					const expectedData =
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<paragraph>[]---</paragraph>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>';
+
+					expect( getData( doc ) ).to.equal( expectedData );
+				} );
 			} );
 
-			it( 'should handle outdenting sub-items when list item is turned off', () => {
-				// From first numbered lsit item to third bulleted list item.
-				doc.selection.setRanges( [ new Range(
-					Position.createAt( root.getChild( 1 ) ),
-					Position.createAt( root.getChild( 5 ) )
-				) ] );
-
-				// Convert paragraphs, leave numbered list items.
-				command._doExecute();
-
-				const expectedData =
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<paragraph>[---</paragraph>' +
-					'<paragraph>---</paragraph>' +
-					'<paragraph>---</paragraph>' +
-					'<paragraph>---</paragraph>' +
-					'<paragraph>]---</paragraph>' +
-					'<listItem indent="0" type="bulleted">---</listItem>' +
-					'<listItem indent="1" type="bulleted">---</listItem>';
-
-				expect( getData( doc ) ).to.equal( expectedData );
+			describe( 'non-collapsed selection', () => {
+				beforeEach( () => {
+					setData(
+						doc,
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<paragraph>---</paragraph>' +
+						'<paragraph>---</paragraph>' +
+						'<listItem indent="0" type="numbered">---</listItem>' +
+						'<listItem indent="0" type="numbered">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>'
+					);
+				} );
+
+				it( 'should rename closest block to listItem and set correct attributes', () => {
+					// From first paragraph to second paragraph.
+					// Command value=false, we are turning on list items.
+					doc.selection.setRanges( [ new Range(
+						Position.createAt( root.getChild( 2 ) ),
+						Position.createAt( root.getChild( 3 ) )
+					) ] );
+
+					command._doExecute();
+
+					const expectedData =
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">[---</listItem>' +
+						'<listItem indent="0" type="bulleted">]---</listItem>' +
+						'<listItem indent="0" type="numbered">---</listItem>' +
+						'<listItem indent="0" type="numbered">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>';
+
+					expect( getData( doc ) ).to.equal( expectedData );
+				} );
+
+				it( 'should rename closest listItem to paragraph and remove attributes', () => {
+					// From second bullet list item to first numbered list item.
+					// Command value=true, we are turning off list items.
+					doc.selection.setRanges( [ new Range(
+						Position.createAt( root.getChild( 1 ) ),
+						Position.createAt( root.getChild( 4 ) )
+					) ] );
+
+					// Convert paragraphs, leave numbered list items.
+					command._doExecute();
+
+					const expectedData =
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<paragraph>[---</paragraph>' +
+						'<paragraph>---</paragraph>' +
+						'<paragraph>---</paragraph>' +
+						'<paragraph>]---</paragraph>' +
+						'<listItem indent="0" type="numbered">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>';
+
+					expect( getData( doc ) ).to.equal( expectedData );
+				} );
+
+				it( 'should change closest listItem\'s type', () => {
+					// From first numbered lsit item to third bulleted list item.
+					doc.selection.setRanges( [ new Range(
+						Position.createAt( root.getChild( 4 ) ),
+						Position.createAt( root.getChild( 6 ) )
+					) ] );
+
+					// Convert paragraphs, leave numbered list items.
+					command._doExecute();
+
+					const expectedData =
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<paragraph>---</paragraph>' +
+						'<paragraph>---</paragraph>' +
+						'<listItem indent="0" type="bulleted">[---</listItem>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">]---</listItem>' +
+						'<listItem indent="2" type="bulleted">---</listItem>';
+
+					expect( getData( doc ) ).to.equal( expectedData );
+				} );
+
+				it( 'should handle outdenting sub-items when list item is turned off', () => {
+					// From first numbered lsit item to third bulleted list item.
+					doc.selection.setRanges( [ new Range(
+						Position.createAt( root.getChild( 1 ) ),
+						Position.createAt( root.getChild( 5 ) )
+					) ] );
+
+					// Convert paragraphs, leave numbered list items.
+					command._doExecute();
+
+					const expectedData =
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<paragraph>[---</paragraph>' +
+						'<paragraph>---</paragraph>' +
+						'<paragraph>---</paragraph>' +
+						'<paragraph>---</paragraph>' +
+						'<paragraph>]---</paragraph>' +
+						'<listItem indent="0" type="bulleted">---</listItem>' +
+						'<listItem indent="1" type="bulleted">---</listItem>';
+
+					expect( getData( doc ) ).to.equal( expectedData );
+				} );
 			} );
 		} );
 	} );

+ 0 - 2
packages/ckeditor5-list/tests/manual/list.md

@@ -1,5 +1,3 @@
-@bender-ui: collapsed
-
 ### Loading
 
 1. The data should be loaded with: