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/1643
Browse files Browse the repository at this point in the history
  • Loading branch information
jodator committed Aug 14, 2019
2 parents f922a0a + 89dbe43 commit 6f3ced2
Show file tree
Hide file tree
Showing 70 changed files with 1,425 additions and 291 deletions.
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
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
13 changes: 10 additions & 3 deletions src/model/documentfragment.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,22 @@ export default class DocumentFragment {
}

/**
* Checks whether given model tree object is of given type.
* Checks whether this object is of the given type.
*
* Read more in {@link module:engine/model/node~Node#is}.
* docFrag.is( 'documentFragment' ); // -> true
* docFrag.is( 'model:documentFragment' ); // -> true
*
* docFrag.is( 'view:documentFragment' ); // -> false
* docFrag.is( 'element' ); // -> false
* docFrag.is( 'node' ); // -> false
*
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
*
* @param {String} type
* @returns {Boolean}
*/
is( type ) {
return type == 'documentFragment';
return type == 'documentFragment' || type == 'model:documentFragment';
}

/**
Expand Down
22 changes: 14 additions & 8 deletions src/model/documentselection.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,21 +367,27 @@ export default class DocumentSelection {
}

/**
* Checks whether object is of given type following the convention set by
* {@link module:engine/model/node~Node#is `Node#is()`}.
* Checks whether this object is of the given type.
*
* const selection = new DocumentSelection( ... );
* selection.is( 'selection' ); // -> true
* selection.is( 'documentSelection' ); // -> true
* selection.is( 'model:selection' ); // -> true
* selection.is( 'model:documentSelection' ); // -> true
*
* selection.is( 'selection' ); // true
* selection.is( 'documentSelection' ); // true
* selection.is( 'node' ); // false
* selection.is( 'element' ); // false
* selection.is( 'view:selection' ); // -> false
* selection.is( 'element' ); // -> false
* selection.is( 'node' ); // -> false
*
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
*
* @param {String} type
* @returns {Boolean}
*/
is( type ) {
return type == 'selection' || type == 'documentSelection';
return type == 'selection' ||
type == 'model:selection' ||
type == 'documentSelection' ||
type == 'model:documentSelection';
}

/**
Expand Down
32 changes: 20 additions & 12 deletions 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 Expand Up @@ -89,29 +89,37 @@ export default class Element extends Node {
}

/**
* Checks whether this model object is of the given type.
* Checks whether this object is of the given.
*
* obj.name; // 'listItem'
* obj instanceof Element; // true
* element.is( 'element' ); // -> true
* element.is( 'node' ); // -> true
* element.is( 'model:element' ); // -> true
* element.is( 'model:node' ); // -> true
*
* obj.is( 'element' ); // true
* obj.is( 'listItem' ); // true
* obj.is( 'element', 'listItem' ); // true
* obj.is( 'text' ); // false
* obj.is( 'element', 'image' ); // false
* element.is( 'view:element' ); // -> false
* element.is( 'documentSelection' ); // -> false
*
* Read more in {@link module:engine/model/node~Node#is `Node#is()`}.
* Assuming that the object being checked is an element, you can also check its
* {@link module:engine/model/element~Element#name name}:
*
* element.is( 'image' ); // -> true if this is an <image> element
* element.is( 'element', 'image' ); // -> same as above
* text.is( 'image' ); -> false
*
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
*
* @param {String} type Type to check when `name` parameter is present.
* Otherwise, it acts like the `name` parameter.
* @param {String} [name] Element name.
* @returns {Boolean}
*/
is( type, name = null ) {
const cutType = type.replace( /^model:/, '' );

if ( !name ) {
return type == 'element' || type == this.name || super.is( type );
return cutType == 'element' || cutType == this.name || super.is( type );
} else {
return type == 'element' && name == this.name;
return cutType == 'element' && name == this.name;
}
}

Expand Down
20 changes: 20 additions & 0 deletions src/model/liveposition.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,26 @@ export default class LivePosition extends Position {
this.stopListening();
}

/**
* Checks whether this object is of the given.
*
* livePosition.is( 'position' ); // -> true
* livePosition.is( 'model:position' ); // -> true
* livePosition.is( 'liveposition' ); // -> true
* livePosition.is( 'model:livePosition' ); // -> true
*
* livePosition.is( 'view:position' ); // -> false
* livePosition.is( 'documentSelection' ); // -> false
*
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
*
* @param {String} type
* @returns {Boolean}
*/
is( type ) {
return type == 'livePosition' || type == 'model:livePosition' || super.is( type );
}

/**
* Creates a {@link module:engine/model/position~Position position instance}, which is equal to this live position.
*
Expand Down
20 changes: 20 additions & 0 deletions src/model/liverange.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ export default class LiveRange extends Range {
this.stopListening();
}

/**
* Checks whether this object is of the given.
*
* liveRange.is( 'range' ); // -> true
* liveRange.is( 'model:range' ); // -> true
* liveRange.is( 'liveRange' ); // -> true
* liveRange.is( 'model:liveRange' ); // -> true
*
* liveRange.is( 'view:range' ); // -> false
* liveRange.is( 'documentSelection' ); // -> false
*
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
*
* @param {String} type
* @returns {Boolean}
*/
is( type ) {
return type == 'liveRange' || type == 'model:liveRange' || super.is( type );
}

/**
* Creates a {@link module:engine/model/range~Range range instance} that is equal to this live range.
*
Expand Down
18 changes: 18 additions & 0 deletions src/model/markercollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,24 @@ class Marker {
return this._liveRange.toRange();
}

/**
* Checks whether this object is of the given.
*
* marker.is( 'marker' ); // -> true
* marker.is( 'model:marker' ); // -> true
*
* marker.is( 'view:element' ); // -> false
* marker.is( 'documentSelection' ); // -> false
*
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
*
* @param {String} type
* @returns {Boolean}
*/
is( type ) {
return type == 'marker' || type == 'model:marker';
}

/**
* Binds new live range to the marker and detach the old one if is attached.
*
Expand Down
70 changes: 47 additions & 23 deletions src/model/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,53 @@ export default class Node {
return json;
}

/**
* Checks whether this object is of the given type.
*
* This method is useful when processing model objects that are of unknown type. For example, a function
* may return a {@link module:engine/model/documentfragment~DocumentFragment} or a {@link module:engine/model/node~Node}
* that can be either a text node or an element. This method can be used to check what kind of object is returned.
*
* someObject.is( 'element' ); // -> true if this is an element
* someObject.is( 'node' ); // -> true if this is a node (a text node or an element)
* someObject.is( 'documentFragment' ); // -> true if this is a document fragment
*
* Since this method is also available on a range of view objects, you can prefix the type of the object with
* `model:` or `view:` to check, for example, if this is the model's or view's element:
*
* modelElement.is( 'model:element' ); // -> true
* modelElement.is( 'view:element' ); // -> false
*
* By using this method it is also possible to check a name of an element:
*
* imageElement.is( 'image' ); // -> true
* imageElement.is( 'element', 'image' ); // -> same as above
* imageElement.is( 'model:element', 'image' ); // -> same as above, but more precise
*
* The list of model objects which implement the `is()` method:
*
* * {@link module:engine/model/node~Node#is `Node#is()`}
* * {@link module:engine/model/text~Text#is `Text#is()`}
* * {@link module:engine/model/element~Element#is `Element#is()`}
* * {@link module:engine/model/rootelement~RootElement#is `RootElement#is()`}
* * {@link module:engine/model/position~Position#is `Position#is()`}
* * {@link module:engine/model/liveposition~LivePosition#is `LivePosition#is()`}
* * {@link module:engine/model/range~Range#is `Range#is()`}
* * {@link module:engine/model/liverange~LiveRange#is `LiveRange#is()`}
* * {@link module:engine/model/documentfragment~DocumentFragment#is `DocumentFragment#is()`}
* * {@link module:engine/model/selection~Selection#is `Selection#is()`}
* * {@link module:engine/model/documentselection~DocumentSelection#is `DocumentSelection#is()`}
* * {@link module:engine/model/markercollection~Marker#is `Marker#is()`}
* * {@link module:engine/model/textproxy~TextProxy#is `TextProxy#is()`}
*
* @method #is
* @param {String} type
* @returns {Boolean}
*/
is( type ) {
return type == 'node' || type == 'model:node';
}

/**
* Creates a copy of this node, that is a node with exactly same attributes, and returns it.
*
Expand Down Expand Up @@ -460,29 +507,6 @@ export default class Node {
_clearAttributes() {
this._attrs.clear();
}

/**
* Checks whether given model tree object is of given type.
*
* This method is useful when processing model tree objects that are of unknown type. For example, a function
* may return {@link module:engine/model/documentfragment~DocumentFragment} or {@link module:engine/model/node~Node}
* that can be either text node or element. This method can be used to check what kind of object is returned.
*
* obj.is( 'node' ); // true for any node, false for document fragment and text fragment
* obj.is( 'documentFragment' ); // true for document fragment, false for any node
* obj.is( 'element' ); // true for any element, false for text node or document fragment
* obj.is( 'element', 'paragraph' ); // true only for element which name is 'paragraph'
* obj.is( 'paragraph' ); // shortcut for obj.is( 'element', 'paragraph' )
* obj.is( 'text' ); // true for text node, false for element and document fragment
* obj.is( 'textProxy' ); // true for text proxy object
*
* @method #is
* @param {'element'|'rootElement'|'text'|'textProxy'|'documentFragment'} type
* @returns {Boolean}
*/
is( type ) {
return type == '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
Loading

0 comments on commit 6f3ced2

Please sign in to comment.