@ckeditor/ckeditor5-list
Advanced tools
Comparing version 0.6.1 to 0.7.0
Changelog | ||
========= | ||
## [0.7.0](https://github.com/ckeditor/ckeditor5-list/compare/v0.6.1...v0.7.0) (2017-09-03) | ||
### Bug fixes | ||
* `ListCommand` should check whether it can be applied to the selection. Closes [#62](https://github.com/ckeditor/ckeditor5-list/issues/62). ([12b77ae](https://github.com/ckeditor/ckeditor5-list/commit/12b77ae)) | ||
* `view.UIElement` will no longer be incorrectly removed instead of `<li>` element if it was before `<li>` element to remove. Closes [#74](https://github.com/ckeditor/ckeditor5-list/issues/74). ([aa7855c](https://github.com/ckeditor/ckeditor5-list/commit/aa7855c)) | ||
* Fixed a bug when editor sometimes crashed when list item was moved outside and before a container in which it was. Closes [#78](https://github.com/ckeditor/ckeditor5-list/issues/78). ([3d8814e](https://github.com/ckeditor/ckeditor5-list/commit/3d8814e)) | ||
* List model fixer will not be triggered if a change-to-fix is in a `transparent` batch. ([0779f35](https://github.com/ckeditor/ckeditor5-list/commit/0779f35)) | ||
* `<ul>` and `<ol>` view elements will now be inserted after view UI elements. Closes [#71](https://github.com/ckeditor/ckeditor5-list/issues/71). ([0e85b2f](https://github.com/ckeditor/ckeditor5-list/commit/0e85b2f)) | ||
* The `ListEngine` plugin will not crash editor when using `DataController#insertContent()` with model items (it worked with data fragments only). Closes [#69](https://github.com/ckeditor/ckeditor5-list/issues/69). ([e0216a8](https://github.com/ckeditor/ckeditor5-list/commit/e0216a8)) | ||
### Features | ||
* List feature should use `EditingKeystrokeHandler` instead of direct event listeners. Closes [#76](https://github.com/ckeditor/ckeditor5-list/issues/76). ([aaf362c](https://github.com/ckeditor/ckeditor5-list/commit/aaf362c)) | ||
### Other changes | ||
* Aligned the implementation to the new Command API (see https://github.com/ckeditor/ckeditor5-core/issues/88). ([9a7d596](https://github.com/ckeditor/ckeditor5-list/commit/9a7d596)) | ||
* Cleaning up svg icons. ([2d423db](https://github.com/ckeditor/ckeditor5-list/commit/2d423db)) | ||
### BREAKING CHANGES | ||
* The command API has been changed. | ||
## [0.6.1](https://github.com/ckeditor/ckeditor5-list/compare/v0.6.0...v0.6.1) (2017-05-07) | ||
@@ -5,0 +30,0 @@ |
@@ -6,3 +6,3 @@ /** | ||
/* jshint browser: false, node: true, strict: true */ | ||
/* eslint-env node */ | ||
@@ -12,3 +12,4 @@ 'use strict'; | ||
const gulp = require( 'gulp' ); | ||
const ckeditor5Lint = require( '@ckeditor/ckeditor5-dev-lint' )( { | ||
const ckeditor5Lint = require( '@ckeditor/ckeditor5-dev-lint' ); | ||
const options = { | ||
// Files ignored by `gulp lint` task. | ||
@@ -19,6 +20,6 @@ // Files from .gitignore will be added automatically during task execution. | ||
] | ||
} ); | ||
}; | ||
gulp.task( 'lint', ckeditor5Lint.lint ); | ||
gulp.task( 'lint-staged', ckeditor5Lint.lintStaged ); | ||
gulp.task( 'lint', () => ckeditor5Lint.lint( options ) ); | ||
gulp.task( 'lint-staged', () => ckeditor5Lint.lintStaged( options ) ); | ||
gulp.task( 'pre-commit', [ 'lint-staged' ] ); |
{ | ||
"name": "@ckeditor/ckeditor5-list", | ||
"version": "0.6.1", | ||
"version": "0.7.0", | ||
"description": "Introduces ordered and unordered lists feature to CKEditor 5.", | ||
"keywords": [], | ||
"dependencies": { | ||
"@ckeditor/ckeditor5-engine": "^0.10.0", | ||
"@ckeditor/ckeditor5-paragraph": "^0.8.0", | ||
"@ckeditor/ckeditor5-core": "^0.8.1", | ||
"@ckeditor/ckeditor5-ui": "^0.9.0", | ||
"@ckeditor/ckeditor5-utils": "^0.9.1" | ||
"@ckeditor/ckeditor5-engine": "^0.11.0", | ||
"@ckeditor/ckeditor5-paragraph": "^0.9.0", | ||
"@ckeditor/ckeditor5-core": "^0.9.0", | ||
"@ckeditor/ckeditor5-ui": "^0.10.0", | ||
"@ckeditor/ckeditor5-utils": "^0.10.0" | ||
}, | ||
"devDependencies": { | ||
"@ckeditor/ckeditor5-basic-styles": "^0.8.1", | ||
"@ckeditor/ckeditor5-clipboard": "^0.6.0", | ||
"@ckeditor/ckeditor5-dev-lint": "^2.0.2", | ||
"@ckeditor/ckeditor5-editor-classic": "^0.7.3", | ||
"@ckeditor/ckeditor5-enter": "^0.9.1", | ||
"@ckeditor/ckeditor5-heading": "^0.9.1", | ||
"@ckeditor/ckeditor5-typing": "^0.9.1", | ||
"@ckeditor/ckeditor5-undo": "^0.8.1", | ||
"gulp": "^3.9.0", | ||
"@ckeditor/ckeditor5-basic-styles": "^0.9.0", | ||
"@ckeditor/ckeditor5-block-quote": "^0.2.0", | ||
"@ckeditor/ckeditor5-clipboard": "^0.7.0", | ||
"@ckeditor/ckeditor5-dev-lint": "^3.1.0", | ||
"@ckeditor/ckeditor5-editor-classic": "^0.8.0", | ||
"@ckeditor/ckeditor5-enter": "^0.10.0", | ||
"@ckeditor/ckeditor5-heading": "^0.10.0", | ||
"@ckeditor/ckeditor5-typing": "^0.10.0", | ||
"@ckeditor/ckeditor5-undo": "^0.9.0", | ||
"eslint-config-ckeditor5": "^1.0.5", | ||
"gulp": "^3.9.1", | ||
"guppy-pre-commit": "^0.4.0" | ||
@@ -24,0 +26,0 @@ }, |
@@ -1,4 +0,5 @@ | ||
CKEditor 5 Lists Feature | ||
CKEditor 5 lists feature | ||
======================================== | ||
[![Join the chat at https://gitter.im/ckeditor/ckeditor5](https://badges.gitter.im/ckeditor/ckeditor5.svg)](https://gitter.im/ckeditor/ckeditor5?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-list.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-list) | ||
@@ -10,3 +11,3 @@ [![Build Status](https://travis-ci.org/ckeditor/ckeditor5-list.svg?branch=master)](https://travis-ci.org/ckeditor/ckeditor5-list) | ||
Introduces ordered and unordered lists feature to CKEditor 5. More information about the project can be found at the following URL: <https://github.com/ckeditor/ckeditor5-list>. | ||
Introduces ordered (numbered) and unordered (bulleted) lists feature to CKEditor 5. More information about the project can be found at the following URL: <https://github.com/ckeditor/ckeditor5-list>. | ||
@@ -13,0 +14,0 @@ ## License |
@@ -24,9 +24,9 @@ /** | ||
/** | ||
* Model to view converter for `listItem` model element insertion. | ||
* A model-to-view converter for `listItem` model element insertion. | ||
* | ||
* It creates `<ul><li></li><ul>` (or `<ol>`) view structure out of `listItem` model element, inserts it at correct | ||
* position, and merges the list with surrounding lists (if able). | ||
* It creates a `<ul><li></li><ul>` (or `<ol>`) view structure out of a `listItem` model element, inserts it at the correct | ||
* position, and merges the list with surrounding lists (if available). | ||
* | ||
* @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:insert | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data Additional information about the change. | ||
@@ -58,9 +58,9 @@ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume. | ||
/** | ||
* Model to view converter for `type` attribute change on `listItem` model element. | ||
* A model-to-view converter for `type` attribute change on `listItem` model element. | ||
* | ||
* This change means that `<li>`s parent changes from `<ul>` to `<ol>` (or vice versa). This is accomplished by breaking | ||
* view elements, changing their name and merging them. | ||
* This change means that `<li>` elements parent changes from `<ul>` to `<ol>` (or vice versa). This is accomplished | ||
* by breaking view elements, changing their name and merging them. | ||
* | ||
* @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:changeAttribute | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data Additional information about the change. | ||
@@ -94,6 +94,6 @@ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume. | ||
/** | ||
* Model to view converter for `listItem` model element remove. | ||
* A model-to-view converter for `listItem` model element removal. | ||
* | ||
* @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:remove | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data Additional information about the change. | ||
@@ -108,5 +108,7 @@ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume. | ||
const viewPosition = conversionApi.mapper.toViewPosition( data.sourcePosition ); | ||
const viewItem = viewPosition.nodeAfter.is( 'li' ) ? viewPosition.nodeAfter : viewPosition.nodeAfter.getChild( 0 ); | ||
let viewPosition = conversionApi.mapper.toViewPosition( data.sourcePosition ); | ||
viewPosition = viewPosition.getLastMatchingPosition( value => !value.item.is( 'li' ) ); | ||
const viewItem = viewPosition.nodeAfter; | ||
// 1. Break the container after and before the list item. | ||
@@ -138,6 +140,6 @@ // This will create a view list with one view list item -- the one that changed type. | ||
/** | ||
* Model to view converter for `indent` attribute change on `listItem` model element. | ||
* A model-to-view converter for `indent` attribute change on `listItem` model element. | ||
* | ||
* @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:changeAttribute | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data Additional information about the change. | ||
@@ -184,4 +186,4 @@ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume. | ||
/** | ||
* A special model to view converter introduced by {@link module:list/list~List List feature}. This converter is fired for | ||
* insert change of every model item, and should be fired before actual converter. The converter checks whether inserted | ||
* A special model-to-view converter introduced by the {@link module:list/list~List list feature}. This converter is fired for | ||
* insert change of every model item, and should be fired before the actual converter. The converter checks whether the inserted | ||
* model item is a non-`listItem` element. If it is, and it is inserted inside a view list, the converter breaks the | ||
@@ -204,3 +206,3 @@ * list so the model element is inserted to the view parent element corresponding to its model parent element. | ||
* @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:insert | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data Additional information about the change. | ||
@@ -292,3 +294,3 @@ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume. | ||
if ( i > 0 ) { | ||
let mergePos = mergeViewLists( previousList, previousList.nextSibling ); | ||
const mergePos = mergeViewLists( previousList, previousList.nextSibling ); | ||
@@ -310,3 +312,3 @@ // If `mergePos` is in `previousList` it means that the lists got merged. | ||
/** | ||
* A special model to view converter introduced by {@link module:list/list~List List feature}. This converter takes care of | ||
* A special model-to-view converter introduced by the {@link module:list/list~List list feature}. This converter takes care of | ||
* merging view lists after something is removed or moved from near them. | ||
@@ -328,4 +330,3 @@ * | ||
* @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:remove | ||
* @see module:engine/conversion/modelconversiondispatcher~ModelConversionDispatcher#event:move | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data Additional information about the change. | ||
@@ -349,13 +350,13 @@ * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume. | ||
/** | ||
* View to model converter that converts view `<li>` elements into `listItem` model elements. | ||
* A view-to-model converter that converts `<li>` view elements into `listItem` model elements. | ||
* | ||
* To set correct values of `type` and `indent` attribute the converter: | ||
* To set correct values of the `type` and `indent` attributes the converter: | ||
* * checks `<li>`'s parent, | ||
* * passes `data.indent` value when `<li>`'s sub-items are converted. | ||
* * passes the `data.indent` value when `<li>`'s sub-items are converted. | ||
* | ||
* @see module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:element | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {Object} data Object containing conversion input and a placeholder for conversion output and possibly other values. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values. | ||
* @param {module:engine/conversion/viewconsumable~ViewConsumable} consumable Values to consume. | ||
* @param {Object} conversionApi Conversion interface to be used by callback. | ||
* @param {Object} conversionApi Conversion interface to be used by the callback. | ||
*/ | ||
@@ -381,3 +382,3 @@ export function viewModelConverter( evt, data, consumable, conversionApi ) { | ||
// `listItem`s will be kept in flat structure. | ||
let items = new ModelDocumentFragment(); | ||
const items = new ModelDocumentFragment(); | ||
items.appendChildren( listItem ); | ||
@@ -388,3 +389,3 @@ | ||
// This should be handled by `<ul>` and `<ol>` converters. | ||
for ( let child of data.input.getChildren() ) { | ||
for ( const child of data.input.getChildren() ) { | ||
// Let's convert the child. | ||
@@ -412,9 +413,9 @@ const converted = conversionApi.convertItem( child, consumable, data ); | ||
/** | ||
* View to model converter for `<ul>` and `<ol>` view elements, that cleans the input view out of garbage. | ||
* This is mostly to clean white spaces from between `<li>` view elements inside the view list element, however also | ||
* A view-to-model converter for `<ul>` and `<ol>` view elements that cleans the input view of garbage. | ||
* This is mostly to clean whitespaces from between `<li>` view elements inside the view list element, however, also | ||
* incorrect data can be cleared if the view was incorrect. | ||
* | ||
* @see module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:element | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {Object} data Object containing conversion input and a placeholder for conversion output and possibly other values. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values. | ||
* @param {module:engine/conversion/viewconsumable~ViewConsumable} consumable Values to consume. | ||
@@ -427,3 +428,3 @@ */ | ||
for ( let child of children ) { | ||
for ( const child of children ) { | ||
if ( !child.is( 'li' ) ) { | ||
@@ -437,7 +438,7 @@ child.remove(); | ||
/** | ||
* View to model converter for `<li>, that cleans white space formatting from the input view. | ||
* A view-to-model converter for `<li>` elements that cleans whitespace formatting from the input view. | ||
* | ||
* @see module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:element | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {Object} data Object containing conversion input and a placeholder for conversion output and possibly other values. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data An object containing conversion input and a placeholder for conversion output and possibly other values. | ||
* @param {module:engine/conversion/viewconsumable~ViewConsumable} consumable Values to consume. | ||
@@ -456,3 +457,3 @@ */ | ||
for ( let child of children ) { | ||
for ( const child of children ) { | ||
if ( foundList && !child.is( 'ul' ) && !child.is( 'ol' ) ) { | ||
@@ -483,9 +484,9 @@ child.remove(); | ||
/** | ||
* Callback for model position to view position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes positions | ||
* between `listItem` elements, that would be incorrectly mapped because of how list items are represented in model | ||
* The callback for model position to view position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes | ||
* positions between `listItem` elements that would be incorrectly mapped because of how list items are represented in model | ||
* and view. | ||
* | ||
* @see module:engine/conversion/mapper~Mapper#event:modelToViewPosition | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {Object} data Object containing additional data and placeholder for mapping result. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data An object containing additional data and placeholder for mapping result. | ||
*/ | ||
@@ -497,3 +498,3 @@ export function modelToViewPosition( evt, data ) { | ||
const viewItem = data.mapper.toViewElement( modelItem ); | ||
const topmostViewList = viewItem.getAncestors().find( ( element ) => element.is( 'ul' ) || element.is( 'ol' ) ); | ||
const topmostViewList = viewItem.getAncestors().find( element => element.is( 'ul' ) || element.is( 'ol' ) ); | ||
const walker = new ViewTreeWalker( { | ||
@@ -503,3 +504,3 @@ startPosition: ViewPosition.createAt( viewItem, 0 ) | ||
for ( let value of walker ) { | ||
for ( const value of walker ) { | ||
if ( value.type == 'elementStart' && value.item.is( 'li' ) ) { | ||
@@ -519,9 +520,9 @@ data.viewPosition = value.previousPosition; | ||
/** | ||
* Callback for view position to model position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes positions | ||
* between `<li>` elements, that would be incorrectly mapped because of how list items are represented in model | ||
* The callback for view position to model position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes | ||
* positions between `<li>` elements that would be incorrectly mapped because of how list items are represented in model | ||
* and view. | ||
* | ||
* @see module:engine/conversion/mapper~Mapper#event:viewToModelPosition | ||
* @param {module:utils/eventinfo~EventInfo} evt Object containing information about the fired event. | ||
* @param {Object} data Object containing additional data and placeholder for mapping result. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Object} data An object containing additional data and placeholder for mapping result. | ||
*/ | ||
@@ -577,3 +578,3 @@ export function viewToModelPosition( evt, data ) { | ||
/** | ||
* Post fixer that reacts to changes on document and fixed incorrect model states. | ||
* Post-fixer that reacts to changes on document and fixes incorrect model states. | ||
* | ||
@@ -589,21 +590,31 @@ * Example: | ||
* <listItem type="bulleted" indent=0>Item 1</listItem> | ||
* <listItem type="bulleted" indent=1>Item 3</listItem> <--- note that indent got postfixed. | ||
* <listItem type="bulleted" indent=1>Item 3</listItem> <--- note that indent got post-fixed. | ||
* | ||
* @param {module:engine/model/document~Document} document Document to observe. | ||
* @returns {Function} Callback to be attached to {@link module:engine/model/document~Document#event:change document change event}. | ||
* @param {module:engine/model/document~Document} document The document to observe. | ||
* @returns {Function} A callback to be attached to the {@link module:engine/model/document~Document#event:change document change event}. | ||
*/ | ||
export function modelChangePostFixer( document ) { | ||
return ( evt, type, changes, batch ) => { | ||
if ( batch.type == 'transparent' ) { | ||
return; | ||
} | ||
if ( type == 'remove' ) { | ||
const howMany = changes.range.end.offset - changes.range.start.offset; | ||
const sourcePos = changes.sourcePosition._getTransformedByInsertion( changes.range.start, howMany, true ); | ||
// Fix list items after the cut-out range. | ||
// This fix is needed if items in model after cut-out range have now wrong indents compared to their previous siblings. | ||
_fixItemsIndent( changes.sourcePosition, document, batch ); | ||
_fixItemsIndent( sourcePos, document, batch ); | ||
// This fix is needed if two different nested lists got merged, change types of list items "below". | ||
_fixItemsType( changes.sourcePosition, false, document, batch ); | ||
_fixItemsType( sourcePos, false, document, batch ); | ||
} else if ( type == 'move' ) { | ||
const howMany = changes.range.end.offset - changes.range.start.offset; | ||
const sourcePos = changes.sourcePosition._getTransformedByInsertion( changes.range.start, howMany, true ); | ||
// Fix list items after the cut-out range. | ||
// This fix is needed if items in model after cut-out range have now wrong indents compared to their previous siblings. | ||
_fixItemsIndent( changes.sourcePosition, document, batch ); | ||
_fixItemsIndent( sourcePos, document, batch ); | ||
// This fix is needed if two different nested lists got merged, change types of list items "below". | ||
_fixItemsType( changes.sourcePosition, false, document, batch ); | ||
_fixItemsType( sourcePos, false, document, batch ); | ||
@@ -679,3 +690,3 @@ // Fix items in moved range. | ||
// Since we are outdenting list items, it is safer to start from the last one (it will maintain correct model state). | ||
for ( let item of items.reverse() ) { | ||
for ( const item of items.reverse() ) { | ||
batch.setAttribute( item.item, 'indent', item.indent ); | ||
@@ -724,5 +735,5 @@ } | ||
/** | ||
* Fixer for pasted content that includes list items. | ||
* A fixer for pasted content that includes list items. | ||
* | ||
* Fixes indent of pasted list items so the pasted items match correctly to the context they are pasted into. | ||
* It fixes indentation of pasted list items so the pasted items match correctly to the context they are pasted into. | ||
* | ||
@@ -744,14 +755,16 @@ * Example: | ||
* | ||
* @param {module:engine/model/document~Document} document Document to observe. | ||
* @returns {Function} Callback to be attached to {@link module:engine/model/document~Document#event:change document change event}. | ||
* @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. | ||
* @param {Array} args Arguments of {@link module:engine/controller/datacontroller~DataController#insertContent}. | ||
*/ | ||
export function modelIndentPasteFixer( evt, data ) { | ||
export function modelIndentPasteFixer( evt, [ content, selection ] ) { | ||
// Check whether inserted content starts from a `listItem`. If it does not, it means that there are some other | ||
// elements before it and there is no need to fix indents, because even if we insert that content into a list, | ||
// that list will be broken. | ||
let item = data.content.getChild( 0 ); | ||
// Note: we also need to handle singular elements because inserting item with indent 0 into 0,1,[],2 | ||
// would create incorrect model. | ||
let item = content.is( 'documentFragment' ) ? content.getChild( 0 ) : content; | ||
if ( item.is( 'listItem' ) ) { | ||
// Get a reference list item. Inserted list items will be fixed according to that item. | ||
const pos = data.selection.getFirstPosition(); | ||
const pos = selection.getFirstPosition(); | ||
let refItem = null; | ||
@@ -824,3 +837,3 @@ | ||
while ( item && item.name == 'listItem' ) { | ||
let itemIndent = item.getAttribute( 'indent' ); | ||
const itemIndent = item.getAttribute( 'indent' ); | ||
@@ -879,3 +892,3 @@ if ( | ||
// Break the list after it. Inserted view item will be inserted in the broken space. | ||
let viewItem = mapper.toViewElement( prevItem ); | ||
const viewItem = mapper.toViewElement( prevItem ); | ||
insertPosition = viewWriter.breakContainer( ViewPosition.createAfter( viewItem ) ); | ||
@@ -911,2 +924,4 @@ } else { | ||
insertPosition = positionAfterUiElements( insertPosition ); | ||
// Insert the view item. | ||
@@ -922,7 +937,7 @@ viewWriter.insert( insertPosition, injectedList ); | ||
modelItem, | ||
{ biggerIndent: true, getNext: true, isMapped: true, mapper: mapper } | ||
{ biggerIndent: true, getNext: true, isMapped: true, mapper } | ||
); | ||
if ( nextItem ) { | ||
let viewItem = mapper.toViewElement( nextItem ); | ||
const viewItem = mapper.toViewElement( nextItem ); | ||
@@ -1029,5 +1044,7 @@ // Break the list between found view item and its preceding `<li>`s. | ||
insertPosition = positionAfterUiElements( insertPosition ); | ||
// Handle multiple lists. This happens if list item has nested numbered and bulleted lists. Following lists | ||
// are inserted after the first list (no need to recalculate insertion position for them). | ||
for ( let child of [ ...viewRemovedItem.getChildren() ] ) { | ||
for ( const child of [ ...viewRemovedItem.getChildren() ] ) { | ||
if ( child.is( 'ul' ) || child.is( 'ol' ) ) { | ||
@@ -1059,1 +1076,10 @@ insertPosition = viewWriter.move( ViewRange.createOn( child ), insertPosition ).end; | ||
} | ||
// Helper function that for given `view.Position`, returns a `view.Position` that is after all `view.UIElement`s that | ||
// are after given position. | ||
// For example: | ||
// <container:p>foo^<ui:span></ui:span><ui:span></ui:span>bar</contain:p> | ||
// For position ^, a position before "bar" will be returned. | ||
function positionAfterUiElements( viewPosition ) { | ||
return viewPosition.getLastMatchingPosition( value => value.item.is( 'uiElement' ) ); | ||
} |
@@ -10,3 +10,3 @@ /** | ||
import Command from '@ckeditor/ckeditor5-core/src/command/command'; | ||
import Command from '@ckeditor/ckeditor5-core/src/command'; | ||
import first from '@ckeditor/ckeditor5-utils/src/first'; | ||
@@ -17,3 +17,3 @@ | ||
* | ||
* @extends core.command.Command | ||
* @extends module:core/command~Command | ||
*/ | ||
@@ -24,4 +24,4 @@ export default class IndentCommand extends Command { | ||
* | ||
* @param {module:core/editor/editor~Editor} editor Editor instance. | ||
* @param {'forward'|'backward'} indentDirection Direction of indent. If it is equal to `backward`, the command | ||
* @param {module:core/editor/editor~Editor} editor The editor instance. | ||
* @param {'forward'|'backward'} indentDirection The direction of indent. If it is equal to `backward`, the command | ||
* will outdent a list item. | ||
@@ -33,3 +33,3 @@ */ | ||
/** | ||
* By how much the command will change list item's indent attribute. | ||
* Determines by how much the command will change the list item's indent attribute. | ||
* | ||
@@ -41,6 +41,2 @@ * @readonly | ||
this._indentBy = indentDirection == 'forward' ? 1 : -1; | ||
this.listenTo( editor.document, 'changesDone', () => { | ||
this.refreshState(); | ||
} ); | ||
} | ||
@@ -51,3 +47,12 @@ | ||
*/ | ||
_doExecute() { | ||
refresh() { | ||
this.isEnabled = this._checkEnabled(); | ||
} | ||
/** | ||
* Indents or outdents (depends on the {@link #constructor}'s `indentDirection` parameter) selected list items. | ||
* | ||
* @fires execute | ||
*/ | ||
execute() { | ||
const doc = this.editor.document; | ||
@@ -78,3 +83,3 @@ const batch = doc.batch(); | ||
for ( let item of itemsToChange ) { | ||
for ( const item of itemsToChange ) { | ||
const indent = item.getAttribute( 'indent' ) + this._indentBy; | ||
@@ -102,3 +107,3 @@ | ||
for ( let item of itemsToChange ) { | ||
for ( const item of itemsToChange ) { | ||
_fixType( item, batch ); | ||
@@ -110,3 +115,6 @@ } | ||
/** | ||
* @inheritDoc | ||
* Checks whether the command can be enabled in the current context. | ||
* | ||
* @private | ||
* @returns {Boolean} Whether the command should be enabled. | ||
*/ | ||
@@ -113,0 +121,0 @@ _checkEnabled() { |
@@ -16,8 +16,7 @@ /** | ||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | ||
import { parseKeystroke } from '@ckeditor/ckeditor5-utils/src/keyboard'; | ||
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview'; | ||
/** | ||
* The lists feature. It introduces the `numberedList` and `bulletedList` buttons which | ||
* allows to convert paragraphs to/from list items and indent/outdent them. | ||
* The list feature. It introduces the `numberedList` and `bulletedList` buttons that | ||
* allow to convert paragraphs to and from list items and indent or outdent them. | ||
* | ||
@@ -40,3 +39,3 @@ * See also {@link module:list/listengine~ListEngine}. | ||
static get pluginName() { | ||
return 'list/list'; | ||
return 'List'; | ||
} | ||
@@ -53,4 +52,4 @@ | ||
// Overwrite default enter key behavior. | ||
// If enter key is pressed with selection collapsed in empty list item, outdent it instead of breaking it. | ||
// Overwrite default Enter key behavior. | ||
// If Enter key is pressed with selection collapsed in empty list item, outdent it instead of breaking it. | ||
this.listenTo( this.editor.editing.view, 'enter', ( evt, data ) => { | ||
@@ -68,15 +67,4 @@ const doc = this.editor.document; | ||
// Add tab key support. | ||
// When in list item, pressing tab should indent list item, if possible. | ||
// Pressing Shift+Tab shout outdent list item. | ||
this.listenTo( this.editor.editing.view, 'keydown', ( evt, data ) => { | ||
let commandName; | ||
if ( data.keystroke == parseKeystroke( 'Tab' ) ) { | ||
commandName = 'indentList'; | ||
} else if ( data.keystroke == parseKeystroke( 'Shift+Tab' ) ) { | ||
commandName = 'outdentList'; | ||
} | ||
if ( commandName ) { | ||
const getCommandExecuter = commandName => { | ||
return ( data, cancel ) => { | ||
const command = this.editor.commands.get( commandName ); | ||
@@ -86,8 +74,9 @@ | ||
this.editor.execute( commandName ); | ||
cancel(); | ||
} | ||
}; | ||
}; | ||
data.preventDefault(); | ||
evt.stop(); | ||
} | ||
} | ||
} ); | ||
this.editor.keystrokes.set( 'Tab', getCommandExecuter( 'indentList' ) ); | ||
this.editor.keystrokes.set( 'Shift+Tab', getCommandExecuter( 'outdentList' ) ); | ||
} | ||
@@ -99,5 +88,5 @@ | ||
* @private | ||
* @param {String} commandName Name of the command. | ||
* @param {Object} label Button label. | ||
* @param {String} icon Source of the icon. | ||
* @param {String} commandName The name of the command. | ||
* @param {Object} label The button label. | ||
* @param {String} icon The source of the icon. | ||
*/ | ||
@@ -108,8 +97,8 @@ _addButton( commandName, label, icon ) { | ||
editor.ui.componentFactory.add( commandName, ( locale ) => { | ||
editor.ui.componentFactory.add( commandName, locale => { | ||
const buttonView = new ButtonView( locale ); | ||
buttonView.set( { | ||
label: label, | ||
icon: icon, | ||
label, | ||
icon, | ||
tooltip: true | ||
@@ -116,0 +105,0 @@ } ); |
@@ -10,3 +10,3 @@ /** | ||
import Command from '@ckeditor/ckeditor5-core/src/command/command'; | ||
import Command from '@ckeditor/ckeditor5-core/src/command'; | ||
import Position from '@ckeditor/ckeditor5-engine/src/model/position'; | ||
@@ -18,3 +18,3 @@ import first from '@ckeditor/ckeditor5-utils/src/first'; | ||
* | ||
* @extends module:core/command/command~Command | ||
* @extends module:core/command~Command | ||
*/ | ||
@@ -25,3 +25,3 @@ export default class ListCommand extends Command { | ||
* | ||
* @param {module:core/editor/editor~Editor} editor Editor instance. | ||
* @param {module:core/editor/editor~Editor} editor The editor instance. | ||
* @param {'numbered'|'bulleted'} type List type that will be handled by this command. | ||
@@ -33,3 +33,3 @@ */ | ||
/** | ||
* The type of list created by the command. | ||
* The type of the list created by the command. | ||
* | ||
@@ -42,37 +42,30 @@ * @readonly | ||
/** | ||
* Flag indicating whether the command is active, which means that selection starts in a list of the same type. | ||
* A flag indicating whether the command is active, which means that the selection starts in a list of the same type. | ||
* | ||
* @observable | ||
* @readonly | ||
* @member {Boolean} #value | ||
*/ | ||
this.set( 'value', false ); | ||
// Listen on selection and document changes and set the current command's value. | ||
this.listenTo( editor.document, 'changesDone', () => { | ||
this.refreshValue(); | ||
this.refreshState(); | ||
} ); | ||
} | ||
/** | ||
* Sets command's value based on the document selection. | ||
* @inheritDoc | ||
*/ | ||
refreshValue() { | ||
// Check whether closest `listItem` ancestor of the position has a correct type. | ||
const listItem = first( this.editor.document.selection.getSelectedBlocks() ); | ||
this.value = listItem && listItem.is( 'listItem' ) && listItem.getAttribute( 'type' ) == this.type; | ||
refresh() { | ||
this.value = this._getValue(); | ||
this.isEnabled = this._checkEnabled(); | ||
} | ||
/** | ||
* Executes command. | ||
* Executes the command. | ||
* | ||
* @protected | ||
* @param {Object} [options] Options for executed command. | ||
* @param {module:engine/model/batch~Batch} [options.batch] Batch to collect all the change steps. | ||
* New batch will be created if this option is not set. | ||
* @param {Object} [options] Options for the executed command. | ||
* @param {module:engine/model/batch~Batch} [options.batch] A batch to collect all the change steps. | ||
* A new batch will be created if this option is not set. | ||
*/ | ||
_doExecute( options = {} ) { | ||
execute( options = {} ) { | ||
const document = this.editor.document; | ||
const blocks = Array.from( document.selection.getSelectedBlocks() ); | ||
const blocks = Array.from( document.selection.getSelectedBlocks() ) | ||
.filter( block => checkCanBecomeListItem( block, document.schema ) ); | ||
@@ -168,3 +161,3 @@ // Whether we are turning off some items. | ||
for ( let item of changes ) { | ||
for ( const item of changes ) { | ||
batch.setAttribute( item.element, 'indent', item.indent ); | ||
@@ -196,3 +189,3 @@ } | ||
for ( let item of blocks ) { | ||
for ( const item of blocks ) { | ||
if ( item.is( 'listItem' ) && item.getAttribute( 'indent' ) < lowestIndent ) { | ||
@@ -217,3 +210,3 @@ lowestIndent = item.getAttribute( 'indent' ); | ||
// Do it in reverse as there might be multiple blocks (same as with changing indents). | ||
for ( let element of blocks.reverse() ) { | ||
for ( const element of blocks.reverse() ) { | ||
if ( turnOff && element.name == 'listItem' ) { | ||
@@ -237,4 +230,20 @@ // We are turning off and the element is a `listItem` - it should be converted to `paragraph`. | ||
/** | ||
* @inheritDoc | ||
* Checks the command's {@link #value}. | ||
* | ||
* @private | ||
* @returns {Boolean} The current value. | ||
*/ | ||
_getValue() { | ||
// Check whether closest `listItem` ancestor of the position has a correct type. | ||
const listItem = first( this.editor.document.selection.getSelectedBlocks() ); | ||
return !!listItem && listItem.is( 'listItem' ) && listItem.getAttribute( 'type' ) == this.type; | ||
} | ||
/** | ||
* Checks whether the command can be enabled in the current context. | ||
* | ||
* @private | ||
* @returns {Boolean} Whether the command should be enabled. | ||
*/ | ||
_checkEnabled() { | ||
@@ -256,7 +265,3 @@ // If command value is true it means that we are in list item, so the command should be enabled. | ||
// Otherwise, check if list item can be inserted at the position start. | ||
return schema.check( { | ||
name: 'listItem', | ||
attributes: [ 'type', 'indent' ], | ||
inside: Position.createBefore( firstBlock ) | ||
} ); | ||
return checkCanBecomeListItem( firstBlock, schema ); | ||
} | ||
@@ -311,1 +316,15 @@ } | ||
} | ||
// Checks whether the given block can be replaced by a listItem. | ||
// | ||
// @private | ||
// @param {module:engine/model/element~Element} block A block to be tested. | ||
// @param {module:engine/model/schema~Schema} schema The schema of the document. | ||
// @returns {Boolean} | ||
function checkCanBecomeListItem( block, schema ) { | ||
return schema.check( { | ||
name: 'listItem', | ||
attributes: [ 'type', 'indent' ], | ||
inside: Position.createBefore( block ) | ||
} ); | ||
} |
@@ -33,3 +33,3 @@ /** | ||
/** | ||
* The engine of the lists feature. It handles creating, editing and removing lists and list items. | ||
* The engine of the list feature. It handles creating, editing and removing lists and list items. | ||
* It registers the `numberedList`, `bulletedList`, `indentList` and `outdentList` commands. | ||
@@ -76,3 +76,3 @@ * | ||
if ( type == 'move' ) { | ||
for ( let item of changes.range.getItems() ) { | ||
for ( const item of changes.range.getItems() ) { | ||
if ( item.is( 'listItem' ) ) { | ||
@@ -119,8 +119,8 @@ editing.mapper.unbindModelElement( item ); | ||
// Register commands for numbered and bulleted list. | ||
editor.commands.set( 'numberedList', new ListCommand( editor, 'numbered' ) ); | ||
editor.commands.set( 'bulletedList', new ListCommand( editor, 'bulleted' ) ); | ||
editor.commands.add( 'numberedList', new ListCommand( editor, 'numbered' ) ); | ||
editor.commands.add( 'bulletedList', new ListCommand( editor, 'bulleted' ) ); | ||
// Register commands for indenting. | ||
editor.commands.set( 'indentList', new IndentCommand( editor, 'forward' ) ); | ||
editor.commands.set( 'outdentList', new IndentCommand( editor, 'backward' ) ); | ||
editor.commands.add( 'indentList', new IndentCommand( editor, 'forward' ) ); | ||
editor.commands.add( 'outdentList', new IndentCommand( editor, 'backward' ) ); | ||
} | ||
@@ -132,5 +132,5 @@ } | ||
for ( let child of element.getChildren() ) { | ||
for ( const child of element.getChildren() ) { | ||
if ( child.name == 'ul' || child.name == 'ol' ) { | ||
for ( let item of child.getChildren() ) { | ||
for ( const item of child.getChildren() ) { | ||
length += getViewListItemLength( item ); | ||
@@ -137,0 +137,0 @@ } |
@@ -13,3 +13,3 @@ /** | ||
/** | ||
* View element class representing list item (`<li>`). It extends {@link module:engine/view/containerelement~ContainerElement} | ||
* View element class representing a list item (`<li>`). It extends {@link module:engine/view/containerelement~ContainerElement} | ||
* and overwrites {@link module:list/viewlistitemelement~ViewListItemElement#getFillerOffset evaluating whether filler offset} | ||
@@ -22,7 +22,7 @@ * is needed. | ||
/** | ||
* Creates `<li>` view item. | ||
* Creates a `<li>` view item. | ||
* | ||
* @param {Object|Iterable} [attrs] Collection of attributes. | ||
* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children] List of nodes to be inserted | ||
* into created element. | ||
* @param {Object|Iterable} [attrs] A collection of attributes. | ||
* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>} [children] The list of nodes to be inserted | ||
* into the created element. | ||
*/ | ||
@@ -43,3 +43,2 @@ constructor( attrs, children ) { | ||
function getFillerOffset() { | ||
/*jshint validthis:true */ | ||
const hasOnlyLists = !this.isEmpty && ( this.getChild( 0 ).name == 'ul' || this.getChild( 0 ).name == 'ol' ); | ||
@@ -46,0 +45,0 @@ |
@@ -56,3 +56,3 @@ /** | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 5 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 5 ) ); | ||
} ); | ||
@@ -65,3 +65,3 @@ | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 0 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 0 ) ); | ||
} ); | ||
@@ -112,3 +112,3 @@ | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 2 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 2 ) ); | ||
} ); | ||
@@ -130,9 +130,9 @@ | ||
describe( '_doExecute', () => { | ||
describe( 'execute()', () => { | ||
it( 'should increment indent attribute by 1', () => { | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 5 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 5 ) ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -152,6 +152,6 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 1 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 1 ) ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -173,7 +173,7 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
new Position( root.getChild( 1 ), [ 0 ] ), | ||
new Position( root.getChild( 3 ), [ 0 ] ) | ||
new Position( root.getChild( 3 ), [ 1 ] ) | ||
) ] ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -200,3 +200,3 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -223,3 +223,3 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -252,3 +252,3 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 5 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 5 ) ); | ||
} ); | ||
@@ -262,3 +262,3 @@ | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 0 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 0 ) ); | ||
} ); | ||
@@ -272,3 +272,3 @@ | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 2 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 2 ) ); | ||
} ); | ||
@@ -280,9 +280,9 @@ | ||
describe( '_doExecute', () => { | ||
describe( 'execute()', () => { | ||
it( 'should decrement indent attribute by 1 (if it is bigger than 0)', () => { | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 5 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 5 ) ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -302,6 +302,6 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 0 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 0 ) ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -321,6 +321,6 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( root.getChild( 1 ) ); | ||
doc.selection.setCollapsedAt( root.getChild( 1 ) ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -342,7 +342,7 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
new Position( root.getChild( 1 ), [ 0 ] ), | ||
new Position( root.getChild( 3 ), [ 0 ] ) | ||
new Position( root.getChild( 3 ), [ 1 ] ) | ||
) ] ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -368,3 +368,3 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -388,3 +388,3 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -409,3 +409,3 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -428,3 +428,3 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -452,3 +452,3 @@ // Another possible behaviour would be that "b" list item becomes first list item of a top level | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -455,0 +455,0 @@ expect( getData( doc, { withoutSelection: true } ) ).to.equal( |
@@ -18,3 +18,3 @@ /** | ||
describe( 'List', () => { | ||
let editor, doc, bulletedListButton, numberedListButton, schema; | ||
let editor, doc, bulletedListButton, numberedListButton; | ||
@@ -25,8 +25,5 @@ beforeEach( () => { | ||
return ClassicTestEditor.create( editorElement, { | ||
plugins: [ Paragraph, List ] | ||
} ) | ||
return ClassicTestEditor.create( editorElement, { plugins: [ Paragraph, List ] } ) | ||
.then( newEditor => { | ||
editor = newEditor; | ||
schema = editor.document.schema; | ||
doc = editor.document; | ||
@@ -129,4 +126,5 @@ | ||
domEvtDataStub = { | ||
keystroke: getCode( 'Tab' ), | ||
preventDefault() {} | ||
keyCode: getCode( 'Tab' ), | ||
preventDefault: sinon.spy(), | ||
stopPropagation: sinon.spy() | ||
}; | ||
@@ -152,6 +150,8 @@ | ||
expect( editor.execute.calledWithExactly( 'indentList' ) ).to.be.true; | ||
sinon.assert.calledOnce( domEvtDataStub.preventDefault ); | ||
sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); | ||
} ); | ||
it( 'should execute outdentList command on Shift+Tab keystroke', () => { | ||
domEvtDataStub.keystroke += getCode( 'Shift' ); | ||
domEvtDataStub.keyCode += getCode( 'Shift' ); | ||
@@ -168,2 +168,4 @@ setData( | ||
expect( editor.execute.calledWithExactly( 'outdentList' ) ).to.be.true; | ||
sinon.assert.calledOnce( domEvtDataStub.preventDefault ); | ||
sinon.assert.calledOnce( domEvtDataStub.stopPropagation ); | ||
} ); | ||
@@ -177,6 +179,8 @@ | ||
expect( editor.execute.called ).to.be.false; | ||
sinon.assert.notCalled( domEvtDataStub.preventDefault ); | ||
sinon.assert.notCalled( domEvtDataStub.stopPropagation ); | ||
} ); | ||
it( 'should not indent or outdent if alt+tab is pressed', () => { | ||
domEvtDataStub.keystroke += getCode( 'alt' ); | ||
domEvtDataStub.keyCode += getCode( 'alt' ); | ||
@@ -192,4 +196,6 @@ setData( | ||
expect( editor.execute.called ).to.be.false; | ||
sinon.assert.notCalled( domEvtDataStub.preventDefault ); | ||
sinon.assert.notCalled( domEvtDataStub.stopPropagation ); | ||
} ); | ||
} ); | ||
} ); |
@@ -45,3 +45,3 @@ /** | ||
doc.selection.collapse( doc.getRoot().getChild( 0 ) ); | ||
doc.selection.setCollapsedAt( doc.getRoot().getChild( 0 ) ); | ||
} ); | ||
@@ -67,3 +67,3 @@ | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( doc.getRoot().getChild( 3 ) ); | ||
doc.selection.setCollapsedAt( doc.getRoot().getChild( 3 ) ); | ||
} ); | ||
@@ -76,3 +76,3 @@ | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( doc.getRoot().getChild( 2 ) ); | ||
doc.selection.setCollapsedAt( doc.getRoot().getChild( 2 ) ); | ||
} ); | ||
@@ -85,3 +85,3 @@ | ||
doc.enqueueChanges( () => { | ||
doc.selection.collapse( doc.getRoot().getChild( 1 ) ); | ||
doc.selection.setCollapsedAt( doc.getRoot().getChild( 1 ) ); | ||
} ); | ||
@@ -121,3 +121,3 @@ | ||
describe( '_doExecute', () => { | ||
describe( 'execute()', () => { | ||
describe( 'custom options', () => { | ||
@@ -129,3 +129,3 @@ it( 'should use provided batch', () => { | ||
command._doExecute( { batch } ); | ||
command.execute( { batch } ); | ||
@@ -140,3 +140,3 @@ expect( batch.deltas.length ).to.be.above( 0 ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -149,3 +149,3 @@ expect( getData( doc ) ).to.equal( '<listItem indent="0" type="bulleted">fo[]o</listItem>' ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -159,3 +159,3 @@ // Attributes will be removed by post fixer. | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -166,2 +166,3 @@ expect( getData( doc ) ).to.equal( '<listItem indent="0" type="bulleted">fo[]o</listItem>' ); | ||
it( 'should handle outdenting sub-items when list item is turned off', () => { | ||
/* eslint-disable max-len */ | ||
// Taken from docs. | ||
@@ -202,2 +203,3 @@ // | ||
// 14 * -------- | ||
/* eslint-enable max-len */ | ||
@@ -222,3 +224,3 @@ setData( | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -260,2 +262,27 @@ const expectedData = | ||
// https://github.com/ckeditor/ckeditor5-list/issues/62 | ||
it( 'should not rename blocks which cannot become listItems', () => { | ||
doc.schema.registerItem( 'restricted' ); | ||
doc.schema.allow( { name: 'restricted', inside: '$root' } ); | ||
doc.schema.disallow( { name: 'paragraph', inside: 'restricted' } ); | ||
doc.schema.registerItem( 'fooBlock', '$block' ); | ||
doc.schema.allow( { name: 'fooBlock', inside: 'restricted' } ); | ||
setData( | ||
doc, | ||
'<paragraph>a[bc</paragraph>' + | ||
'<restricted><fooBlock></fooBlock></restricted>' + | ||
'<paragraph>de]f</paragraph>' | ||
); | ||
command.execute(); | ||
expect( getData( doc ) ).to.equal( | ||
'<listItem indent="0" type="bulleted">a[bc</listItem>' + | ||
'<restricted><fooBlock></fooBlock></restricted>' + | ||
'<listItem indent="0" type="bulleted">de]f</listItem>' | ||
); | ||
} ); | ||
it( 'should rename closest block to listItem and set correct attributes', () => { | ||
@@ -267,7 +294,7 @@ // From first paragraph to second paragraph. | ||
Position.createAt( root.getChild( 2 ) ), | ||
Position.createAt( root.getChild( 3 ) ) | ||
Position.createAt( root.getChild( 3 ), 'end' ) | ||
) ] ); | ||
} ); | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -278,3 +305,3 @@ const expectedData = | ||
'<listItem indent="0" type="bulleted">[---</listItem>' + | ||
'<listItem indent="0" type="bulleted">]---</listItem>' + | ||
'<listItem indent="0" type="bulleted">---]</listItem>' + | ||
'<listItem indent="0" type="numbered">---</listItem>' + | ||
@@ -294,3 +321,3 @@ '<listItem indent="0" type="numbered">---</listItem>' + | ||
Position.createAt( root.getChild( 1 ) ), | ||
Position.createAt( root.getChild( 4 ) ) | ||
Position.createAt( root.getChild( 4 ), 'end' ) | ||
) ] ); | ||
@@ -300,3 +327,3 @@ } ); | ||
// Convert paragraphs, leave numbered list items. | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -308,3 +335,3 @@ const expectedData = | ||
'<paragraph>---</paragraph>' + | ||
'<paragraph indent="0" type="numbered">]---</paragraph>' + // Attributes will be removed by post fixer. | ||
'<paragraph indent="0" type="numbered">---]</paragraph>' + // Attributes will be removed by post fixer. | ||
'<listItem indent="0" type="numbered">---</listItem>' + | ||
@@ -327,3 +354,3 @@ '<listItem indent="1" type="bulleted">---</listItem>' + | ||
// Convert paragraphs, leave numbered list items. | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -348,3 +375,3 @@ const expectedData = | ||
Position.createAt( root.getChild( 1 ) ), | ||
Position.createAt( root.getChild( 5 ) ) | ||
Position.createAt( root.getChild( 5 ), 'end' ) | ||
) ] ); | ||
@@ -354,3 +381,3 @@ } ); | ||
// Convert paragraphs, leave numbered list items. | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -363,3 +390,3 @@ const expectedData = | ||
'<paragraph indent="0" type="numbered">---</paragraph>' + // Attributes will be removed by post fixer. | ||
'<paragraph indent="0" type="numbered">]---</paragraph>' + // Attributes will be removed by post fixer. | ||
'<paragraph indent="0" type="numbered">---]</paragraph>' + // Attributes will be removed by post fixer. | ||
'<listItem indent="0" type="bulleted">---</listItem>' + | ||
@@ -404,3 +431,3 @@ '<listItem indent="1" type="bulleted">---</listItem>'; | ||
command._doExecute(); | ||
command.execute(); | ||
@@ -407,0 +434,0 @@ const expectedData = |
@@ -8,3 +8,3 @@ /** | ||
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classic'; | ||
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; | ||
import Enter from '@ckeditor/ckeditor5-enter/src/enter'; | ||
@@ -18,11 +18,12 @@ import Typing from '@ckeditor/ckeditor5-typing/src/typing'; | ||
ClassicEditor.create( document.querySelector( '#editor' ), { | ||
plugins: [ Enter, Typing, Heading, Paragraph, Undo, List, Clipboard ], | ||
toolbar: [ 'headings', 'bulletedList', 'numberedList', 'undo', 'redo' ] | ||
} ) | ||
.then( editor => { | ||
window.editor = editor; | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); | ||
ClassicEditor | ||
.create( document.querySelector( '#editor' ), { | ||
plugins: [ Enter, Typing, Heading, Paragraph, Undo, List, Clipboard ], | ||
toolbar: [ 'headings', 'bulletedList', 'numberedList', 'undo', 'redo' ] | ||
} ) | ||
.then( editor => { | ||
window.editor = editor; | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); |
@@ -8,3 +8,3 @@ /** | ||
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classic'; | ||
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'; | ||
import Enter from '@ckeditor/ckeditor5-enter/src/enter'; | ||
@@ -19,13 +19,14 @@ import Typing from '@ckeditor/ckeditor5-typing/src/typing'; | ||
ClassicEditor.create( document.querySelector( '#editor' ), { | ||
plugins: [ Enter, Typing, Heading, Paragraph, Undo, List, Clipboard, Link ], | ||
toolbar: [ 'headings', 'bulletedList', 'numberedList', 'undo', 'redo' ] | ||
} ) | ||
.then( editor => { | ||
window.editor = editor; | ||
window.modelRoot = editor.document.getRoot(); | ||
window.viewRoot = editor.editing.view.getRoot(); | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); | ||
ClassicEditor | ||
.create( document.querySelector( '#editor' ), { | ||
plugins: [ Enter, Typing, Heading, Paragraph, Undo, List, Clipboard, Link ], | ||
toolbar: [ 'headings', 'bulletedList', 'numberedList', 'undo', 'redo' ] | ||
} ) | ||
.then( editor => { | ||
window.editor = editor; | ||
window.modelRoot = editor.document.getRoot(); | ||
window.viewRoot = editor.editing.view.getRoot(); | ||
} ) | ||
.catch( err => { | ||
console.error( err.stack ); | ||
} ); |
@@ -12,3 +12,3 @@ /** | ||
it( 'should extend ViewContainerElement', () => { | ||
let item = new ViewListItemElement(); | ||
const item = new ViewListItemElement(); | ||
@@ -19,3 +19,3 @@ expect( item ).to.be.instanceof( ViewContainerElement ); | ||
it( 'should have li name', () => { | ||
let item = new ViewListItemElement(); | ||
const item = new ViewListItemElement(); | ||
@@ -27,3 +27,3 @@ expect( item.name ).to.equal( 'li' ); | ||
it( 'should return 0 if item is empty', () => { | ||
let item = new ViewListItemElement(); | ||
const item = new ViewListItemElement(); | ||
@@ -34,3 +34,3 @@ expect( item.getFillerOffset() ).to.equal( 0 ); | ||
it( 'should return 0 if item has only lists as children', () => { | ||
let item = new ViewListItemElement( null, [ | ||
const item = new ViewListItemElement( null, [ | ||
new ViewContainerElement( 'ul', null, [ | ||
@@ -46,3 +46,3 @@ new ViewListItemElement( null, new ViewText( 'foo' ) ), | ||
it( 'should return null if item has non-list contents', () => { | ||
let item = new ViewListItemElement( null, new ViewText( 'foo' ) ); | ||
const item = new ViewListItemElement( null, new ViewText( 'foo' ) ); | ||
@@ -49,0 +49,0 @@ expect( item.getFillerOffset() ).to.be.null; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
250416
57
5582
16
12
+ Added@ckeditor/ckeditor5-core@0.9.0(transitive)
+ Added@ckeditor/ckeditor5-engine@0.11.0(transitive)
+ Added@ckeditor/ckeditor5-paragraph@0.9.0(transitive)
+ Added@ckeditor/ckeditor5-theme-lark@0.9.0(transitive)
+ Added@ckeditor/ckeditor5-ui@0.10.0(transitive)
+ Added@ckeditor/ckeditor5-utils@0.10.0(transitive)
- Removed@ckeditor/ckeditor5-core@0.8.1(transitive)
- Removed@ckeditor/ckeditor5-engine@0.10.0(transitive)
- Removed@ckeditor/ckeditor5-paragraph@0.8.0(transitive)
- Removed@ckeditor/ckeditor5-theme-lark@0.8.0(transitive)
- Removed@ckeditor/ckeditor5-ui@0.9.0(transitive)
- Removed@ckeditor/ckeditor5-utils@0.9.1(transitive)