{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-list/src/listcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/listui.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/list.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/theme/icons/bulletedlist.svg","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/checktodolistcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/todolistconverters.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/todolistediting.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/todolistui.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/todolist.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/theme/icons/todolist.svg","webpack:///./node_modules/@ckeditor/ckeditor5-list/theme/icons/numberedlist.svg","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/indentcommand.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/converters.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/listediting.js","webpack:///./node_modules/@ckeditor/ckeditor5-list/src/utils.js"],"names":["ListCommand","editor","type","this","value","_getValue","isEnabled","_checkEnabled","model","document","blocks","Array","from","selection","getSelectedBlocks","filter","block","checkCanBecomeListItem","schema","turnOff","change","writer","next","length","nextSibling","currentIndent","Number","POSITIVE_INFINITY","changes","name","getAttribute","indent","newIndent","push","element","listIndent","reverse","item","setAttribute","lowestIndent","is","_fixType","rename","setAttributes","listType","fire","listItem","first","firstBlock","Command","isBackward","startingItem","checkChild","parent","isObject","ListUI","t","createUIComponent","numberedListIcon","bulletedListIcon","Plugin","List","ListEditing","module","exports","attributeKey","CheckTodoListCommand","_selectedElements","on","refresh","priority","_getSelectedItems","every","selectionRange","getFirstRange","startElement","start","elements","checkAttribute","getItems","includes","options","undefined","forceValue","removeAttribute","modelViewInsertion","onCheckboxChecked","evt","data","conversionApi","consumable","test","modelItem","consume","viewWriter","viewItem","generateLiInUl","isChecked","checkmarkElement","createCheckmarkElement","span","createContainerElement","class","addClass","insert","createPositionAt","createPositionAfter","injectViewList","dataModelViewInsertion","label","checkbox","createEmptyElement","disabled","dataViewModelCheckmarkInsertion","modelCursor","isAtStart","hasAttribute","modelRange","createRange","modelViewChangeType","onCheckedChange","view","mapper","toViewElement","labelElement","findLabel","attributeNewValue","itemRange","createRangeIn","nestedList","findNestedList","descriptionStart","positionAfterUiElements","descriptionEnd","createPositionBefore","end","descriptionRange","move","attributeOldValue","descriptionSpan","findDescription","removeClass","remove","modelViewChangeChecked","oldCheckmarkElement","getChild","newCheckmarkElement","mapModelToViewPosition","modelPosition","viewLi","descSpan","viewPosition","findPositionIn","offset","onChange","uiElement","createUIElement","contenteditable","domDocument","createElement","addEventListener","domElement","toDomElement","appendChild","range","hasClass","ITEM_TOGGLE_KEYSTROKE","parseKeystroke","TodoListEditing","editing","extend","allowAttributes","addAttributeCheck","context","attributeName","last","commands","add","checkTodoListCommand","downcastDispatcher","upcastDispatcher","_handleCheckmarkChange","listenTo","jumpOverCheckmarkOnSideArrowKeyPress","locale","getCode","execute","stop","listItemsToFix","Set","args","operation","oldName","position","nodeAfter","key","oldValue","registerPostFixer","hasChanged","clear","previousSelectionRanges","getRanges","setSelection","eventInfo","domEventData","direction","getLocalizedArrowKeyCodeDirection","keyCode","contentLanguageDirection","isCollapsed","getFirstPosition","newRange","getNearestSelectionRange","preventDefault","stopPropagation","TodoListUI","todoListIcon","TodoList","IndentCommand","indentDirection","_indentBy","doc","itemsToChange","lastItem","prev","previousSibling","modelViewRemove","toViewPosition","viewStart","getLastMatchingPosition","breakContainer","viewList","viewListPrev","removeRange","createRangeOn","removed","mergeViewLists","toModelElement","hoistNestedLists","child","unbindViewElement","listName","modelViewMergeAfterChangeType","getChildren","modelViewChangeIndent","modelViewSplitOnInsert","lists","removeStart","removeEnd","isEqual","i","previousList","nodeBefore","insertedRange","mergePos","modelViewMergeAfter","viewItemPrev","viewItemNext","viewModelConverter","getIndent","safeInsert","nextPosition","viewToModelListItemChildrenConverter","updateConversionResult","cleanList","children","isWrongElement","isList","_remove","cleanListItem","childCount","foundList","firstNode","_data","replace","modelToViewPosition","isPhantom","topmostViewList","getAncestors","find","walker","getWalker","previousPosition","viewToModelPosition","viewPos","viewParent","isAtEnd","modelNode","modelLength","getModelLength","getShiftedBy","modelChangePostFixer","differ","getChanges","itemToListHead","Map","applied","entry","_addListToFix","e","innerItem","posAfter","values","listHead","_fixListIndents","_fixListTypes","previousNode","has","set","maxIndent","fixBy","itemIndent","typesStack","slice","modelIndentPasteFixer","content","selectable","createSelection","pos","refItem","indentChange","_setAttribute","listItemModel","viewChildren","convertItem","result","convertedChild","wasSplit","findNextListItem","startPosition","treeWalker","TreeWalker","nextIndent","modelRemoveStartPosition","viewRemoveStartPosition","viewRemovedItem","insertPosition","prevModelItem","getSiblingListItem","sameIndent","smallerIndent","foo","prevIndent","prevViewList","viewElement","register","inheritAllFrom","registerViewToModelLength","getViewListItemLength","conversion","for","dispatcher","viewDocument","positionParent","getLastPosition","isEmpty","firstPosition","previousIsAListItem","priorities","high","getCommandExecuter","commandName","cancel","command","get","keystrokes","outdent","registerChildCommand","createViewListItemElement","getFillerOffset","getListItemFillerOffset","bindElements","injectedItem","injectedList","prevItem","mappedViewAncestor","findMappedViewAncestor","prevView","walkerBoundaries","ignoreElementEnd","breakPosition","targetPosition","nextViewList","lastSubChild","modelChild","firstList","secondList","mergeContainers","icon","ui","componentFactory","buttonView","ButtonView","tooltip","isToggleable","bind","to","focus","node","hasOnlyLists","call"],"mappings":"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","file":"js/chunk-vendors~e4fa5284.47413141.js","sourcesContent":["/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/listcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { first } from 'ckeditor5/src/utils';\n\n/**\n * The list command. It is used by the {@link module:list/list~List list feature}.\n *\n * @extends module:core/command~Command\n */\nexport default class ListCommand extends Command {\n\t/**\n\t * Creates an instance of the command.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {'numbered'|'bulleted'} type List type that will be handled by this command.\n\t */\n\tconstructor( editor, type ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * The type of the list created by the command.\n\t\t *\n\t\t * @readonly\n\t\t * @member {'numbered'|'bulleted'|'todo'}\n\t\t */\n\t\tthis.type = type;\n\n\t\t/**\n\t\t * A flag indicating whether the command is active, which means that the selection starts in a list of the same type.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #value\n\t\t */\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.value = this._getValue();\n\t\tthis.isEnabled = this._checkEnabled();\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @protected\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst document = model.document;\n\t\tconst blocks = Array.from( document.selection.getSelectedBlocks() )\n\t\t\t.filter( block => checkCanBecomeListItem( block, model.schema ) );\n\n\t\t// Whether we are turning off some items.\n\t\tconst turnOff = this.value === true;\n\t\t// If we are turning off items, we are going to rename them to paragraphs.\n\n\t\tmodel.change( writer => {\n\t\t\t// If part of a list got turned off, we need to handle (outdent) all of sub-items of the last turned-off item.\n\t\t\t// To be sure that model is all the time in a good state, we first fix items below turned-off item.\n\t\t\tif ( turnOff ) {\n\t\t\t\t// Start from the model item that is just after the last turned-off item.\n\t\t\t\tlet next = blocks[ blocks.length - 1 ].nextSibling;\n\t\t\t\tlet currentIndent = Number.POSITIVE_INFINITY;\n\t\t\t\tlet changes = [];\n\n\t\t\t\t// Correct indent of all items after the last turned off item.\n\t\t\t\t// Rules that should be followed:\n\t\t\t\t// 1. All direct sub-items of turned-off item should become indent 0, because the first item after it\n\t\t\t\t// will be the first item of a new list. Other items are at the same level, so should have same 0 index.\n\t\t\t\t// 2. All items with indent lower than indent of turned-off item should become indent 0, because they\n\t\t\t\t// should not end up as a child of any of list items that they were not children of before.\n\t\t\t\t// 3. All other items should have their indent changed relatively to it's parent.\n\t\t\t\t//\n\t\t\t\t// For example:\n\t\t\t\t// 1 * --------\n\t\t\t\t// 2 * --------\n\t\t\t\t// 3 * --------\t\t\t<-- this is turned off.\n\t\t\t\t// 4 * --------\t\t<-- this has to become indent = 0, because it will be first item on a new list.\n\t\t\t\t// 5 * --------\t<-- this should be still be a child of item above, so indent = 1.\n\t\t\t\t// 6 * --------\t\t\t<-- this has to become indent = 0, because it should not be a child of any of items above.\n\t\t\t\t// 7 * --------\t\t<-- this should be still be a child of item above, so indent = 1.\n\t\t\t\t// 8 * --------\t\t\t\t<-- this has to become indent = 0.\n\t\t\t\t// 9 * --------\t\t\t<-- this should still be a child of item above, so indent = 1.\n\t\t\t\t// 10 * --------\t\t<-- this should still be a child of item above, so indent = 2.\n\t\t\t\t// 11 * --------\t\t<-- this should still be at the same level as item above, so indent = 2.\n\t\t\t\t// 12 * --------\t\t\t\t<-- this and all below are left unchanged.\n\t\t\t\t// 13 * --------\n\t\t\t\t// 14 * --------\n\t\t\t\t//\n\t\t\t\t// After turning off 3 the list becomes:\n\t\t\t\t//\n\t\t\t\t// 1 * --------\n\t\t\t\t// 2 * --------\n\t\t\t\t//\n\t\t\t\t// 3 --------\n\t\t\t\t//\n\t\t\t\t// 4 * --------\n\t\t\t\t// 5 * --------\n\t\t\t\t// 6 * --------\n\t\t\t\t// 7 * --------\n\t\t\t\t// 8 * --------\n\t\t\t\t// 9 * --------\n\t\t\t\t// 10 * --------\n\t\t\t\t// 11 * --------\n\t\t\t\t// 12 * --------\n\t\t\t\t// 13 * --------\n\t\t\t\t// 14 * --------\n\t\t\t\t//\n\t\t\t\t// Thanks to this algorithm no lists are mismatched and no items get unexpected children/parent, while\n\t\t\t\t// those parent-child connection which are possible to maintain are still maintained. It's worth noting\n\t\t\t\t// that this is the same effect that we would be get by multiple use of outdent command. However doing\n\t\t\t\t// it like this is much more efficient because it's less operation (less memory usage, easier OT) and\n\t\t\t\t// less conversion (faster).\n\t\t\t\twhile ( next && next.name == 'listItem' && next.getAttribute( 'listIndent' ) !== 0 ) {\n\t\t\t\t\t// Check each next list item, as long as its indent is bigger than 0.\n\t\t\t\t\t// If the indent is 0 we are not going to change anything anyway.\n\t\t\t\t\tconst indent = next.getAttribute( 'listIndent' );\n\n\t\t\t\t\t// We check if that's item indent is lower as current relative indent.\n\t\t\t\t\tif ( indent < currentIndent ) {\n\t\t\t\t\t\t// If it is, current relative indent becomes that indent.\n\t\t\t\t\t\tcurrentIndent = indent;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fix indent relatively to current relative indent.\n\t\t\t\t\t// Note, that if we just changed the current relative indent, the newIndent will be equal to 0.\n\t\t\t\t\tconst newIndent = indent - currentIndent;\n\n\t\t\t\t\t// Save the entry in changes array. We do not apply it at the moment, because we will need to\n\t\t\t\t\t// reverse the changes so the last item is changed first.\n\t\t\t\t\t// This is to keep model in correct state all the time.\n\t\t\t\t\tchanges.push( { element: next, listIndent: newIndent } );\n\n\t\t\t\t\t// Find next item.\n\t\t\t\t\tnext = next.nextSibling;\n\t\t\t\t}\n\n\t\t\t\tchanges = changes.reverse();\n\n\t\t\t\tfor ( const item of changes ) {\n\t\t\t\t\twriter.setAttribute( 'listIndent', item.listIndent, item.element );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we are turning on, we might change some items that are already `listItem`s but with different type.\n\t\t\t// Changing one nested list item to other type should also trigger changing all its siblings so the\n\t\t\t// whole nested list is of the same type.\n\t\t\t// Example (assume changing to numbered list):\n\t\t\t// * ------\t\t\t\t<-- do not fix, top level item\n\t\t\t// * ------\t\t\t<-- fix, because latter list item of this item's list is changed\n\t\t\t// * ------\t\t<-- do not fix, item is not affected (different list)\n\t\t\t// * ------\t\t\t<-- fix, because latter list item of this item's list is changed\n\t\t\t// * ------\t\t<-- fix, because latter list item of this item's list is changed\n\t\t\t// * ---[--\t\t<-- already in selection\n\t\t\t// * ------\t\t\t<-- already in selection\n\t\t\t// * ------\t\t\t<-- already in selection\n\t\t\t// * ------\t\t\t\t<-- already in selection, but does not cause other list items to change because is top-level\n\t\t\t// * ---]--\t\t\t<-- already in selection\n\t\t\t// * ------\t\t\t<-- fix, because preceding list item of this item's list is changed\n\t\t\t// * ------\t\t<-- do not fix, item is not affected (different list)\n\t\t\t// * ------\t\t\t\t<-- do not fix, top level item\n\t\t\tif ( !turnOff ) {\n\t\t\t\t// Find lowest indent among selected items. This will be indicator what is the indent of\n\t\t\t\t// top-most list affected by the command.\n\t\t\t\tlet lowestIndent = Number.POSITIVE_INFINITY;\n\n\t\t\t\tfor ( const item of blocks ) {\n\t\t\t\t\tif ( item.is( 'element', 'listItem' ) && item.getAttribute( 'listIndent' ) < lowestIndent ) {\n\t\t\t\t\t\tlowestIndent = item.getAttribute( 'listIndent' );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Do not execute the fix for top-level lists.\n\t\t\t\tlowestIndent = lowestIndent === 0 ? 1 : lowestIndent;\n\n\t\t\t\t// Fix types of list items that are \"before\" the selected blocks.\n\t\t\t\t_fixType( blocks, true, lowestIndent );\n\n\t\t\t\t// Fix types of list items that are \"after\" the selected blocks.\n\t\t\t\t_fixType( blocks, false, lowestIndent );\n\t\t\t}\n\n\t\t\t// Phew! Now it will be easier :).\n\t\t\t// For each block element that was in the selection, we will either: turn it to list item,\n\t\t\t// turn it to paragraph, or change it's type. Or leave it as it is.\n\t\t\t// Do it in reverse as there might be multiple blocks (same as with changing indents).\n\t\t\tfor ( const element of blocks.reverse() ) {\n\t\t\t\tif ( turnOff && element.name == 'listItem' ) {\n\t\t\t\t\t// We are turning off and the element is a `listItem` - it should be converted to `paragraph`.\n\t\t\t\t\t// List item specific attributes are removed by post fixer.\n\t\t\t\t\twriter.rename( element, 'paragraph' );\n\t\t\t\t} else if ( !turnOff && element.name != 'listItem' ) {\n\t\t\t\t\t// We are turning on and the element is not a `listItem` - it should be converted to `listItem`.\n\t\t\t\t\t// The order of operations is important to keep model in correct state.\n\t\t\t\t\twriter.setAttributes( { listType: this.type, listIndent: 0 }, element );\n\t\t\t\t\twriter.rename( element, 'listItem' );\n\t\t\t\t} else if ( !turnOff && element.name == 'listItem' && element.getAttribute( 'listType' ) != this.type ) {\n\t\t\t\t\t// We are turning on and the element is a `listItem` but has different type - change it's type and\n\t\t\t\t\t// type of it's all siblings that have same indent.\n\t\t\t\t\twriter.setAttribute( 'listType', this.type, element );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Event fired by the {@link #execute} method.\n\t\t\t *\n\t\t\t * It allows to execute an action after executing the {@link ~ListCommand#execute} method, for example adjusting\n\t\t\t * attributes of changed blocks.\n\t\t\t *\n\t\t\t * @protected\n\t\t\t * @event _executeCleanup\n\t\t\t */\n\t\t\tthis.fire( '_executeCleanup', blocks );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks the command's {@link #value}.\n\t *\n\t * @private\n\t * @returns {Boolean} The current value.\n\t */\n\t_getValue() {\n\t\t// Check whether closest `listItem` ancestor of the position has a correct type.\n\t\tconst listItem = first( this.editor.model.document.selection.getSelectedBlocks() );\n\n\t\treturn !!listItem && listItem.is( 'element', 'listItem' ) && listItem.getAttribute( 'listType' ) == this.type;\n\t}\n\n\t/**\n\t * Checks whether the command can be enabled in the current context.\n\t *\n\t * @private\n\t * @returns {Boolean} Whether the command should be enabled.\n\t */\n\t_checkEnabled() {\n\t\t// If command value is true it means that we are in list item, so the command should be enabled.\n\t\tif ( this.value ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst selection = this.editor.model.document.selection;\n\t\tconst schema = this.editor.model.schema;\n\n\t\tconst firstBlock = first( selection.getSelectedBlocks() );\n\n\t\tif ( !firstBlock ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Otherwise, check if list item can be inserted at the position start.\n\t\treturn checkCanBecomeListItem( firstBlock, schema );\n\t}\n}\n\n// Helper function used when one or more list item have their type changed. Fixes type of other list items\n// that are affected by the change (are in same lists) but are not directly in selection. The function got extracted\n// not to duplicated code, as same fix has to be performed before and after selection.\n//\n// @param {Array.} blocks Blocks that are in selection.\n// @param {Boolean} isBackward Specified whether fix will be applied for blocks before first selected block (`true`)\n// or blocks after last selected block (`false`).\n// @param {Number} lowestIndent Lowest indent among selected blocks.\nfunction _fixType( blocks, isBackward, lowestIndent ) {\n\t// We need to check previous sibling of first changed item and next siblings of last changed item.\n\tconst startingItem = isBackward ? blocks[ 0 ] : blocks[ blocks.length - 1 ];\n\n\tif ( startingItem.is( 'element', 'listItem' ) ) {\n\t\tlet item = startingItem[ isBackward ? 'previousSibling' : 'nextSibling' ];\n\t\t// During processing items, keeps the lowest indent of already processed items.\n\t\t// This saves us from changing too many items.\n\t\t// Following example is for going forward as it is easier to read, however same applies to going backward.\n\t\t// * ------\n\t\t// * ------\n\t\t// * --[---\n\t\t// * ------\t\t<-- `lowestIndent` should be 1\n\t\t// * --]---\t\t<-- `startingItem`, `currentIndent` = 2, `lowestIndent` == 1\n\t\t// * ------\t\t<-- should be fixed, `indent` == 2 == `currentIndent`\n\t\t// * ------\t\t<-- should be fixed, set `currentIndent` to 1, `indent` == 1 == `currentIndent`\n\t\t// * ------\t\t<-- should not be fixed, item is in different list, `indent` = 2, `indent` != `currentIndent`\n\t\t// * ------\t\t<-- should be fixed, `indent` == 1 == `currentIndent`\n\t\t// * ------\t\t\t<-- break loop (`indent` < `lowestIndent`)\n\t\tlet currentIndent = startingItem.getAttribute( 'listIndent' );\n\n\t\t// Look back until a list item with indent lower than reference `lowestIndent`.\n\t\t// That would be the parent of nested sublist which contains item having `lowestIndent`.\n\t\twhile ( item && item.is( 'element', 'listItem' ) && item.getAttribute( 'listIndent' ) >= lowestIndent ) {\n\t\t\tif ( currentIndent > item.getAttribute( 'listIndent' ) ) {\n\t\t\t\tcurrentIndent = item.getAttribute( 'listIndent' );\n\t\t\t}\n\n\t\t\t// Found an item that is in the same nested sublist.\n\t\t\tif ( item.getAttribute( 'listIndent' ) == currentIndent ) {\n\t\t\t\t// Just add the item to selected blocks like it was selected by the user.\n\t\t\t\tblocks[ isBackward ? 'unshift' : 'push' ]( item );\n\t\t\t}\n\n\t\t\titem = item[ isBackward ? 'previousSibling' : 'nextSibling' ];\n\t\t}\n\t}\n}\n\n// Checks whether the given block can be replaced by a listItem.\n//\n// @private\n// @param {module:engine/model/element~Element} block A block to be tested.\n// @param {module:engine/model/schema~Schema} schema The schema of the document.\n// @returns {Boolean}\nfunction checkCanBecomeListItem( block, schema ) {\n\treturn schema.checkChild( block.parent, 'listItem' ) && !schema.isObject( block );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/listui\n */\n\nimport { createUIComponent } from './utils';\n\nimport numberedListIcon from '../theme/icons/numberedlist.svg';\nimport bulletedListIcon from '../theme/icons/bulletedlist.svg';\n\nimport { Plugin } from 'ckeditor5/src/core';\n\n/**\n * The list UI feature. It introduces the `'numberedList'` and `'bulletedList'` buttons that\n * allow to convert paragraphs to and from list items and indent or outdent them.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ListUI extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ListUI';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst t = this.editor.t;\n\n\t\t// Create two buttons and link them with numberedList and bulletedList commands.\n\t\tcreateUIComponent( this.editor, 'numberedList', t( 'Numbered List' ), numberedListIcon );\n\t\tcreateUIComponent( this.editor, 'bulletedList', t( 'Bulleted List' ), bulletedListIcon );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/list\n */\n\nimport ListEditing from './listediting';\nimport ListUI from './listui';\n\nimport { Plugin } from 'ckeditor5/src/core';\n\n/**\n * The list feature.\n *\n * This is a \"glue\" plugin that loads the {@link module:list/listediting~ListEditing list editing feature}\n * and {@link module:list/listui~ListUI list UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class List extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ListEditing, ListUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'List';\n\t}\n}\n","module.exports = \"\"","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/checktodolistcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\n\nconst attributeKey = 'todoListChecked';\n\n/**\n * The check to-do command.\n *\n * The command is registered by the {@link module:list/todolistediting~TodoListEditing} as\n * the `checkTodoList` editor command and it is also available via aliased `todoListCheck` name.\n *\n * @extends module:core/command~Command\n */\nexport default class CheckTodoListCommand extends Command {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * A flag indicating whether the command is active. The command is active when at least one of\n\t\t * {@link module:engine/model/selection~Selection selected} elements is a to-do list item.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Boolean} #isEnabled\n\t\t */\n\n\t\t/**\n\t\t * A list of to-do list items selected by the {@link module:engine/model/selection~Selection}.\n\t\t *\n\t\t * @observable\n\t\t * @readonly\n\t\t * @member {Array.} #value\n\t\t */\n\n\t\t/**\n\t\t * A list of to-do list items selected by the {@link module:engine/model/selection~Selection}.\n\t\t *\n\t\t * @protected\n\t\t * @type {Array.}\n\t\t */\n\t\tthis._selectedElements = [];\n\n\t\t// Refresh command before executing to be sure all values are up to date.\n\t\t// It is needed when selection has changed before command execution, in the same change block.\n\t\tthis.on( 'execute', () => {\n\t\t\tthis.refresh();\n\t\t}, { priority: 'highest' } );\n\t}\n\n\t/**\n\t * Updates the command's {@link #value} and {@link #isEnabled} properties based on the current selection.\n\t */\n\trefresh() {\n\t\tthis._selectedElements = this._getSelectedItems();\n\t\tthis.value = this._selectedElements.every( element => !!element.getAttribute( 'todoListChecked' ) );\n\t\tthis.isEnabled = !!this._selectedElements.length;\n\t}\n\n\t/**\n\t * Gets all to-do list items selected by the {@link module:engine/model/selection~Selection}.\n\t *\n\t * @private\n\t * @returns {Array.}\n\t */\n\t_getSelectedItems() {\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\n\t\tconst selectionRange = model.document.selection.getFirstRange();\n\t\tconst startElement = selectionRange.start.parent;\n\t\tconst elements = [];\n\n\t\tif ( schema.checkAttribute( startElement, attributeKey ) ) {\n\t\t\telements.push( startElement );\n\t\t}\n\n\t\tfor ( const item of selectionRange.getItems() ) {\n\t\t\tif ( schema.checkAttribute( item, attributeKey ) && !elements.includes( item ) ) {\n\t\t\t\telements.push( item );\n\t\t\t}\n\t\t}\n\n\t\treturn elements;\n\t}\n\n\t/**\n\t * Executes the command.\n\t *\n\t * @param {Object} [options]\n\t * @param {Boolean} [options.forceValue] If set, it will force the command behavior. If `true`, the command will apply\n\t * the attribute. Otherwise, the command will remove the attribute. If not set, the command will look for its current\n\t * value to decide what it should do.\n\t */\n\texecute( options = {} ) {\n\t\tthis.editor.model.change( writer => {\n\t\t\tfor ( const element of this._selectedElements ) {\n\t\t\t\tconst value = ( options.forceValue === undefined ) ? !this.value : options.forceValue;\n\n\t\t\t\tif ( value ) {\n\t\t\t\t\twriter.setAttribute( attributeKey, true, element );\n\t\t\t\t} else {\n\t\t\t\t\twriter.removeAttribute( attributeKey, element );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/todolistconverters\n */\n\n/* global document */\n\nimport { createElement } from 'ckeditor5/src/utils';\n\nimport { generateLiInUl, injectViewList, positionAfterUiElements, findNestedList } from './utils';\n\n/**\n * A model-to-view converter for the `listItem` model element insertion.\n *\n * It converts the `listItem` model element to an unordered list with a {@link module:engine/view/uielement~UIElement checkbox element}\n * at the beginning of each list item. It also merges the list with surrounding lists (if available).\n *\n * It is used by {@link module:engine/controller/editingcontroller~EditingController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:engine/model/model~Model} model Model instance.\n * @param {Function} onCheckboxChecked Callback function.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewInsertion( model, onCheckboxChecked ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst consumable = conversionApi.consumable;\n\n\t\tif ( !consumable.test( data.item, 'insert' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listType' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listIndent' )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data.item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelItem = data.item;\n\n\t\tconsumable.consume( modelItem, 'insert' );\n\t\tconsumable.consume( modelItem, 'attribute:listType' );\n\t\tconsumable.consume( modelItem, 'attribute:listIndent' );\n\t\tconsumable.consume( modelItem, 'attribute:todoListChecked' );\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst viewItem = generateLiInUl( modelItem, conversionApi );\n\n\t\tconst isChecked = !!modelItem.getAttribute( 'todoListChecked' );\n\t\tconst checkmarkElement = createCheckmarkElement( modelItem, viewWriter, isChecked, onCheckboxChecked );\n\n\t\tconst span = viewWriter.createContainerElement( 'span', {\n\t\t\tclass: 'todo-list__label__description'\n\t\t} );\n\n\t\tviewWriter.addClass( 'todo-list', viewItem.parent );\n\t\tviewWriter.insert( viewWriter.createPositionAt( viewItem, 0 ), checkmarkElement );\n\t\tviewWriter.insert( viewWriter.createPositionAfter( checkmarkElement ), span );\n\n\t\tinjectViewList( modelItem, viewItem, conversionApi, model );\n\t};\n}\n\n/**\n * A model-to-view converter for the `listItem` model element insertion.\n *\n * It is used by {@link module:engine/controller/datacontroller~DataController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function dataModelViewInsertion( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst consumable = conversionApi.consumable;\n\n\t\tif ( !consumable.test( data.item, 'insert' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listType' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listIndent' )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( data.item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelItem = data.item;\n\n\t\tconsumable.consume( modelItem, 'insert' );\n\t\tconsumable.consume( modelItem, 'attribute:listType' );\n\t\tconsumable.consume( modelItem, 'attribute:listIndent' );\n\t\tconsumable.consume( modelItem, 'attribute:todoListChecked' );\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst viewItem = generateLiInUl( modelItem, conversionApi );\n\n\t\tviewWriter.addClass( 'todo-list', viewItem.parent );\n\n\t\tconst label = viewWriter.createContainerElement( 'label', {\n\t\t\tclass: 'todo-list__label'\n\t\t} );\n\n\t\tconst checkbox = viewWriter.createEmptyElement( 'input', {\n\t\t\ttype: 'checkbox',\n\t\t\tdisabled: 'disabled'\n\t\t} );\n\n\t\tconst span = viewWriter.createContainerElement( 'span', {\n\t\t\tclass: 'todo-list__label__description'\n\t\t} );\n\n\t\tif ( modelItem.getAttribute( 'todoListChecked' ) ) {\n\t\t\tviewWriter.setAttribute( 'checked', 'checked', checkbox );\n\t\t}\n\n\t\tviewWriter.insert( viewWriter.createPositionAt( viewItem, 0 ), label );\n\t\tviewWriter.insert( viewWriter.createPositionAt( label, 0 ), checkbox );\n\t\tviewWriter.insert( viewWriter.createPositionAfter( checkbox ), span );\n\n\t\tinjectViewList( modelItem, viewItem, conversionApi, model );\n\t};\n}\n\n/**\n * A view-to-model converter for the checkbox element inside a view list item.\n *\n * It changes the `listType` of the model `listItem` to a `todo` value.\n * When a view checkbox element is marked as checked, an additional `todoListChecked=\"true\"` attribute is added to the model item.\n *\n * It is used by {@link module:engine/controller/datacontroller~DataController}.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input, a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function dataViewModelCheckmarkInsertion( evt, data, conversionApi ) {\n\tconst modelCursor = data.modelCursor;\n\tconst modelItem = modelCursor.parent;\n\tconst viewItem = data.viewItem;\n\n\tif ( viewItem.getAttribute( 'type' ) != 'checkbox' || modelItem.name != 'listItem' || !modelCursor.isAtStart ) {\n\t\treturn;\n\t}\n\n\tif ( !conversionApi.consumable.consume( viewItem, { name: true } ) ) {\n\t\treturn;\n\t}\n\n\tconst writer = conversionApi.writer;\n\n\twriter.setAttribute( 'listType', 'todo', modelItem );\n\n\tif ( data.viewItem.hasAttribute( 'checked' ) ) {\n\t\twriter.setAttribute( 'todoListChecked', true, modelItem );\n\t}\n\n\tdata.modelRange = writer.createRange( modelCursor );\n}\n\n/**\n * A model-to-view converter for the `listType` attribute change on the `listItem` model element.\n *\n * This change means that the `
  • ` element parent changes to `
      ` and a\n * {@link module:engine/view/uielement~UIElement checkbox UI element} is added at the beginning\n * of the list item element (or vice versa).\n *\n * This converter is preceded by {@link module:list/converters~modelViewChangeType} and followed by\n * {@link module:list/converters~modelViewMergeAfterChangeType} to handle splitting and merging surrounding lists of the same type.\n *\n * It is used by {@link module:engine/controller/editingcontroller~EditingController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {Function} onCheckedChange Callback fired after clicking the checkbox UI element.\n * @param {module:engine/view/view~View} view Editing view controller.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewChangeType( onCheckedChange, view ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\tconst labelElement = findLabel( viewItem, view );\n\n\t\tif ( data.attributeNewValue == 'todo' ) {\n\t\t\tconst isChecked = !!data.item.getAttribute( 'todoListChecked' );\n\t\t\tconst checkmarkElement = createCheckmarkElement( data.item, viewWriter, isChecked, onCheckedChange );\n\n\t\t\tconst span = viewWriter.createContainerElement( 'span', {\n\t\t\t\tclass: 'todo-list__label__description'\n\t\t\t} );\n\n\t\t\tconst itemRange = viewWriter.createRangeIn( viewItem );\n\t\t\tconst nestedList = findNestedList( viewItem );\n\n\t\t\tconst descriptionStart = positionAfterUiElements( itemRange.start );\n\t\t\tconst descriptionEnd = nestedList ? viewWriter.createPositionBefore( nestedList ) : itemRange.end;\n\t\t\tconst descriptionRange = viewWriter.createRange( descriptionStart, descriptionEnd );\n\n\t\t\tviewWriter.addClass( 'todo-list', viewItem.parent );\n\t\t\tviewWriter.move( descriptionRange, viewWriter.createPositionAt( span, 0 ) );\n\t\t\tviewWriter.insert( viewWriter.createPositionAt( viewItem, 0 ), checkmarkElement );\n\t\t\tviewWriter.insert( viewWriter.createPositionAfter( checkmarkElement ), span );\n\t\t} else if ( data.attributeOldValue == 'todo' ) {\n\t\t\tconst descriptionSpan = findDescription( viewItem, view );\n\n\t\t\tviewWriter.removeClass( 'todo-list', viewItem.parent );\n\t\t\tviewWriter.remove( labelElement );\n\t\t\tviewWriter.move( viewWriter.createRangeIn( descriptionSpan ), viewWriter.createPositionBefore( descriptionSpan ) );\n\t\t\tviewWriter.remove( descriptionSpan );\n\t\t}\n\t};\n}\n\n/**\n * A model-to-view converter for the `todoListChecked` attribute change on the `listItem` model element.\n *\n * It marks the {@link module:engine/view/uielement~UIElement checkbox UI element} as checked.\n *\n * It is used by {@link module:engine/controller/editingcontroller~EditingController}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {Function} onCheckedChange Callback fired after clicking the checkbox UI element.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewChangeChecked( onCheckedChange ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\t// Do not convert `todoListChecked` attribute when to-do list item has changed to other list item.\n\t\t// This attribute will be removed by the model post fixer.\n\t\tif ( data.item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !conversionApi.consumable.consume( data.item, 'attribute:todoListChecked' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { mapper, writer: viewWriter } = conversionApi;\n\t\tconst isChecked = !!data.item.getAttribute( 'todoListChecked' );\n\t\tconst viewItem = mapper.toViewElement( data.item );\n\t\t// Because of m -> v position mapper we can be sure checkbox is always at the beginning.\n\t\tconst oldCheckmarkElement = viewItem.getChild( 0 );\n\t\tconst newCheckmarkElement = createCheckmarkElement( data.item, viewWriter, isChecked, onCheckedChange );\n\n\t\tviewWriter.insert( viewWriter.createPositionAfter( oldCheckmarkElement ), newCheckmarkElement );\n\t\tviewWriter.remove( oldCheckmarkElement );\n\t};\n}\n\n/**\n * A model-to-view position at zero offset mapper.\n *\n * This helper ensures that position inside todo-list in the view is mapped after the checkbox.\n *\n * It only handles the position at the beginning of a list item as other positions are properly mapped be the default mapper.\n *\n * @param {module:engine/view/view~View} view\n * @return {Function}\n */\nexport function mapModelToViewPosition( view ) {\n\treturn ( evt, data ) => {\n\t\tconst modelPosition = data.modelPosition;\n\t\tconst parent = modelPosition.parent;\n\n\t\tif ( !parent.is( 'element', 'listItem' ) || parent.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewLi = data.mapper.toViewElement( parent );\n\t\tconst descSpan = findDescription( viewLi, view );\n\n\t\tif ( descSpan ) {\n\t\t\tdata.viewPosition = data.mapper.findPositionIn( descSpan, modelPosition.offset );\n\t\t}\n\t};\n}\n\n// Creates a checkbox UI element.\n//\n// @private\n// @param {module:engine/model/item~Item} modelItem\n// @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n// @param {Boolean} isChecked\n// @param {Function} onChange\n// @returns {module:view/uielement~UIElement}\nfunction createCheckmarkElement( modelItem, viewWriter, isChecked, onChange ) {\n\tconst uiElement = viewWriter.createUIElement(\n\t\t'label',\n\t\t{\n\t\t\tclass: 'todo-list__label',\n\t\t\tcontenteditable: false\n\t\t},\n\t\tfunction( domDocument ) {\n\t\t\tconst checkbox = createElement( document, 'input', { type: 'checkbox' } );\n\n\t\t\tif ( isChecked ) {\n\t\t\t\tcheckbox.setAttribute( 'checked', 'checked' );\n\t\t\t}\n\n\t\t\tcheckbox.addEventListener( 'change', () => onChange( modelItem ) );\n\n\t\t\tconst domElement = this.toDomElement( domDocument );\n\n\t\t\tdomElement.appendChild( checkbox );\n\n\t\t\treturn domElement;\n\t\t}\n\t);\n\n\treturn uiElement;\n}\n\n// Helper method to find label element inside li.\nfunction findLabel( viewItem, view ) {\n\tconst range = view.createRangeIn( viewItem );\n\n\tfor ( const value of range ) {\n\t\tif ( value.item.is( 'uiElement', 'label' ) ) {\n\t\t\treturn value.item;\n\t\t}\n\t}\n}\n\nfunction findDescription( viewItem, view ) {\n\tconst range = view.createRangeIn( viewItem );\n\n\tfor ( const value of range ) {\n\t\tif ( value.item.is( 'containerElement', 'span' ) && value.item.hasClass( 'todo-list__label__description' ) ) {\n\t\t\treturn value.item;\n\t\t}\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/todolistediting\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport {\n\tgetCode,\n\tparseKeystroke,\n\tgetLocalizedArrowKeyCodeDirection\n} from 'ckeditor5/src/utils';\n\nimport ListCommand from './listcommand';\nimport ListEditing from './listediting';\nimport CheckTodoListCommand from './checktodolistcommand';\nimport {\n\tdataModelViewInsertion,\n\tdataViewModelCheckmarkInsertion,\n\tmapModelToViewPosition,\n\tmodelViewChangeChecked,\n\tmodelViewChangeType,\n\tmodelViewInsertion\n} from './todolistconverters';\n\nconst ITEM_TOGGLE_KEYSTROKE = parseKeystroke( 'Ctrl+Enter' );\n\n/**\n * The engine of the to-do list feature. It handles creating, editing and removing to-do lists and their items.\n *\n * It registers the entire functionality of the {@link module:list/listediting~ListEditing list editing plugin} and extends\n * it with the commands:\n *\n * - `'todoList'`,\n * - `'checkTodoList'`,\n * - `'todoListCheck'` as an alias for `checkTodoList` command.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TodoListEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'TodoListEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ListEditing ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst { editing, data, model } = editor;\n\n\t\t// Extend schema.\n\t\tmodel.schema.extend( 'listItem', {\n\t\t\tallowAttributes: [ 'todoListChecked' ]\n\t\t} );\n\n\t\t// Disallow todoListChecked attribute on other nodes than listItem with to-do listType.\n\t\tmodel.schema.addAttributeCheck( ( context, attributeName ) => {\n\t\t\tconst item = context.last;\n\n\t\t\tif ( attributeName == 'todoListChecked' && item.name == 'listItem' && item.getAttribute( 'listType' ) != 'todo' ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t\t// Register `todoList` command.\n\t\teditor.commands.add( 'todoList', new ListCommand( editor, 'todo' ) );\n\n\t\tconst checkTodoListCommand = new CheckTodoListCommand( editor );\n\n\t\t// Register `checkTodoList` command and add `todoListCheck` command as an alias for backward compatibility.\n\t\teditor.commands.add( 'checkTodoList', checkTodoListCommand );\n\t\teditor.commands.add( 'todoListCheck', checkTodoListCommand );\n\n\t\t// Define converters.\n\t\tdata.downcastDispatcher.on( 'insert:listItem', dataModelViewInsertion( model ), { priority: 'high' } );\n\t\tdata.upcastDispatcher.on( 'element:input', dataViewModelCheckmarkInsertion, { priority: 'high' } );\n\n\t\tediting.downcastDispatcher.on(\n\t\t\t'insert:listItem',\n\t\t\tmodelViewInsertion( model, listItem => this._handleCheckmarkChange( listItem ) ),\n\t\t\t{ priority: 'high' }\n\t\t);\n\t\tediting.downcastDispatcher.on(\n\t\t\t'attribute:listType:listItem',\n\t\t\tmodelViewChangeType( listItem => this._handleCheckmarkChange( listItem ), editing.view )\n\t\t);\n\t\tediting.downcastDispatcher.on(\n\t\t\t'attribute:todoListChecked:listItem',\n\t\t\tmodelViewChangeChecked( listItem => this._handleCheckmarkChange( listItem ) )\n\t\t);\n\n\t\tediting.mapper.on( 'modelToViewPosition', mapModelToViewPosition( editing.view ) );\n\t\tdata.mapper.on( 'modelToViewPosition', mapModelToViewPosition( editing.view ) );\n\n\t\t// Jump at the end of the previous node on left arrow key press, when selection is after the checkbox.\n\t\t//\n\t\t//

      Foo

      \n\t\t//
      • {}Bar
      \n\t\t//\n\t\t// press: `<-`\n\t\t//\n\t\t//

      Foo{}

      \n\t\t//
      • Bar
      \n\t\t//\n\t\tthis.listenTo( editing.view.document, 'keydown', jumpOverCheckmarkOnSideArrowKeyPress( model, editor.locale ) );\n\n\t\t// Toggle check state of selected to-do list items on keystroke.\n\t\tthis.listenTo( editing.view.document, 'keydown', ( evt, data ) => {\n\t\t\tif ( getCode( data ) === ITEM_TOGGLE_KEYSTROKE ) {\n\t\t\t\teditor.execute( 'checkTodoList' );\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\n\t\t// Remove `todoListChecked` attribute when a host element is no longer a to-do list item.\n\t\tconst listItemsToFix = new Set();\n\n\t\tthis.listenTo( model, 'applyOperation', ( evt, args ) => {\n\t\t\tconst operation = args[ 0 ];\n\n\t\t\tif ( operation.type == 'rename' && operation.oldName == 'listItem' ) {\n\t\t\t\tconst item = operation.position.nodeAfter;\n\n\t\t\t\tif ( item.hasAttribute( 'todoListChecked' ) ) {\n\t\t\t\t\tlistItemsToFix.add( item );\n\t\t\t\t}\n\t\t\t} else if ( operation.type == 'changeAttribute' && operation.key == 'listType' && operation.oldValue === 'todo' ) {\n\t\t\t\tfor ( const item of operation.range.getItems() ) {\n\t\t\t\t\tif ( item.hasAttribute( 'todoListChecked' ) && item.getAttribute( 'listType' ) !== 'todo' ) {\n\t\t\t\t\t\tlistItemsToFix.add( item );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\tmodel.document.registerPostFixer( writer => {\n\t\t\tlet hasChanged = false;\n\n\t\t\tfor ( const listItem of listItemsToFix ) {\n\t\t\t\twriter.removeAttribute( 'todoListChecked', listItem );\n\t\t\t\thasChanged = true;\n\t\t\t}\n\n\t\t\tlistItemsToFix.clear();\n\n\t\t\treturn hasChanged;\n\t\t} );\n\t}\n\n\t/**\n\t * Handles the checkbox element change, moves the selection to the corresponding model item to make it possible\n\t * to toggle the `todoListChecked` attribute using the command, and restores the selection position.\n\t *\n\t * Some say it's a hack :) Moving the selection only for executing the command on a certain node and restoring it after,\n\t * is not a clear solution. We need to design an API for using commands beyond the selection range.\n\t * See https://github.com/ckeditor/ckeditor5/issues/1954.\n\t *\n\t * @private\n\t * @param {module:engine/model/element~Element} listItem\n\t */\n\t_handleCheckmarkChange( listItem ) {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst previousSelectionRanges = Array.from( model.document.selection.getRanges() );\n\n\t\tmodel.change( writer => {\n\t\t\twriter.setSelection( listItem, 'end' );\n\t\t\teditor.execute( 'checkTodoList' );\n\t\t\twriter.setSelection( previousSelectionRanges );\n\t\t} );\n\t}\n}\n\n// Handles the left/right (LTR/RTL content) arrow key and moves the selection at the end of the previous block element\n// if the selection is just after the checkbox element. In other words, it jumps over the checkbox element when\n// moving the selection to the left/right (LTR/RTL).\n//\n// @private\n// @param {module:engine/model/model~Model} model\n// @param {module:utils/locale~Locale} locale\n// @returns {Function} Callback for 'keydown' events.\nfunction jumpOverCheckmarkOnSideArrowKeyPress( model, locale ) {\n\treturn ( eventInfo, domEventData ) => {\n\t\tconst direction = getLocalizedArrowKeyCodeDirection( domEventData.keyCode, locale.contentLanguageDirection );\n\n\t\tif ( direction != 'left' ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst schema = model.schema;\n\t\tconst selection = model.document.selection;\n\n\t\tif ( !selection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst position = selection.getFirstPosition();\n\t\tconst parent = position.parent;\n\n\t\tif ( parent.name === 'listItem' && parent.getAttribute( 'listType' ) == 'todo' && position.isAtStart ) {\n\t\t\tconst newRange = schema.getNearestSelectionRange( model.createPositionBefore( parent ), 'backward' );\n\n\t\t\tif ( newRange ) {\n\t\t\t\tmodel.change( writer => writer.setSelection( newRange ) );\n\t\t\t}\n\n\t\t\tdomEventData.preventDefault();\n\t\t\tdomEventData.stopPropagation();\n\t\t\teventInfo.stop();\n\t\t}\n\t};\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/todolistui\n */\n\nimport { createUIComponent } from './utils';\nimport todoListIcon from '../theme/icons/todolist.svg';\nimport { Plugin } from 'ckeditor5/src/core';\n\n/**\n * The to-do list UI feature. It introduces the `'todoList'` button that\n * allows to convert elements to and from to-do list items and to indent or outdent them.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TodoListUI extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'TodoListUI';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst t = this.editor.t;\n\n\t\tcreateUIComponent( this.editor, 'todoList', t( 'To-do List' ), todoListIcon );\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/todolist\n */\n\nimport TodoListEditing from './todolistediting';\nimport TodoListUI from './todolistui';\nimport { Plugin } from 'ckeditor5/src/core';\nimport '../theme/todolist.css';\n\n/**\n * The to-do list feature.\n *\n * This is a \"glue\" plugin that loads the {@link module:list/todolistediting~TodoListEditing to-do list editing feature}\n * and the {@link module:list/todolistui~TodoListUI to-do list UI feature}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class TodoList extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ TodoListEditing, TodoListUI ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'TodoList';\n\t}\n}\n","module.exports = \"\"","module.exports = \"\"","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/indentcommand\n */\n\nimport { Command } from 'ckeditor5/src/core';\nimport { first } from 'ckeditor5/src/utils';\n\n/**\n * The list indent command. It is used by the {@link module:list/list~List list feature}.\n *\n * @extends module:core/command~Command\n */\nexport default class IndentCommand extends Command {\n\t/**\n\t * Creates an instance of the command.\n\t *\n\t * @param {module:core/editor/editor~Editor} editor The editor instance.\n\t * @param {'forward'|'backward'} indentDirection The direction of indent. If it is equal to `backward`, the command\n\t * will outdent a list item.\n\t */\n\tconstructor( editor, indentDirection ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * Determines by how much the command will change the list item's indent attribute.\n\t\t *\n\t\t * @readonly\n\t\t * @private\n\t\t * @member {Number}\n\t\t */\n\t\tthis._indentBy = indentDirection == 'forward' ? 1 : -1;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\trefresh() {\n\t\tthis.isEnabled = this._checkEnabled();\n\t}\n\n\t/**\n\t * Indents or outdents (depending on the {@link #constructor}'s `indentDirection` parameter) selected list items.\n\t *\n\t * @fires execute\n\t * @fires _executeCleanup\n\t */\n\texecute() {\n\t\tconst model = this.editor.model;\n\t\tconst doc = model.document;\n\t\tlet itemsToChange = Array.from( doc.selection.getSelectedBlocks() );\n\n\t\tmodel.change( writer => {\n\t\t\tconst lastItem = itemsToChange[ itemsToChange.length - 1 ];\n\n\t\t\t// Indenting a list item should also indent all the items that are already sub-items of indented item.\n\t\t\tlet next = lastItem.nextSibling;\n\n\t\t\t// Check all items after last indented item, as long as their indent is bigger than indent of that item.\n\t\t\twhile ( next && next.name == 'listItem' && next.getAttribute( 'listIndent' ) > lastItem.getAttribute( 'listIndent' ) ) {\n\t\t\t\titemsToChange.push( next );\n\n\t\t\t\tnext = next.nextSibling;\n\t\t\t}\n\n\t\t\t// We need to be sure to keep model in correct state after each small change, because converters\n\t\t\t// bases on that state and assumes that model is correct.\n\t\t\t// Because of that, if the command outdents items, we will outdent them starting from the last item, as\n\t\t\t// it is safer.\n\t\t\tif ( this._indentBy < 0 ) {\n\t\t\t\titemsToChange = itemsToChange.reverse();\n\t\t\t}\n\n\t\t\tfor ( const item of itemsToChange ) {\n\t\t\t\tconst indent = item.getAttribute( 'listIndent' ) + this._indentBy;\n\n\t\t\t\t// If indent is lower than 0, it means that the item got outdented when it was not indented.\n\t\t\t\t// This means that we need to convert that list item to paragraph.\n\t\t\t\tif ( indent < 0 ) {\n\t\t\t\t\t// To keep the model as correct as possible, first rename listItem, then remove attributes,\n\t\t\t\t\t// as listItem without attributes is very incorrect and will cause problems in converters.\n\t\t\t\t\t// No need to remove attributes, will be removed by post fixer.\n\t\t\t\t\twriter.rename( item, 'paragraph' );\n\t\t\t\t}\n\t\t\t\t// If indent is >= 0, change the attribute value.\n\t\t\t\telse {\n\t\t\t\t\twriter.setAttribute( 'listIndent', indent, item );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Event fired by the {@link #execute} method.\n\t\t\t *\n\t\t\t * It allows to execute an action after executing the {@link ~IndentCommand#execute} method, for example adjusting\n\t\t\t * attributes of changed list items.\n\t\t\t *\n\t\t\t * @protected\n\t\t\t * @event _executeCleanup\n\t\t\t */\n\t\t\tthis.fire( '_executeCleanup', itemsToChange );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks whether the command can be enabled in the current context.\n\t *\n\t * @private\n\t * @returns {Boolean} Whether the command should be enabled.\n\t */\n\t_checkEnabled() {\n\t\t// Check whether any of position's ancestor is a list item.\n\t\tconst listItem = first( this.editor.model.document.selection.getSelectedBlocks() );\n\n\t\t// If selection is not in a list item, the command is disabled.\n\t\tif ( !listItem || !listItem.is( 'element', 'listItem' ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this._indentBy > 0 ) {\n\t\t\t// Cannot indent first item in it's list. Check if before `listItem` is a list item that is in same list.\n\t\t\t// To be in the same list, the item has to have same attributes and cannot be \"split\" by an item with lower indent.\n\t\t\tconst indent = listItem.getAttribute( 'listIndent' );\n\t\t\tconst type = listItem.getAttribute( 'listType' );\n\n\t\t\tlet prev = listItem.previousSibling;\n\n\t\t\twhile ( prev && prev.is( 'element', 'listItem' ) && prev.getAttribute( 'listIndent' ) >= indent ) {\n\t\t\t\tif ( prev.getAttribute( 'listIndent' ) == indent ) {\n\t\t\t\t\t// The item is on the same level.\n\t\t\t\t\t// If it has same type, it means that we found a preceding sibling from the same list.\n\t\t\t\t\t// If it does not have same type, it means that `listItem` is on different list (this can happen only\n\t\t\t\t\t// on top level lists, though).\n\t\t\t\t\treturn prev.getAttribute( 'listType' ) == type;\n\t\t\t\t}\n\n\t\t\t\tprev = prev.previousSibling;\n\t\t\t}\n\n\t\t\t// Could not find similar list item, this means that `listItem` is first in its list.\n\t\t\treturn false;\n\t\t}\n\n\t\t// If we are outdenting it is enough to be in list item. Every list item can always be outdented.\n\t\treturn true;\n\t}\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/converters\n */\n\nimport { TreeWalker } from 'ckeditor5/src/engine';\n\nimport {\n\tgenerateLiInUl,\n\tinjectViewList,\n\tmergeViewLists,\n\tgetSiblingListItem,\n\tpositionAfterUiElements\n} from './utils';\n\n/**\n * A model-to-view converter for the `listItem` model element insertion.\n *\n * It creates a `
        • ` (or `
            `) view structure out of a `listItem` model element, inserts it at the correct\n * position, and merges the list with surrounding lists (if available).\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewInsertion( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst consumable = conversionApi.consumable;\n\n\t\tif ( !consumable.test( data.item, 'insert' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listType' ) ||\n\t\t\t!consumable.test( data.item, 'attribute:listIndent' )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconsumable.consume( data.item, 'insert' );\n\t\tconsumable.consume( data.item, 'attribute:listType' );\n\t\tconsumable.consume( data.item, 'attribute:listIndent' );\n\n\t\tconst modelItem = data.item;\n\t\tconst viewItem = generateLiInUl( modelItem, conversionApi );\n\n\t\tinjectViewList( modelItem, viewItem, conversionApi, model );\n\t};\n}\n\n/**\n * A model-to-view converter for the `listItem` model element removal.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:remove\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewRemove( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tconst viewPosition = conversionApi.mapper.toViewPosition( data.position );\n\t\tconst viewStart = viewPosition.getLastMatchingPosition( value => !value.item.is( 'element', 'li' ) );\n\t\tconst viewItem = viewStart.nodeAfter;\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\t// 1. Break the container after and before the list item.\n\t\t// This will create a view list with one view list item - the one to remove.\n\t\tviewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) );\n\t\tviewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\n\t\t// 2. Remove the list with the item to remove.\n\t\tconst viewList = viewItem.parent;\n\t\tconst viewListPrev = viewList.previousSibling;\n\t\tconst removeRange = viewWriter.createRangeOn( viewList );\n\t\tconst removed = viewWriter.remove( removeRange );\n\n\t\t// 3. Merge the whole created by breaking and removing the list.\n\t\tif ( viewListPrev && viewListPrev.nextSibling ) {\n\t\t\tmergeViewLists( viewWriter, viewListPrev, viewListPrev.nextSibling );\n\t\t}\n\n\t\t// 4. Bring back nested list that was in the removed
          1. .\n\t\tconst modelItem = conversionApi.mapper.toModelElement( viewItem );\n\n\t\thoistNestedLists( modelItem.getAttribute( 'listIndent' ) + 1, data.position, removeRange.start, viewItem, conversionApi, model );\n\n\t\t// 5. Unbind removed view item and all children.\n\t\tfor ( const child of viewWriter.createRangeIn( removed ).getItems() ) {\n\t\t\tconversionApi.mapper.unbindViewElement( child );\n\t\t}\n\n\t\tevt.stop();\n\t};\n}\n\n/**\n * A model-to-view converter for the `type` attribute change on the `listItem` model element.\n *\n * This change means that the `
          2. ` element parent changes from `
              ` to `
                ` (or vice versa). This is accomplished\n * by breaking view elements and changing their name. The next {@link module:list/converters~modelViewMergeAfterChangeType}\n * converter will attempt to merge split nodes.\n *\n * Splitting this conversion into 2 steps makes it possible to add an additional conversion in the middle.\n * Check {@link module:list/todolistconverters~modelViewChangeType} to see an example of it.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewChangeType( evt, data, conversionApi ) {\n\tif ( !conversionApi.consumable.consume( data.item, 'attribute:listType' ) ) {\n\t\treturn;\n\t}\n\n\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\tconst viewWriter = conversionApi.writer;\n\n\t// Break the container after and before the list item.\n\t// This will create a view list with one view list item -- the one that changed type.\n\tviewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) );\n\tviewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\n\t// Change name of the view list that holds the changed view item.\n\t// We cannot just change name property, because that would not render properly.\n\tconst viewList = viewItem.parent;\n\tconst listName = data.attributeNewValue == 'numbered' ? 'ol' : 'ul';\n\n\tviewWriter.rename( listName, viewList );\n}\n\n/**\n * A model-to-view converter that attempts to merge nodes split by {@link module:list/converters~modelViewChangeType}.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewMergeAfterChangeType( evt, data, conversionApi ) {\n\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\tconst viewList = viewItem.parent;\n\tconst viewWriter = conversionApi.writer;\n\n\t// Merge the changed view list with other lists, if possible.\n\tmergeViewLists( viewWriter, viewList, viewList.nextSibling );\n\tmergeViewLists( viewWriter, viewList.previousSibling, viewList );\n\n\t// Consumable insertion of children inside the item. They are already handled by re-building the item in view.\n\tfor ( const child of data.item.getChildren() ) {\n\t\tconversionApi.consumable.consume( child, 'insert' );\n\t}\n}\n\n/**\n * A model-to-view converter for the `listIndent` attribute change on the `listItem` model element.\n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function modelViewChangeIndent( model ) {\n\treturn ( evt, data, conversionApi ) => {\n\t\tif ( !conversionApi.consumable.consume( data.item, 'attribute:listIndent' ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst viewItem = conversionApi.mapper.toViewElement( data.item );\n\t\tconst viewWriter = conversionApi.writer;\n\n\t\t// 1. Break the container after and before the list item.\n\t\t// This will create a view list with one view list item -- the one that changed type.\n\t\tviewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) );\n\t\tviewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\n\t\t// 2. Extract view list with changed view list item and merge \"hole\" possibly created by breaking and removing elements.\n\t\tconst viewList = viewItem.parent;\n\t\tconst viewListPrev = viewList.previousSibling;\n\t\tconst removeRange = viewWriter.createRangeOn( viewList );\n\t\tviewWriter.remove( removeRange );\n\n\t\tif ( viewListPrev && viewListPrev.nextSibling ) {\n\t\t\tmergeViewLists( viewWriter, viewListPrev, viewListPrev.nextSibling );\n\t\t}\n\n\t\t// 3. Bring back nested list that was in the removed
              1. .\n\t\thoistNestedLists( data.attributeOldValue + 1, data.range.start, removeRange.start, viewItem, conversionApi, model );\n\n\t\t// 4. Inject view list like it is newly inserted.\n\t\tinjectViewList( data.item, viewItem, conversionApi, model );\n\n\t\t// 5. Consume insertion of children inside the item. They are already handled by re-building the item in view.\n\t\tfor ( const child of data.item.getChildren() ) {\n\t\t\tconversionApi.consumable.consume( child, 'insert' );\n\t\t}\n\t};\n}\n\n/**\n * A special model-to-view converter introduced by the {@link module:list/list~List list feature}. This converter is fired for\n * insert change of every model item, and should be fired before the actual converter. The converter checks whether the inserted\n * model item is a non-`listItem` element. If it is, and it is inserted inside a view list, the converter breaks the\n * list so the model element is inserted to the view parent element corresponding to its model parent element.\n *\n * The converter prevents such situations:\n *\n *\t\t// Model: // View:\n *\t\tfoo
                  \n *\t\tbar
                • foo
                • \n *\t\t
                • bar
                • \n *\t\t
                \n *\n *\t\t// After change: // Correct view guaranteed by this converter:\n *\t\tfoo
                • foo

                xxx

                • bar
                \n *\t\txxx // Instead of this wrong view state:\n *\t\tbar
                • foo
                • xxx

                • bar
                \n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewSplitOnInsert( evt, data, conversionApi ) {\n\tif ( data.item.name != 'listItem' ) {\n\t\tlet viewPosition = conversionApi.mapper.toViewPosition( data.range.start );\n\n\t\tconst viewWriter = conversionApi.writer;\n\t\tconst lists = [];\n\n\t\t// Break multiple ULs/OLs if there are.\n\t\t//\n\t\t// Imagine following list:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.1.3 --------\n\t\t// 1.1.3.1 --------\n\t\t// 1.2 --------\n\t\t// 1.2.1 --------\n\t\t// 2 --------\n\t\t//\n\t\t// Insert paragraph after item 1.1.1:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t//\n\t\t// Lorem ipsum.\n\t\t//\n\t\t// 1.1.2 --------\n\t\t// 1.1.3 --------\n\t\t// 1.1.3.1 --------\n\t\t// 1.2 --------\n\t\t// 1.2.1 --------\n\t\t// 2 --------\n\t\t//\n\t\t// In this case 1.1.2 has to become beginning of a new list.\n\t\t// We need to break list before 1.1.2 (obvious), then we need to break list also before 1.2.\n\t\t// Then we need to move those broken pieces one after another and merge:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t//\n\t\t// Lorem ipsum.\n\t\t//\n\t\t// 1.1.2 --------\n\t\t// 1.1.3 --------\n\t\t// 1.1.3.1 --------\n\t\t// 1.2 --------\n\t\t// 1.2.1 --------\n\t\t// 2 --------\n\t\t//\n\t\twhile ( viewPosition.parent.name == 'ul' || viewPosition.parent.name == 'ol' ) {\n\t\t\tviewPosition = viewWriter.breakContainer( viewPosition );\n\n\t\t\tif ( viewPosition.parent.name != 'li' ) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Remove lists that are after inserted element.\n\t\t\t// They will be brought back later, below the inserted element.\n\t\t\tconst removeStart = viewPosition;\n\t\t\tconst removeEnd = viewWriter.createPositionAt( viewPosition.parent, 'end' );\n\n\t\t\t// Don't remove if there is nothing to remove.\n\t\t\tif ( !removeStart.isEqual( removeEnd ) ) {\n\t\t\t\tconst removed = viewWriter.remove( viewWriter.createRange( removeStart, removeEnd ) );\n\t\t\t\tlists.push( removed );\n\t\t\t}\n\n\t\t\tviewPosition = viewWriter.createPositionAfter( viewPosition.parent );\n\t\t}\n\n\t\t// Bring back removed lists.\n\t\tif ( lists.length > 0 ) {\n\t\t\tfor ( let i = 0; i < lists.length; i++ ) {\n\t\t\t\tconst previousList = viewPosition.nodeBefore;\n\t\t\t\tconst insertedRange = viewWriter.insert( viewPosition, lists[ i ] );\n\t\t\t\tviewPosition = insertedRange.end;\n\n\t\t\t\t// Don't merge first list! We want a split in that place (this is why this converter is introduced).\n\t\t\t\tif ( i > 0 ) {\n\t\t\t\t\tconst mergePos = mergeViewLists( viewWriter, previousList, previousList.nextSibling );\n\n\t\t\t\t\t// If `mergePos` is in `previousList` it means that the lists got merged.\n\t\t\t\t\t// In this case, we need to fix insert position.\n\t\t\t\t\tif ( mergePos && mergePos.parent == previousList ) {\n\t\t\t\t\t\tviewPosition.offset--;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Merge last inserted list with element after it.\n\t\t\tmergeViewLists( viewWriter, viewPosition.nodeBefore, viewPosition.nodeAfter );\n\t\t}\n\t}\n}\n\n/**\n * A special model-to-view converter introduced by the {@link module:list/list~List list feature}. This converter takes care of\n * merging view lists after something is removed or moved from near them.\n *\n * Example:\n *\n *\t\t// Model: // View:\n *\t\tfoo
                • foo
                \n *\t\txxx

                xxx

                \n *\t\tbar
                • bar
                \n *\n *\t\t// After change: // Correct view guaranteed by this converter:\n *\t\tfoo
                  \n *\t\tbar
                • foo
                • \n *\t\t
                • bar
                • \n *\t\t
                \n *\n * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:remove\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.\n */\nexport function modelViewMergeAfter( evt, data, conversionApi ) {\n\tconst viewPosition = conversionApi.mapper.toViewPosition( data.position );\n\tconst viewItemPrev = viewPosition.nodeBefore;\n\tconst viewItemNext = viewPosition.nodeAfter;\n\n\t// Merge lists if something (remove, move) was done from inside of list.\n\t// Merging will be done only if both items are view lists of the same type.\n\t// The check is done inside the helper function.\n\tmergeViewLists( conversionApi.writer, viewItemPrev, viewItemNext );\n}\n\n/**\n * A view-to-model converter that converts the `
              2. ` view elements into the `listItem` model elements.\n *\n * To set correct values of the `listType` and `listIndent` attributes the converter:\n * * checks `
              3. `'s parent,\n * * stores and increases the `conversionApi.store.indent` value when `
              4. `'s sub-items are converted.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function viewModelConverter( evt, data, conversionApi ) {\n\tif ( conversionApi.consumable.consume( data.viewItem, { name: true } ) ) {\n\t\tconst writer = conversionApi.writer;\n\n\t\t// 1. Create `listItem` model element.\n\t\tconst listItem = writer.createElement( 'listItem' );\n\n\t\t// 2. Handle `listItem` model element attributes.\n\t\tconst indent = getIndent( data.viewItem );\n\n\t\twriter.setAttribute( 'listIndent', indent, listItem );\n\n\t\t// Set 'bulleted' as default. If this item is pasted into a context,\n\t\tconst type = data.viewItem.parent && data.viewItem.parent.name == 'ol' ? 'numbered' : 'bulleted';\n\t\twriter.setAttribute( 'listType', type, listItem );\n\n\t\tif ( !conversionApi.safeInsert( listItem, data.modelCursor ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst nextPosition = viewToModelListItemChildrenConverter( listItem, data.viewItem.getChildren(), conversionApi );\n\n\t\t// Result range starts before the first item and ends after the last.\n\t\tdata.modelRange = writer.createRange( data.modelCursor, nextPosition );\n\n\t\tconversionApi.updateConversionResult( listItem, data );\n\t}\n}\n\n/**\n * A view-to-model converter for the `
                  ` and `
                    ` view elements that cleans the input view of garbage.\n * This is mostly to clean whitespaces from between the `
                  1. ` view elements inside the view list element, however, also\n * incorrect data can be cleared if the view was incorrect.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function cleanList( evt, data, conversionApi ) {\n\tif ( conversionApi.consumable.test( data.viewItem, { name: true } ) ) {\n\t\t// Caching children because when we start removing them iterating fails.\n\t\tconst children = Array.from( data.viewItem.getChildren() );\n\n\t\tfor ( const child of children ) {\n\t\t\tconst isWrongElement = !( child.is( 'element', 'li' ) || isList( child ) );\n\n\t\t\tif ( isWrongElement ) {\n\t\t\t\tchild._remove();\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * A view-to-model converter for the `
                  2. ` elements that cleans whitespace formatting from the input view.\n *\n * @see module:engine/conversion/upcastdispatcher~UpcastDispatcher#event:element\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n */\nexport function cleanListItem( evt, data, conversionApi ) {\n\tif ( conversionApi.consumable.test( data.viewItem, { name: true } ) ) {\n\t\tif ( data.viewItem.childCount === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst children = [ ...data.viewItem.getChildren() ];\n\n\t\tlet foundList = false;\n\t\tlet firstNode = true;\n\n\t\tfor ( const child of children ) {\n\t\t\tif ( foundList && !isList( child ) ) {\n\t\t\t\tchild._remove();\n\t\t\t}\n\n\t\t\tif ( child.is( '$text' ) ) {\n\t\t\t\t// If this is the first node and it's a text node, left-trim it.\n\t\t\t\tif ( firstNode ) {\n\t\t\t\t\tchild._data = child.data.replace( /^\\s+/, '' );\n\t\t\t\t}\n\n\t\t\t\t// If this is the last text node before
                      or
                        , right-trim it.\n\t\t\t\tif ( !child.nextSibling || isList( child.nextSibling ) ) {\n\t\t\t\t\tchild._data = child.data.replace( /\\s+$/, '' );\n\t\t\t\t}\n\t\t\t} else if ( isList( child ) ) {\n\t\t\t\t// If this is a
                          or
                            , do not process it, just mark that we already visited list element.\n\t\t\t\tfoundList = true;\n\t\t\t}\n\n\t\t\tfirstNode = false;\n\t\t}\n\t}\n}\n\n/**\n * Returns a callback for model position to view position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes\n * positions between the `listItem` elements that would be incorrectly mapped because of how list items are represented in the model\n * and in the view.\n *\n * @see module:engine/conversion/mapper~Mapper#event:modelToViewPosition\n * @param {module:engine/view/view~View} view A view instance.\n * @returns {Function}\n */\nexport function modelToViewPosition( view ) {\n\treturn ( evt, data ) => {\n\t\tif ( data.isPhantom ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelItem = data.modelPosition.nodeBefore;\n\n\t\tif ( modelItem && modelItem.is( 'element', 'listItem' ) ) {\n\t\t\tconst viewItem = data.mapper.toViewElement( modelItem );\n\t\t\tconst topmostViewList = viewItem.getAncestors().find( isList );\n\t\t\tconst walker = view.createPositionAt( viewItem, 0 ).getWalker();\n\n\t\t\tfor ( const value of walker ) {\n\t\t\t\tif ( value.type == 'elementStart' && value.item.is( 'element', 'li' ) ) {\n\t\t\t\t\tdata.viewPosition = value.previousPosition;\n\n\t\t\t\t\tbreak;\n\t\t\t\t} else if ( value.type == 'elementEnd' && value.item == topmostViewList ) {\n\t\t\t\t\tdata.viewPosition = value.nextPosition;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * The callback for view position to model position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes\n * positions between the `
                          1. ` elements that would be incorrectly mapped because of how list items are represented in the model\n * and in the view.\n *\n * @see module:engine/conversion/mapper~Mapper#event:viewToModelPosition\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {Function} Returns a conversion callback.\n */\nexport function viewToModelPosition( model ) {\n\treturn ( evt, data ) => {\n\t\tconst viewPos = data.viewPosition;\n\t\tconst viewParent = viewPos.parent;\n\t\tconst mapper = data.mapper;\n\n\t\tif ( viewParent.name == 'ul' || viewParent.name == 'ol' ) {\n\t\t\t// Position is directly in
                              or
                                .\n\t\t\tif ( !viewPos.isAtEnd ) {\n\t\t\t\t// If position is not at the end, it must be before
                              1. .\n\t\t\t\t// Get that
                              2. , map it to `listItem` and set model position before that `listItem`.\n\t\t\t\tconst modelNode = mapper.toModelElement( viewPos.nodeAfter );\n\n\t\t\t\tdata.modelPosition = model.createPositionBefore( modelNode );\n\t\t\t} else {\n\t\t\t\t// Position is at the end of
                                  or
                                    , so there is no
                                  1. after it to be mapped.\n\t\t\t\t// There is
                                  2. before the position, but we cannot just map it to `listItem` and set model position after it,\n\t\t\t\t// because that
                                  3. may contain nested items.\n\t\t\t\t// We will check \"model length\" of that
                                  4. , in other words - how many `listItem`s are in that
                                  5. .\n\t\t\t\tconst modelNode = mapper.toModelElement( viewPos.nodeBefore );\n\t\t\t\tconst modelLength = mapper.getModelLength( viewPos.nodeBefore );\n\n\t\t\t\t// Then we get model position before mapped `listItem` and shift it accordingly.\n\t\t\t\tdata.modelPosition = model.createPositionBefore( modelNode ).getShiftedBy( modelLength );\n\t\t\t}\n\n\t\t\tevt.stop();\n\t\t} else if (\n\t\t\tviewParent.name == 'li' &&\n\t\t\tviewPos.nodeBefore &&\n\t\t\t( viewPos.nodeBefore.name == 'ul' || viewPos.nodeBefore.name == 'ol' )\n\t\t) {\n\t\t\t// In most cases when view position is in
                                  6. it is in text and this is a correct position.\n\t\t\t// However, if position is after
                                      or
                                        we have to fix it -- because in model
                                          /
                                            are not in the `listItem`.\n\t\t\tconst modelNode = mapper.toModelElement( viewParent );\n\n\t\t\t// Check all
                                              s and
                                                s that are in the
                                              1. but before mapped position.\n\t\t\t// Get model length of those elements and then add it to the offset of `listItem` mapped to the original
                                              2. .\n\t\t\tlet modelLength = 1; // Starts from 1 because the original
                                              3. has to be counted in too.\n\t\t\tlet viewList = viewPos.nodeBefore;\n\n\t\t\twhile ( viewList && isList( viewList ) ) {\n\t\t\t\tmodelLength += mapper.getModelLength( viewList );\n\n\t\t\t\tviewList = viewList.previousSibling;\n\t\t\t}\n\n\t\t\tdata.modelPosition = model.createPositionBefore( modelNode ).getShiftedBy( modelLength );\n\n\t\t\tevt.stop();\n\t\t}\n\t};\n}\n\n/**\n * Post-fixer that reacts to changes on document and fixes incorrect model states.\n *\n * In the example below, there is a correct list structure.\n * Then the middle element is removed so the list structure will become incorrect:\n *\n *\t\tItem 1\n *\t\tItem 2 <--- this is removed.\n *\t\tItem 3\n *\n * The list structure after the middle element is removed:\n *\n * \t\tItem 1\n *\t\tItem 3\n *\n * Should become:\n *\n *\t\tItem 1\n *\t\tItem 3 <--- note that indent got post-fixed.\n *\n * @param {module:engine/model/model~Model} model The data model.\n * @param {module:engine/model/writer~Writer} writer The writer to do changes with.\n * @returns {Boolean} `true` if any change has been applied, `false` otherwise.\n */\nexport function modelChangePostFixer( model, writer ) {\n\tconst changes = model.document.differ.getChanges();\n\tconst itemToListHead = new Map();\n\n\tlet applied = false;\n\n\tfor ( const entry of changes ) {\n\t\tif ( entry.type == 'insert' && entry.name == 'listItem' ) {\n\t\t\t_addListToFix( entry.position );\n\t\t} else if ( entry.type == 'insert' && entry.name != 'listItem' ) {\n\t\t\tif ( entry.name != '$text' ) {\n\t\t\t\t// In case of renamed element.\n\t\t\t\tconst item = entry.position.nodeAfter;\n\n\t\t\t\tif ( item.hasAttribute( 'listIndent' ) ) {\n\t\t\t\t\twriter.removeAttribute( 'listIndent', item );\n\n\t\t\t\t\tapplied = true;\n\t\t\t\t}\n\n\t\t\t\tif ( item.hasAttribute( 'listType' ) ) {\n\t\t\t\t\twriter.removeAttribute( 'listType', item );\n\n\t\t\t\t\tapplied = true;\n\t\t\t\t}\n\n\t\t\t\tif ( item.hasAttribute( 'listStyle' ) ) {\n\t\t\t\t\twriter.removeAttribute( 'listStyle', item );\n\n\t\t\t\t\tapplied = true;\n\t\t\t\t}\n\n\t\t\t\tfor ( const innerItem of Array.from( model.createRangeIn( item ) ).filter( e => e.item.is( 'element', 'listItem' ) ) ) {\n\t\t\t\t\t_addListToFix( innerItem.previousPosition );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst posAfter = entry.position.getShiftedBy( entry.length );\n\n\t\t\t_addListToFix( posAfter );\n\t\t} else if ( entry.type == 'remove' && entry.name == 'listItem' ) {\n\t\t\t_addListToFix( entry.position );\n\t\t} else if ( entry.type == 'attribute' && entry.attributeKey == 'listIndent' ) {\n\t\t\t_addListToFix( entry.range.start );\n\t\t} else if ( entry.type == 'attribute' && entry.attributeKey == 'listType' ) {\n\t\t\t_addListToFix( entry.range.start );\n\t\t}\n\t}\n\n\tfor ( const listHead of itemToListHead.values() ) {\n\t\t_fixListIndents( listHead );\n\t\t_fixListTypes( listHead );\n\t}\n\n\treturn applied;\n\n\tfunction _addListToFix( position ) {\n\t\tconst previousNode = position.nodeBefore;\n\n\t\tif ( !previousNode || !previousNode.is( 'element', 'listItem' ) ) {\n\t\t\tconst item = position.nodeAfter;\n\n\t\t\tif ( item && item.is( 'element', 'listItem' ) ) {\n\t\t\t\titemToListHead.set( item, item );\n\t\t\t}\n\t\t} else {\n\t\t\tlet listHead = previousNode;\n\n\t\t\tif ( itemToListHead.has( listHead ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (\n\t\t\t\t// Cache previousSibling and reuse for performance reasons. See #6581.\n\t\t\t\tlet previousSibling = listHead.previousSibling;\n\t\t\t\tpreviousSibling && previousSibling.is( 'element', 'listItem' );\n\t\t\t\tpreviousSibling = listHead.previousSibling\n\t\t\t) {\n\t\t\t\tlistHead = previousSibling;\n\n\t\t\t\tif ( itemToListHead.has( listHead ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\titemToListHead.set( previousNode, listHead );\n\t\t}\n\t}\n\n\tfunction _fixListIndents( item ) {\n\t\tlet maxIndent = 0;\n\t\tlet fixBy = null;\n\n\t\twhile ( item && item.is( 'element', 'listItem' ) ) {\n\t\t\tconst itemIndent = item.getAttribute( 'listIndent' );\n\n\t\t\tif ( itemIndent > maxIndent ) {\n\t\t\t\tlet newIndent;\n\n\t\t\t\tif ( fixBy === null ) {\n\t\t\t\t\tfixBy = itemIndent - maxIndent;\n\t\t\t\t\tnewIndent = maxIndent;\n\t\t\t\t} else {\n\t\t\t\t\tif ( fixBy > itemIndent ) {\n\t\t\t\t\t\tfixBy = itemIndent;\n\t\t\t\t\t}\n\n\t\t\t\t\tnewIndent = itemIndent - fixBy;\n\t\t\t\t}\n\n\t\t\t\twriter.setAttribute( 'listIndent', newIndent, item );\n\n\t\t\t\tapplied = true;\n\t\t\t} else {\n\t\t\t\tfixBy = null;\n\t\t\t\tmaxIndent = item.getAttribute( 'listIndent' ) + 1;\n\t\t\t}\n\n\t\t\titem = item.nextSibling;\n\t\t}\n\t}\n\n\tfunction _fixListTypes( item ) {\n\t\tlet typesStack = [];\n\t\tlet prev = null;\n\n\t\twhile ( item && item.is( 'element', 'listItem' ) ) {\n\t\t\tconst itemIndent = item.getAttribute( 'listIndent' );\n\n\t\t\tif ( prev && prev.getAttribute( 'listIndent' ) > itemIndent ) {\n\t\t\t\ttypesStack = typesStack.slice( 0, itemIndent + 1 );\n\t\t\t}\n\n\t\t\tif ( itemIndent != 0 ) {\n\t\t\t\tif ( typesStack[ itemIndent ] ) {\n\t\t\t\t\tconst type = typesStack[ itemIndent ];\n\n\t\t\t\t\tif ( item.getAttribute( 'listType' ) != type ) {\n\t\t\t\t\t\twriter.setAttribute( 'listType', type, item );\n\n\t\t\t\t\t\tapplied = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttypesStack[ itemIndent ] = item.getAttribute( 'listType' );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprev = item;\n\t\t\titem = item.nextSibling;\n\t\t}\n\t}\n}\n\n/**\n * A fixer for pasted content that includes list items.\n *\n * It fixes indentation of pasted list items so the pasted items match correctly to the context they are pasted into.\n *\n * Example:\n *\n *\t\tA\n *\t\tB^\n *\t\t// At ^ paste: X\n *\t\t// Y\n *\t\tC\n *\n * Should become:\n *\n *\t\tA\n *\t\tBX\n *\t\tY/listItem>\n *\t\tC\n *\n * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.\n * @param {Array} args Arguments of {@link module:engine/model/model~Model#insertContent}.\n */\nexport function modelIndentPasteFixer( evt, [ content, selectable ] ) {\n\t// Check whether inserted content starts from a `listItem`. If it does not, it means that there are some other\n\t// elements before it and there is no need to fix indents, because even if we insert that content into a list,\n\t// that list will be broken.\n\t// Note: we also need to handle singular elements because inserting item with indent 0 into 0,1,[],2\n\t// would create incorrect model.\n\tlet item = content.is( 'documentFragment' ) ? content.getChild( 0 ) : content;\n\n\tlet selection;\n\n\tif ( !selectable ) {\n\t\tselection = this.document.selection;\n\t} else {\n\t\tselection = this.createSelection( selectable );\n\t}\n\n\tif ( item && item.is( 'element', 'listItem' ) ) {\n\t\t// Get a reference list item. Inserted list items will be fixed according to that item.\n\t\tconst pos = selection.getFirstPosition();\n\t\tlet refItem = null;\n\n\t\tif ( pos.parent.is( 'element', 'listItem' ) ) {\n\t\t\trefItem = pos.parent;\n\t\t} else if ( pos.nodeBefore && pos.nodeBefore.is( 'element', 'listItem' ) ) {\n\t\t\trefItem = pos.nodeBefore;\n\t\t}\n\n\t\t// If there is `refItem` it means that we do insert list items into an existing list.\n\t\tif ( refItem ) {\n\t\t\t// First list item in `data` has indent equal to 0 (it is a first list item). It should have indent equal\n\t\t\t// to the indent of reference item. We have to fix the first item and all of it's children and following siblings.\n\t\t\t// Indent of all those items has to be adjusted to reference item.\n\t\t\tconst indentChange = refItem.getAttribute( 'listIndent' );\n\n\t\t\t// Fix only if there is anything to fix.\n\t\t\tif ( indentChange > 0 ) {\n\t\t\t\t// Adjust indent of all \"first\" list items in inserted data.\n\t\t\t\twhile ( item && item.is( 'element', 'listItem' ) ) {\n\t\t\t\t\titem._setAttribute( 'listIndent', item.getAttribute( 'listIndent' ) + indentChange );\n\n\t\t\t\t\titem = item.nextSibling;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Helper function that converts children of a given `
                                              4. ` view element into corresponding model elements.\n// The function maintains proper order of elements if model `listItem` is split during the conversion\n// due to block children conversion.\n//\n// @param {module:engine/model/element~Element} listItemModel List item model element to which converted children will be inserted.\n// @param {Iterable.} viewChildren View elements which will be converted.\n// @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface to be used by the callback.\n// @returns {module:engine/model/position~Position} Position on which next elements should be inserted after children conversion.\nfunction viewToModelListItemChildrenConverter( listItemModel, viewChildren, conversionApi ) {\n\tconst { writer, schema } = conversionApi;\n\n\t// A position after the last inserted `listItem`.\n\tlet nextPosition = writer.createPositionAfter( listItemModel );\n\n\t// Check all children of the converted `
                                              5. `. At this point we assume there are no \"whitespace\" view text nodes\n\t// in view list, between view list items. This should be handled by `
                                                  ` and `
                                                    ` converters.\n\tfor ( const child of viewChildren ) {\n\t\tif ( child.name == 'ul' || child.name == 'ol' ) {\n\t\t\t// If the children is a list, we will insert its conversion result after currently handled `listItem`.\n\t\t\t// Then, next insertion position will be set after all the new list items (and maybe other elements if\n\t\t\t// something split list item).\n\t\t\t//\n\t\t\t// If this is a list, we expect that some `listItem`s and possibly other blocks will be inserted, however `.modelCursor`\n\t\t\t// should be set after last `listItem` (or block). This is why it feels safe to use it as `nextPosition`\n\t\t\tnextPosition = conversionApi.convertItem( child, nextPosition ).modelCursor;\n\t\t} else {\n\t\t\t// If this is not a list, try inserting content at the end of the currently handled `listItem`.\n\t\t\tconst result = conversionApi.convertItem( child, writer.createPositionAt( listItemModel, 'end' ) );\n\n\t\t\t// It may end up that the current `listItem` becomes split (if that content cannot be inside `listItem`). For example:\n\t\t\t//\n\t\t\t//
                                                  1. Foo

                                                  2. \n\t\t\t//\n\t\t\t// will be converted to:\n\t\t\t//\n\t\t\t// Foo\n\t\t\t//\n\t\t\tconst convertedChild = result.modelRange.start.nodeAfter;\n\t\t\tconst wasSplit = convertedChild && convertedChild.is( 'element' ) && !schema.checkChild( listItemModel, convertedChild.name );\n\n\t\t\tif ( wasSplit ) {\n\t\t\t\t// As `lastListItem` got split, we need to update it to the second part of the split `listItem` element.\n\t\t\t\t//\n\t\t\t\t// `modelCursor` should be set to a position where the conversion should continue. There are multiple possible scenarios\n\t\t\t\t// that may happen. Usually, `modelCursor` (marked as `#` below) would point to the second list item after conversion:\n\t\t\t\t//\n\t\t\t\t//\t\t`
                                                  3. Foo

                                                  4. ` -> `Foo#`\n\t\t\t\t//\n\t\t\t\t// However, in some cases, like auto-paragraphing, the position is placed at the end of the block element:\n\t\t\t\t//\n\t\t\t\t//\t\t`
                                                  5. Foo
                                                  6. ` -> `Foo#`\n\t\t\t\t//\n\t\t\t\t// or after an element if another element broken auto-paragraphed element:\n\t\t\t\t//\n\t\t\t\t//\t\t`
                                                  7. Foo

                                                  8. ` -> `Foo#`\n\t\t\t\t//\n\t\t\t\t// We need to check for such cases and use proper list item and position based on it.\n\t\t\t\t//\n\t\t\t\tif ( result.modelCursor.parent.is( 'element', 'listItem' ) ) {\n\t\t\t\t\t// (1).\n\t\t\t\t\tlistItemModel = result.modelCursor.parent;\n\t\t\t\t} else {\n\t\t\t\t\t// (2), (3).\n\t\t\t\t\tlistItemModel = findNextListItem( result.modelCursor );\n\t\t\t\t}\n\n\t\t\t\tnextPosition = writer.createPositionAfter( listItemModel );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nextPosition;\n}\n\n// Helper function that seeks for a next list item starting from given `startPosition`.\nfunction findNextListItem( startPosition ) {\n\tconst treeWalker = new TreeWalker( { startPosition } );\n\n\tlet value;\n\n\tdo {\n\t\tvalue = treeWalker.next();\n\t} while ( !value.value.item.is( 'element', 'listItem' ) );\n\n\treturn value.value.item;\n}\n\n// Helper function that takes all children of given `viewRemovedItem` and moves them in a correct place, according\n// to other given parameters.\nfunction hoistNestedLists( nextIndent, modelRemoveStartPosition, viewRemoveStartPosition, viewRemovedItem, conversionApi, model ) {\n\t// Find correct previous model list item element.\n\t// The element has to have either same or smaller indent than given reference indent.\n\t// This will be the model element which will get nested items (if it has smaller indent) or sibling items (if it has same indent).\n\t// Keep in mind that such element might not be found, if removed item was the first item.\n\tconst prevModelItem = getSiblingListItem( modelRemoveStartPosition.nodeBefore, {\n\t\tsameIndent: true,\n\t\tsmallerIndent: true,\n\t\tlistIndent: nextIndent,\n\t\tfoo: 'b'\n\t} );\n\n\tconst mapper = conversionApi.mapper;\n\tconst viewWriter = conversionApi.writer;\n\n\t// Indent of found element or `null` if the element has not been found.\n\tconst prevIndent = prevModelItem ? prevModelItem.getAttribute( 'listIndent' ) : null;\n\n\tlet insertPosition;\n\n\tif ( !prevModelItem ) {\n\t\t// If element has not been found, simply insert lists at the position where the removed item was:\n\t\t//\n\t\t// Lorem ipsum.\n\t\t// 1 -------- <--- this is removed, no previous list item, put nested items in place of removed item.\n\t\t// 1.1 -------- <--- this is reference indent.\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\t//\n\t\t// Becomes:\n\t\t//\n\t\t// Lorem ipsum.\n\t\t// 1.1 --------\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\tinsertPosition = viewRemoveStartPosition;\n\t} else if ( prevIndent == nextIndent ) {\n\t\t// If element has been found and has same indent as reference indent it means that nested items should\n\t\t// become siblings of found element:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.2 -------- <--- this is `prevModelItem`.\n\t\t// 2 -------- <--- this is removed, previous list item has indent same as reference indent.\n\t\t// 2.1 -------- <--- this is reference indent, this and 2.2 should become siblings of 1.2.\n\t\t// 2.2 --------\n\t\t//\n\t\t// Becomes:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1 --------\n\t\t// 1.2 --------\n\t\t// 2.1 --------\n\t\t// 2.2 --------\n\t\tconst prevViewList = mapper.toViewElement( prevModelItem ).parent;\n\t\tinsertPosition = viewWriter.createPositionAfter( prevViewList );\n\t} else {\n\t\t// If element has been found and has smaller indent as reference indent it means that nested items\n\t\t// should become nested items of found item:\n\t\t//\n\t\t// 1 -------- <--- this is `prevModelItem`.\n\t\t// 1.1 -------- <--- this is removed, previous list item has indent smaller than reference indent.\n\t\t// 1.1.1 -------- <--- this is reference indent, this and 1.1.1 should become nested items of 1.\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\t//\n\t\t// Becomes:\n\t\t//\n\t\t// 1 --------\n\t\t// 1.1.1 --------\n\t\t// 1.1.2 --------\n\t\t// 1.2 --------\n\t\t//\n\t\t// Note: in this case 1.1.1 have indent 2 while 1 have indent 0. In model that should not be possible,\n\t\t// because following item may have indent bigger only by one. But this is fixed by postfixer.\n\t\tconst modelPosition = model.createPositionAt( prevModelItem, 'end' );\n\t\tinsertPosition = mapper.toViewPosition( modelPosition );\n\t}\n\n\tinsertPosition = positionAfterUiElements( insertPosition );\n\n\t// Handle multiple lists. This happens if list item has nested numbered and bulleted lists. Following lists\n\t// are inserted after the first list (no need to recalculate insertion position for them).\n\tfor ( const child of [ ...viewRemovedItem.getChildren() ] ) {\n\t\tif ( isList( child ) ) {\n\t\t\tinsertPosition = viewWriter.move( viewWriter.createRangeOn( child ), insertPosition ).end;\n\n\t\t\tmergeViewLists( viewWriter, child, child.nextSibling );\n\t\t\tmergeViewLists( viewWriter, child.previousSibling, child );\n\t\t}\n\t}\n}\n\n// Checks if view element is a list type (ul or ol).\n//\n// @param {module:engine/view/element~Element} viewElement\n// @returns {Boolean}\nfunction isList( viewElement ) {\n\treturn viewElement.is( 'element', 'ol' ) || viewElement.is( 'element', 'ul' );\n}\n\n// Calculates the indent value for a list item. Handles HTML compliant and non-compliant lists.\n//\n// Also, fixes non HTML compliant lists indents:\n//\n//\t\tbefore: fixed list:\n//\t\tOL OL\n//\t\t|-> LI (parent LIs: 0) |-> LI (indent: 0)\n//\t\t |-> OL |-> OL\n//\t\t |-> OL |\n//\t\t | |-> OL |\n//\t\t | |-> OL |\n//\t\t | |-> LI (parent LIs: 1) |-> LI (indent: 1)\n//\t\t |-> LI (parent LIs: 1) |-> LI (indent: 1)\n//\n//\t\tbefore: fixed list:\n//\t\tOL OL\n//\t\t|-> OL |\n//\t\t |-> OL |\n//\t\t |-> OL |\n//\t\t |-> LI (parent LIs: 0) |-> LI (indent: 0)\n//\n//\t\tbefore: fixed list:\n//\t\tOL OL\n//\t\t|-> LI (parent LIs: 0) |-> LI (indent: 0)\n//\t\t|-> OL |-> OL\n//\t\t |-> LI (parent LIs: 0) |-> LI (indent: 1)\n//\n// @param {module:engine/view/element~Element} listItem\n// @param {Object} conversionStore\n// @returns {Number}\nfunction getIndent( listItem ) {\n\tlet indent = 0;\n\n\tlet parent = listItem.parent;\n\n\twhile ( parent ) {\n\t\t// Each LI in the tree will result in an increased indent for HTML compliant lists.\n\t\tif ( parent.is( 'element', 'li' ) ) {\n\t\t\tindent++;\n\t\t} else {\n\t\t\t// If however the list is nested in other list we should check previous sibling of any of the list elements...\n\t\t\tconst previousSibling = parent.previousSibling;\n\n\t\t\t// ...because the we might need increase its indent:\n\t\t\t//\t\tbefore: fixed list:\n\t\t\t//\t\tOL OL\n\t\t\t//\t\t|-> LI (parent LIs: 0) |-> LI (indent: 0)\n\t\t\t//\t\t|-> OL |-> OL\n\t\t\t//\t\t |-> LI (parent LIs: 0) |-> LI (indent: 1)\n\t\t\tif ( previousSibling && previousSibling.is( 'element', 'li' ) ) {\n\t\t\t\tindent++;\n\t\t\t}\n\t\t}\n\n\t\tparent = parent.parent;\n\t}\n\n\treturn indent;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/listediting\n */\n\nimport ListCommand from './listcommand';\nimport IndentCommand from './indentcommand';\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport { priorities } from 'ckeditor5/src/utils';\n\nimport {\n\tcleanList,\n\tcleanListItem,\n\tmodelViewInsertion,\n\tmodelViewChangeType,\n\tmodelViewMergeAfterChangeType,\n\tmodelViewMergeAfter,\n\tmodelViewRemove,\n\tmodelViewSplitOnInsert,\n\tmodelViewChangeIndent,\n\tmodelChangePostFixer,\n\tmodelIndentPasteFixer,\n\tviewModelConverter,\n\tmodelToViewPosition,\n\tviewToModelPosition\n} from './converters';\n\n/**\n * The engine of the list feature. It handles creating, editing and removing lists and list items.\n *\n * It registers the `'numberedList'`, `'bulletedList'`, `'indentList'` and `'outdentList'` commands.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class ListEditing extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'ListEditing';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Schema.\n\t\t// Note: in case `$block` will ever be allowed in `listItem`, keep in mind that this feature\n\t\t// uses `Selection#getSelectedBlocks()` without any additional processing to obtain all selected list items.\n\t\t// If there are blocks allowed inside list item, algorithms using `getSelectedBlocks()` will have to be modified.\n\t\teditor.model.schema.register( 'listItem', {\n\t\t\tinheritAllFrom: '$block',\n\t\t\tallowAttributes: [ 'listType', 'listIndent' ]\n\t\t} );\n\n\t\t// Converters.\n\t\tconst data = editor.data;\n\t\tconst editing = editor.editing;\n\n\t\teditor.model.document.registerPostFixer( writer => modelChangePostFixer( editor.model, writer ) );\n\n\t\tediting.mapper.registerViewToModelLength( 'li', getViewListItemLength );\n\t\tdata.mapper.registerViewToModelLength( 'li', getViewListItemLength );\n\n\t\tediting.mapper.on( 'modelToViewPosition', modelToViewPosition( editing.view ) );\n\t\tediting.mapper.on( 'viewToModelPosition', viewToModelPosition( editor.model ) );\n\t\tdata.mapper.on( 'modelToViewPosition', modelToViewPosition( editing.view ) );\n\n\t\teditor.conversion.for( 'editingDowncast' )\n\t\t\t.add( dispatcher => {\n\t\t\t\tdispatcher.on( 'insert', modelViewSplitOnInsert, { priority: 'high' } );\n\t\t\t\tdispatcher.on( 'insert:listItem', modelViewInsertion( editor.model ) );\n\t\t\t\tdispatcher.on( 'attribute:listType:listItem', modelViewChangeType, { priority: 'high' } );\n\t\t\t\tdispatcher.on( 'attribute:listType:listItem', modelViewMergeAfterChangeType, { priority: 'low' } );\n\t\t\t\tdispatcher.on( 'attribute:listIndent:listItem', modelViewChangeIndent( editor.model ) );\n\t\t\t\tdispatcher.on( 'remove:listItem', modelViewRemove( editor.model ) );\n\t\t\t\tdispatcher.on( 'remove', modelViewMergeAfter, { priority: 'low' } );\n\t\t\t} );\n\n\t\teditor.conversion.for( 'dataDowncast' )\n\t\t\t.add( dispatcher => {\n\t\t\t\tdispatcher.on( 'insert', modelViewSplitOnInsert, { priority: 'high' } );\n\t\t\t\tdispatcher.on( 'insert:listItem', modelViewInsertion( editor.model ) );\n\t\t\t} );\n\n\t\teditor.conversion.for( 'upcast' )\n\t\t\t.add( dispatcher => {\n\t\t\t\tdispatcher.on( 'element:ul', cleanList, { priority: 'high' } );\n\t\t\t\tdispatcher.on( 'element:ol', cleanList, { priority: 'high' } );\n\t\t\t\tdispatcher.on( 'element:li', cleanListItem, { priority: 'high' } );\n\t\t\t\tdispatcher.on( 'element:li', viewModelConverter );\n\t\t\t} );\n\n\t\t// Fix indentation of pasted items.\n\t\teditor.model.on( 'insertContent', modelIndentPasteFixer, { priority: 'high' } );\n\n\t\t// Register commands for numbered and bulleted list.\n\t\teditor.commands.add( 'numberedList', new ListCommand( editor, 'numbered' ) );\n\t\teditor.commands.add( 'bulletedList', new ListCommand( editor, 'bulleted' ) );\n\n\t\t// Register commands for indenting.\n\t\teditor.commands.add( 'indentList', new IndentCommand( editor, 'forward' ) );\n\t\teditor.commands.add( 'outdentList', new IndentCommand( editor, 'backward' ) );\n\n\t\tconst viewDocument = editing.view.document;\n\n\t\t// Overwrite default Enter key behavior.\n\t\t// If Enter key is pressed with selection collapsed in empty list item, outdent it instead of breaking it.\n\t\tthis.listenTo( viewDocument, 'enter', ( evt, data ) => {\n\t\t\tconst doc = this.editor.model.document;\n\t\t\tconst positionParent = doc.selection.getLastPosition().parent;\n\n\t\t\tif ( doc.selection.isCollapsed && positionParent.name == 'listItem' && positionParent.isEmpty ) {\n\t\t\t\tthis.editor.execute( 'outdentList' );\n\n\t\t\t\tdata.preventDefault();\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t} );\n\n\t\t// Overwrite default Backspace key behavior.\n\t\t// If Backspace key is pressed with selection collapsed on first position in first list item, outdent it. #83\n\t\t//\n\t\t// Priority high + 10 to override widget and blockquote feature listener.\n\t\tthis.listenTo( viewDocument, 'delete', ( evt, data ) => {\n\t\t\t// Check conditions from those that require less computations like those immediately available.\n\t\t\tif ( data.direction !== 'backward' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst selection = this.editor.model.document.selection;\n\n\t\t\tif ( !selection.isCollapsed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst firstPosition = selection.getFirstPosition();\n\n\t\t\tif ( !firstPosition.isAtStart ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst positionParent = firstPosition.parent;\n\n\t\t\tif ( positionParent.name !== 'listItem' ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst previousIsAListItem = positionParent.previousSibling && positionParent.previousSibling.name === 'listItem';\n\n\t\t\tif ( previousIsAListItem ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.editor.execute( 'outdentList' );\n\n\t\t\tdata.preventDefault();\n\t\t\tevt.stop();\n\t\t}, { priority: priorities.high + 10 } );\n\n\t\tconst getCommandExecuter = commandName => {\n\t\t\treturn ( data, cancel ) => {\n\t\t\t\tconst command = this.editor.commands.get( commandName );\n\n\t\t\t\tif ( command.isEnabled ) {\n\t\t\t\t\tthis.editor.execute( commandName );\n\t\t\t\t\tcancel();\n\t\t\t\t}\n\t\t\t};\n\t\t};\n\n\t\teditor.keystrokes.set( 'Tab', getCommandExecuter( 'indentList' ) );\n\t\teditor.keystrokes.set( 'Shift+Tab', getCommandExecuter( 'outdentList' ) );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\tconst commands = this.editor.commands;\n\n\t\tconst indent = commands.get( 'indent' );\n\t\tconst outdent = commands.get( 'outdent' );\n\n\t\tif ( indent ) {\n\t\t\tindent.registerChildCommand( commands.get( 'indentList' ) );\n\t\t}\n\n\t\tif ( outdent ) {\n\t\t\toutdent.registerChildCommand( commands.get( 'outdentList' ) );\n\t\t}\n\t}\n}\n\nfunction getViewListItemLength( element ) {\n\tlet length = 1;\n\n\tfor ( const child of element.getChildren() ) {\n\t\tif ( child.name == 'ul' || child.name == 'ol' ) {\n\t\t\tfor ( const item of child.getChildren() ) {\n\t\t\t\tlength += getViewListItemLength( item );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn length;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module list/utils\n */\n\nimport { TreeWalker, getFillerOffset } from 'ckeditor5/src/engine';\nimport { ButtonView } from 'ckeditor5/src/ui';\n\n/**\n * Creates a list item {@link module:engine/view/containerelement~ContainerElement}.\n *\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer The writer instance.\n * @returns {module:engine/view/containerelement~ContainerElement}\n */\nexport function createViewListItemElement( writer ) {\n\tconst viewItem = writer.createContainerElement( 'li' );\n\n\tviewItem.getFillerOffset = getListItemFillerOffset;\n\n\treturn viewItem;\n}\n\n/**\n * Helper function that creates a `
                                                    ` or (`
                                                      `) structure out of the given `modelItem` model `listItem` element.\n * Then, it binds the created view list item (`
                                                    1. `) with the model `listItem` element.\n * The function then returns the created view list item (`
                                                    2. `).\n *\n * @param {module:engine/model/item~Item} modelItem Model list item.\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface.\n * @returns {module:engine/view/containerelement~ContainerElement} View list element.\n */\nexport function generateLiInUl( modelItem, conversionApi ) {\n\tconst mapper = conversionApi.mapper;\n\tconst viewWriter = conversionApi.writer;\n\tconst listType = modelItem.getAttribute( 'listType' ) == 'numbered' ? 'ol' : 'ul';\n\tconst viewItem = createViewListItemElement( viewWriter );\n\n\tconst viewList = viewWriter.createContainerElement( listType, null );\n\n\tviewWriter.insert( viewWriter.createPositionAt( viewList, 0 ), viewItem );\n\n\tmapper.bindElements( modelItem, viewItem );\n\n\treturn viewItem;\n}\n\n/**\n * Helper function that inserts a view list at a correct place and merges it with its siblings.\n * It takes a model list item element (`modelItem`) and a corresponding view list item element (`injectedItem`). The view list item\n * should be in a view list element (`
                                                        ` or `
                                                          `) and should be its only child.\n * See comments below to better understand the algorithm.\n *\n * @param {module:engine/view/item~Item} modelItem Model list item.\n * @param {module:engine/view/containerelement~ContainerElement} injectedItem\n * @param {module:engine/conversion/upcastdispatcher~UpcastConversionApi} conversionApi Conversion interface.\n * @param {module:engine/model/model~Model} model The model instance.\n */\nexport function injectViewList( modelItem, injectedItem, conversionApi, model ) {\n\tconst injectedList = injectedItem.parent;\n\tconst mapper = conversionApi.mapper;\n\tconst viewWriter = conversionApi.writer;\n\n\t// The position where the view list will be inserted.\n\tlet insertPosition = mapper.toViewPosition( model.createPositionBefore( modelItem ) );\n\n\t// 1. Find the previous list item that has the same or smaller indent. Basically we are looking for the first model item\n\t// that is a \"parent\" or \"sibling\" of the injected model item.\n\t// If there is no such list item, it means that the injected list item is the first item in \"its list\".\n\tconst refItem = getSiblingListItem( modelItem.previousSibling, {\n\t\tsameIndent: true,\n\t\tsmallerIndent: true,\n\t\tlistIndent: modelItem.getAttribute( 'listIndent' )\n\t} );\n\tconst prevItem = modelItem.previousSibling;\n\n\tif ( refItem && refItem.getAttribute( 'listIndent' ) == modelItem.getAttribute( 'listIndent' ) ) {\n\t\t// There is a list item with the same indent - we found the same-level sibling.\n\t\t// Break the list after it. The inserted view item will be added in the broken space.\n\t\tconst viewItem = mapper.toViewElement( refItem );\n\t\tinsertPosition = viewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) );\n\t} else {\n\t\t// There is no list item with the same indent. Check the previous model item.\n\t\tif ( prevItem && prevItem.name == 'listItem' ) {\n\t\t\t// If it is a list item, it has to have a lower indent.\n\t\t\t// It means that the inserted item should be added to it as its nested item.\n\t\t\tinsertPosition = mapper.toViewPosition( model.createPositionAt( prevItem, 'end' ) );\n\n\t\t\t// There could be some not mapped elements (eg. span in to-do list) but we need to insert\n\t\t\t// a nested list directly inside the li element.\n\t\t\tconst mappedViewAncestor = mapper.findMappedViewAncestor( insertPosition );\n\t\t\tconst nestedList = findNestedList( mappedViewAncestor );\n\n\t\t\t// If there already is some nested list, then use it's position.\n\t\t\tif ( nestedList ) {\n\t\t\t\tinsertPosition = viewWriter.createPositionBefore( nestedList );\n\t\t\t} else {\n\t\t\t\t// Else just put new list on the end of list item content.\n\t\t\t\tinsertPosition = viewWriter.createPositionAt( mappedViewAncestor, 'end' );\n\t\t\t}\n\t\t} else {\n\t\t\t// The previous item is not a list item (or does not exist at all).\n\t\t\t// Just map the position and insert the view item at the mapped position.\n\t\t\tinsertPosition = mapper.toViewPosition( model.createPositionBefore( modelItem ) );\n\t\t}\n\t}\n\n\tinsertPosition = positionAfterUiElements( insertPosition );\n\n\t// Insert the view item.\n\tviewWriter.insert( insertPosition, injectedList );\n\n\t// 2. Handle possible children of the injected model item.\n\tif ( prevItem && prevItem.name == 'listItem' ) {\n\t\tconst prevView = mapper.toViewElement( prevItem );\n\n\t\tconst walkerBoundaries = viewWriter.createRange( viewWriter.createPositionAt( prevView, 0 ), insertPosition );\n\t\tconst walker = walkerBoundaries.getWalker( { ignoreElementEnd: true } );\n\n\t\tfor ( const value of walker ) {\n\t\t\tif ( value.item.is( 'element', 'li' ) ) {\n\t\t\t\tconst breakPosition = viewWriter.breakContainer( viewWriter.createPositionBefore( value.item ) );\n\t\t\t\tconst viewList = value.item.parent;\n\n\t\t\t\tconst targetPosition = viewWriter.createPositionAt( injectedItem, 'end' );\n\t\t\t\tmergeViewLists( viewWriter, targetPosition.nodeBefore, targetPosition.nodeAfter );\n\t\t\t\tviewWriter.move( viewWriter.createRangeOn( viewList ), targetPosition );\n\n\t\t\t\twalker.position = breakPosition;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconst nextViewList = injectedList.nextSibling;\n\n\t\tif ( nextViewList && ( nextViewList.is( 'element', 'ul' ) || nextViewList.is( 'element', 'ol' ) ) ) {\n\t\t\tlet lastSubChild = null;\n\n\t\t\tfor ( const child of nextViewList.getChildren() ) {\n\t\t\t\tconst modelChild = mapper.toModelElement( child );\n\n\t\t\t\tif ( modelChild && modelChild.getAttribute( 'listIndent' ) > modelItem.getAttribute( 'listIndent' ) ) {\n\t\t\t\t\tlastSubChild = child;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( lastSubChild ) {\n\t\t\t\tviewWriter.breakContainer( viewWriter.createPositionAfter( lastSubChild ) );\n\t\t\t\tviewWriter.move( viewWriter.createRangeOn( lastSubChild.parent ), viewWriter.createPositionAt( injectedItem, 'end' ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge the inserted view list with its possible neighbor lists.\n\tmergeViewLists( viewWriter, injectedList, injectedList.nextSibling );\n\tmergeViewLists( viewWriter, injectedList.previousSibling, injectedList );\n}\n\n/**\n * Helper function that takes two parameters that are expected to be view list elements, and merges them.\n * The merge happens only if both parameters are list elements of the same type (the same element name and the same class attributes).\n *\n * @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter The writer instance.\n * @param {module:engine/view/item~Item} firstList The first element to compare.\n * @param {module:engine/view/item~Item} secondList The second element to compare.\n * @returns {module:engine/view/position~Position|null} The position after merge or `null` when there was no merge.\n */\nexport function mergeViewLists( viewWriter, firstList, secondList ) {\n\t// Check if two lists are going to be merged.\n\tif ( !firstList || !secondList || ( firstList.name != 'ul' && firstList.name != 'ol' ) ) {\n\t\treturn null;\n\t}\n\n\t// Both parameters are list elements, so compare types now.\n\tif ( firstList.name != secondList.name || firstList.getAttribute( 'class' ) !== secondList.getAttribute( 'class' ) ) {\n\t\treturn null;\n\t}\n\n\treturn viewWriter.mergeContainers( viewWriter.createPositionAfter( firstList ) );\n}\n\n/**\n * Helper function that for a given `view.Position`, returns a `view.Position` that is after all `view.UIElement`s that\n * are after the given position.\n *\n * For example:\n * `foo^bar`\n * For position ^, the position before \"bar\" will be returned.\n *\n * @param {module:engine/view/position~Position} viewPosition\n * @returns {module:engine/view/position~Position}\n */\nexport function positionAfterUiElements( viewPosition ) {\n\treturn viewPosition.getLastMatchingPosition( value => value.item.is( 'uiElement' ) );\n}\n\n/**\n * Helper function that searches for a previous list item sibling of a given model item that meets the given criteria\n * passed by the options object.\n *\n * @param {module:engine/model/item~Item} modelItem\n * @param {Object} options Search criteria.\n * @param {Boolean} [options.sameIndent=false] Whether the sought sibling should have the same indentation.\n * @param {Boolean} [options.smallerIndent=false] Whether the sought sibling should have a smaller indentation.\n * @param {Number} [options.listIndent] The reference indentation.\n * @param {'forward'|'backward'} [options.direction='backward'] Walking direction.\n * @returns {module:engine/model/item~Item|null}\n */\nexport function getSiblingListItem( modelItem, options ) {\n\tconst sameIndent = !!options.sameIndent;\n\tconst smallerIndent = !!options.smallerIndent;\n\tconst indent = options.listIndent;\n\n\tlet item = modelItem;\n\n\twhile ( item && item.name == 'listItem' ) {\n\t\tconst itemIndent = item.getAttribute( 'listIndent' );\n\n\t\tif ( ( sameIndent && indent == itemIndent ) || ( smallerIndent && indent > itemIndent ) ) {\n\t\t\treturn item;\n\t\t}\n\n\t\tif ( options.direction === 'forward' ) {\n\t\t\titem = item.nextSibling;\n\t\t} else {\n\t\t\titem = item.previousSibling;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Helper method for creating a UI button and linking it with an appropriate command.\n *\n * @private\n * @param {module:core/editor/editor~Editor} editor The editor instance to which the UI component will be added.\n * @param {String} commandName The name of the command.\n * @param {Object} label The button label.\n * @param {String} icon The source of the icon.\n */\nexport function createUIComponent( editor, commandName, label, icon ) {\n\teditor.ui.componentFactory.add( commandName, locale => {\n\t\tconst command = editor.commands.get( commandName );\n\t\tconst buttonView = new ButtonView( locale );\n\n\t\tbuttonView.set( {\n\t\t\tlabel,\n\t\t\ticon,\n\t\t\ttooltip: true,\n\t\t\tisToggleable: true\n\t\t} );\n\n\t\t// Bind button model to command.\n\t\tbuttonView.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' );\n\n\t\t// Execute command.\n\t\tbuttonView.on( 'execute', () => {\n\t\t\teditor.execute( commandName );\n\t\t\teditor.editing.view.focus();\n\t\t} );\n\n\t\treturn buttonView;\n\t} );\n}\n\n/**\n * Returns a first list view element that is direct child of the given view element.\n *\n * @param {module:engine/view/element~Element} viewElement\n * @return {module:engine/view/element~Element|null}\n */\nexport function findNestedList( viewElement ) {\n\tfor ( const node of viewElement.getChildren() ) {\n\t\tif ( node.name == 'ul' || node.name == 'ol' ) {\n\t\t\treturn node;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Returns an array with all `listItem` elements that represents the same list.\n *\n * It means that values for `listIndent`, `listType`, and `listStyle` for all items are equal.\n *\n * @param {module:engine/model/position~Position} position Starting position.\n * @param {'forward'|'backward'} direction Walking direction.\n * @returns {Array.}\n */\nexport function getSiblingNodes( position, direction ) {\n\tconst items = [];\n\tconst listItem = position.parent;\n\tconst walkerOptions = {\n\t\tignoreElementEnd: true,\n\t\tstartPosition: position,\n\t\tshallow: true,\n\t\tdirection\n\t};\n\tconst limitIndent = listItem.getAttribute( 'listIndent' );\n\tconst nodes = [ ...new TreeWalker( walkerOptions ) ]\n\t\t.filter( value => value.item.is( 'element' ) )\n\t\t.map( value => value.item );\n\n\tfor ( const element of nodes ) {\n\t\t// If found something else than `listItem`, we're out of the list scope.\n\t\tif ( !element.is( 'element', 'listItem' ) ) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// If current parsed item has lower indent that element that the element that was a starting point,\n\t\t// it means we left a nested list. Abort searching items.\n\t\t//\n\t\t// ■ List item 1. [listIndent=0]\n\t\t// ○ List item 2.[] [listIndent=1], limitIndent = 1,\n\t\t// ○ List item 3. [listIndent=1]\n\t\t// ■ List item 4. [listIndent=0]\n\t\t//\n\t\t// Abort searching when leave nested list.\n\t\tif ( element.getAttribute( 'listIndent' ) < limitIndent ) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// ■ List item 1.[] [listIndent=0] limitIndent = 0,\n\t\t// ○ List item 2. [listIndent=1]\n\t\t// ○ List item 3. [listIndent=1]\n\t\t// ■ List item 4. [listIndent=0]\n\t\t//\n\t\t// Ignore nested lists.\n\t\tif ( element.getAttribute( 'listIndent' ) > limitIndent ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// ■ List item 1.[] [listType=bulleted]\n\t\t// 1. List item 2. [listType=numbered]\n\t\t// 2.List item 3. [listType=numbered]\n\t\t//\n\t\t// Abort searching when found a different kind of a list.\n\t\tif ( element.getAttribute( 'listType' ) !== listItem.getAttribute( 'listType' ) ) {\n\t\t\tbreak;\n\t\t}\n\n\t\t// ■ List item 1.[] [listType=bulleted]\n\t\t// ■ List item 2. [listType=bulleted]\n\t\t// ○ List item 3. [listType=bulleted]\n\t\t// ○ List item 4. [listType=bulleted]\n\t\t//\n\t\t// Abort searching when found a different list style.\n\t\tif ( element.getAttribute( 'listStyle' ) !== listItem.getAttribute( 'listStyle' ) ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif ( direction === 'backward' ) {\n\t\t\titems.unshift( element );\n\t\t} else {\n\t\t\titems.push( element );\n\t\t}\n\t}\n\n\treturn items;\n}\n\n// Implementation of getFillerOffset for view list item element.\n//\n// @returns {Number|null} Block filler offset or `null` if block filler is not needed.\nfunction getListItemFillerOffset() {\n\tconst hasOnlyLists = !this.isEmpty && ( this.getChild( 0 ).name == 'ul' || this.getChild( 0 ).name == 'ol' );\n\n\tif ( this.isEmpty || hasOnlyLists ) {\n\t\treturn 0;\n\t}\n\n\treturn getFillerOffset.call( this );\n}\n"],"sourceRoot":""}