Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into t/ckeditor5-editor-inline/5
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateusz Samsel committed Aug 14, 2019
2 parents 7a806b9 + b87e57b commit a9ac223
Show file tree
Hide file tree
Showing 43 changed files with 934 additions and 361 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Changelog
=========

## [13.2.1](https://github.com/ckeditor/ckeditor5-engine/compare/v13.2.0...v13.2.1) (2019-07-10)

Internal changes only (updated dependencies, documentation, etc.).


## [13.2.0](https://github.com/ckeditor/ckeditor5-engine/compare/v13.1.1...v13.2.0) (2019-07-04)

### Features
Expand Down
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ckeditor/ckeditor5-engine",
"version": "13.2.0",
"version": "13.2.1",
"description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.",
"keywords": [
"wysiwyg",
Expand All @@ -21,26 +21,26 @@
"ckeditor 5"
],
"dependencies": {
"@ckeditor/ckeditor5-utils": "^13.0.0",
"@ckeditor/ckeditor5-utils": "^13.0.1",
"lodash-es": "^4.17.10"
},
"devDependencies": {
"@ckeditor/ckeditor5-basic-styles": "^11.1.2",
"@ckeditor/ckeditor5-block-quote": "^11.1.1",
"@ckeditor/ckeditor5-core": "^12.2.0",
"@ckeditor/ckeditor5-editor-classic": "^12.1.2",
"@ckeditor/ckeditor5-enter": "^11.0.3",
"@ckeditor/ckeditor5-essentials": "^11.0.3",
"@ckeditor/ckeditor5-heading": "^11.0.3",
"@ckeditor/ckeditor5-link": "^11.1.0",
"@ckeditor/ckeditor5-list": "^12.0.3",
"@ckeditor/ckeditor5-paragraph": "^11.0.3",
"@ckeditor/ckeditor5-theme-lark": "^14.1.0",
"@ckeditor/ckeditor5-typing": "^12.1.0",
"@ckeditor/ckeditor5-undo": "^11.0.3",
"@ckeditor/ckeditor5-widget": "^11.0.3",
"@ckeditor/ckeditor5-basic-styles": "^11.1.3",
"@ckeditor/ckeditor5-block-quote": "^11.1.2",
"@ckeditor/ckeditor5-core": "^12.2.1",
"@ckeditor/ckeditor5-editor-classic": "^12.1.3",
"@ckeditor/ckeditor5-enter": "^11.0.4",
"@ckeditor/ckeditor5-essentials": "^11.0.4",
"@ckeditor/ckeditor5-heading": "^11.0.4",
"@ckeditor/ckeditor5-link": "^11.1.1",
"@ckeditor/ckeditor5-list": "^12.0.4",
"@ckeditor/ckeditor5-paragraph": "^11.0.4",
"@ckeditor/ckeditor5-theme-lark": "^14.1.1",
"@ckeditor/ckeditor5-typing": "^12.1.1",
"@ckeditor/ckeditor5-undo": "^11.0.4",
"@ckeditor/ckeditor5-widget": "^11.0.4",
"eslint": "^5.5.0",
"eslint-config-ckeditor5": "^1.0.11",
"eslint-config-ckeditor5": "^2.0.0",
"husky": "^1.3.1",
"lint-staged": "^7.0.0"
},
Expand Down
9 changes: 3 additions & 6 deletions src/conversion/downcastdispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,6 @@ export default class DowncastDispatcher {
* @param {String} data.attributeKey Attribute key.
* @param {*} data.attributeOldValue Attribute value before the change. This is `null` when selection attribute is converted.
* @param {*} data.attributeNewValue New attribute value.
* @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
* @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface
* to be used by callback, passed in `DowncastDispatcher` constructor.
*/
Expand All @@ -542,7 +541,6 @@ export default class DowncastDispatcher {
*
* @event selection
* @param {module:engine/model/selection~Selection} selection Selection that is converted.
* @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
* @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface
* to be used by callback, passed in `DowncastDispatcher` constructor.
*/
Expand All @@ -558,17 +556,17 @@ export default class DowncastDispatcher {
* If the marker range is not collapsed:
*
* * the event is fired for each item in the marker range one by one,
* * consumables object includes each item of the marker range and the consumable value is same as event name.
* * `conversionApi.consumable` includes each item of the marker range and the consumable value is same as event name.
*
* If the marker range is collapsed:
*
* * there is only one event,
* * consumables object includes marker range with event name.
* * `conversionApi.consumable` includes marker range with event name.
*
* If selection inside a marker is converted:
*
* * there is only one event,
* * consumables object includes selection instance with event name.
* * `conversionApi.consumable` includes selection instance with event name.
*
* @event addMarker
* @param {Object} data Additional information about the change.
Expand All @@ -578,7 +576,6 @@ export default class DowncastDispatcher {
* the marker range was not collapsed.
* @param {module:engine/model/range~Range} data.markerRange Marker range.
* @param {String} data.markerName Marker name.
* @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
* @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface
* to be used by callback, passed in `DowncastDispatcher` constructor.
*/
Expand Down
30 changes: 15 additions & 15 deletions src/conversion/downcasthelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/**
* Contains downcast (model-to-view) converters for {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}.
*
* @module engine/conversion/downcasthelpers
*/

import ModelRange from '../model/range';
import ModelSelection from '../model/selection';
import ModelElement from '../model/element';
Expand All @@ -11,14 +17,8 @@ import ViewAttributeElement from '../view/attributeelement';
import DocumentSelection from '../model/documentselection';
import ConversionHelpers from './conversionhelpers';

import log from '@ckeditor/ckeditor5-utils/src/log';
import { cloneDeep } from 'lodash-es';

/**
* Contains downcast (model-to-view) converters for {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}.
*
* @module engine/conversion/downcasthelpers
*/
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';

/**
* Downcast conversion helper functions.
Expand Down Expand Up @@ -730,9 +730,8 @@ function removeUIElement() {
return;
}

conversionApi.mapper.unbindElementsFromMarkerName( data.markerName );

for ( const element of elements ) {
conversionApi.mapper.unbindElementFromMarkerName( element, data.markerName );
conversionApi.writer.clear( conversionApi.writer.createRangeOn( element ), element );
}

Expand Down Expand Up @@ -824,10 +823,11 @@ function changeAttribute( attributeCreator ) {
*
* @error conversion-attribute-to-attribute-on-text
*/
log.warn( 'conversion-attribute-to-attribute-on-text: ' +
'Trying to convert text node\'s attribute with attribute-to-attribute converter.' );

return;
throw new CKEditorError(
'conversion-attribute-to-attribute-on-text: ' +
'Trying to convert text node\'s attribute with attribute-to-attribute converter.',
[ data, conversionApi ]
);
}

// First remove the old attribute if there was one.
Expand Down Expand Up @@ -1030,9 +1030,9 @@ function removeHighlight( highlightDescriptor ) {
return;
}

conversionApi.mapper.unbindElementsFromMarkerName( data.markerName );

for ( const element of elements ) {
conversionApi.mapper.unbindElementFromMarkerName( element, data.markerName );

if ( element.is( 'attributeElement' ) ) {
conversionApi.writer.unwrap( conversionApi.writer.createRangeOn( element ), viewHighlightElement );
} else {
Expand Down
15 changes: 12 additions & 3 deletions src/conversion/mapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,21 @@ export default class Mapper {
}

/**
* Unbinds all elements from given marker name.
* Unbinds an element from given marker name.
*
* @param {module:engine/view/element~Element} element Element to unbind.
* @param {String} name Marker name.
*/
unbindElementsFromMarkerName( name ) {
this._markerNameToElements.delete( name );
unbindElementFromMarkerName( element, name ) {
const elements = this._markerNameToElements.get( name );

if ( elements ) {
elements.delete( element );

if ( elements.size == 0 ) {
this._markerNameToElements.delete( name );
}
}
}

/**
Expand Down
21 changes: 21 additions & 0 deletions src/conversion/upcastdispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
* }
* } );
*
* // Convert <p>'s font-size style.
* // Note: You should use a low-priority observer in order to ensure that
* // it's executed after the element-to-element converter.
* editor.data.upcastDispatcher.on( 'element:p', ( evt, data, conversionApi ) => {
* const { consumable, schema, writer } = conversionApi;
*
* if ( !consumable.consume( data.viewItem, { style: 'font-size' } ) ) {
* return;
* }
*
* const fontSize = data.viewItem.getStyle( 'font-size' );
*
* // Don't go for the model element after data.modelCursor because it might happen
* // that a single view element was converted to multiple model elements. Get all of them.
* for ( const item of data.modelRange.getItems( { shallow: true } ) ) {
* if ( schema.checkAttribute( item, 'fontSize' ) ) {
* writer.setAttribute( 'fontSize', fontSize, item );
* }
* }
* }, { priority: 'low' } );
*
* // Convert all elements which have no custom converter into paragraph (autoparagraphing).
* editor.data.upcastDispatcher.on( 'element', ( evt, data, conversionApi ) => {
* // When element is already consumed by higher priority converters then do nothing.
Expand Down
4 changes: 2 additions & 2 deletions src/conversion/upcasthelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export default class UpcastHelpers extends ConversionHelpers {
* @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing
* the model attribute. `value` property may be set as a function that takes a view element and returns the value.
* If `String` is given, the model attribute value will be set to `true`.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='low'] Converter priority.
* @returns {module:engine/conversion/upcasthelpers~UpcastHelpers}
*/
elementToAttribute( config ) {
Expand Down Expand Up @@ -422,7 +422,7 @@ function upcastElementToElement( config ) {
// @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing
// the model attribute. `value` property may be set as a function that takes a view element and returns the value.
// If `String` is given, the model attribute value will be set to `true`.
// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
// @param {module:utils/priorities~PriorityString} [config.converterPriority='low'] Converter priority.
// @returns {Function} Conversion helper.
function upcastElementToAttribute( config ) {
config = cloneDeep( config );
Expand Down
44 changes: 39 additions & 5 deletions src/model/differ.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,32 @@ export default class Differ {
return this._changesInElement.size == 0 && this._changedMarkers.size == 0;
}

/**
* Marks given `item` in differ to be "refreshed". It means that the item will be marked as removed and inserted in the differ changes
* set, so it will be effectively re-converted when differ changes will be handled by a dispatcher.
*
* @param {module:engine/model/item~Item} item Item to refresh.
*/
refreshItem( item ) {
if ( this._isInInsertedElement( item.parent ) ) {
return;
}

this._markRemove( item.parent, item.startOffset, item.offsetSize );
this._markInsert( item.parent, item.startOffset, item.offsetSize );

const range = Range._createOn( item );

for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
const markerRange = marker.getRange();

this.bufferMarkerChange( marker.name, markerRange, markerRange, marker.affectsData );
}

// Clear cache after each buffered operation as it is no longer valid.
this._cachedChanges = null;
}

/**
* Buffers the given operation. An operation has to be buffered before it is executed.
*
Expand All @@ -136,7 +162,7 @@ export default class Differ {
case 'addAttribute':
case 'removeAttribute':
case 'changeAttribute': {
for ( const item of operation.range.getItems() ) {
for ( const item of operation.range.getItems( { shallow: true } ) ) {
if ( this._isInInsertedElement( item.parent ) ) {
continue;
}
Expand Down Expand Up @@ -1086,19 +1112,25 @@ function _generateActionsFromChanges( oldChildrenLength, changes ) {
for ( const change of changes ) {
// First, fill "holes" between changes with "equal" actions.
if ( change.offset > offset ) {
actions.push( ...'e'.repeat( change.offset - offset ).split( '' ) );
for ( let i = 0; i < change.offset - offset; i++ ) {
actions.push( 'e' );
}

oldChildrenHandled += change.offset - offset;
}

// Then, fill up actions accordingly to change type.
if ( change.type == 'insert' ) {
actions.push( ...'i'.repeat( change.howMany ).split( '' ) );
for ( let i = 0; i < change.howMany; i++ ) {
actions.push( 'i' );
}

// The last handled offset is after inserted range.
offset = change.offset + change.howMany;
} else if ( change.type == 'remove' ) {
actions.push( ...'r'.repeat( change.howMany ).split( '' ) );
for ( let i = 0; i < change.howMany; i++ ) {
actions.push( 'r' );
}

// The last handled offset is at the position where the nodes were removed.
offset = change.offset;
Expand All @@ -1117,7 +1149,9 @@ function _generateActionsFromChanges( oldChildrenLength, changes ) {
// Fill "equal" actions at the end of actions set. Use `oldChildrenHandled` to see how many children
// has not been changed / removed at the end of their parent.
if ( oldChildrenHandled < oldChildrenLength ) {
actions.push( ...'e'.repeat( oldChildrenLength - oldChildrenHandled ).split( '' ) );
for ( let i = 0; i < oldChildrenLength - oldChildrenHandled - offset; i++ ) {
actions.push( 'e' );
}
}

return actions;
Expand Down
8 changes: 1 addition & 7 deletions src/model/documentselection.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import TextProxy from './textproxy';
import toMap from '@ckeditor/ckeditor5-utils/src/tomap';
import Collection from '@ckeditor/ckeditor5-utils/src/collection';
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
import log from '@ckeditor/ckeditor5-utils/src/log';
import uid from '@ckeditor/ckeditor5-utils/src/uid';

const storePrefix = 'selection:';
Expand Down Expand Up @@ -804,12 +803,7 @@ class LiveSelection extends Selection {
this._checkRange( range );

if ( range.root == this._document.graveyard ) {
/**
* Trying to add a Range that is in the graveyard root. Range rejected.
*
* @warning model-selection-range-in-graveyard
*/
log.warn( 'model-selection-range-in-graveyard: Trying to add a Range that is in the graveyard root. Range rejected.' );
// @if CK_DEBUG // console.warn( 'Trying to add a Range that is in the graveyard root. Range rejected.' );

return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/model/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import isIterable from '@ckeditor/ckeditor5-utils/src/isiterable';
*
* **Important**: see {@link module:engine/model/node~Node} to read about restrictions using `Element` and `Node` API.
*
* @extends {module:engine/model/node~Node}
* @extends module:engine/model/node~Node
*/
export default class Element extends Node {
/**
Expand Down
8 changes: 4 additions & 4 deletions src/model/operation/mergeoperation.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,16 @@ export default class MergeOperation extends Operation {
const targetElement = this.targetPosition.parent;

// Validate whether merge operation has correct parameters.
if ( !sourceElement || !sourceElement.is( 'element' ) || !sourceElement.parent ) {
if ( !sourceElement.parent ) {
/**
* Merge source position is invalid.
* Merge source position is invalid. The element to be merged must have a parent node.
*
* @error merge-operation-source-position-invalid
*/
throw new CKEditorError( 'merge-operation-source-position-invalid: Merge source position is invalid.', this );
} else if ( !targetElement || !targetElement.is( 'element' ) || !targetElement.parent ) {
} else if ( !targetElement.parent ) {
/**
* Merge target position is invalid.
* Merge target position is invalid. The element to be merged must have a parent node.
*
* @error merge-operation-target-position-invalid
*/
Expand Down
11 changes: 1 addition & 10 deletions src/model/operation/moveoperation.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,16 +123,7 @@ export default class MoveOperation extends Operation {
// Validate whether move operation has correct parameters.
// Validation is pretty complex but move operation is one of the core ways to manipulate the document state.
// We expect that many errors might be connected with one of scenarios described below.
if ( !sourceElement || !targetElement ) {
/**
* Source position or target position is invalid.
*
* @error move-operation-position-invalid
*/
throw new CKEditorError(
'move-operation-position-invalid: Source position or target position is invalid.', this
);
} else if ( sourceOffset + this.howMany > sourceElement.maxOffset ) {
if ( sourceOffset + this.howMany > sourceElement.maxOffset ) {
/**
* The nodes which should be moved do not exist.
*
Expand Down
Loading

0 comments on commit a9ac223

Please sign in to comment.