Socket
Socket
Sign inDemoInstall

@ckeditor/ckeditor5-engine

Package Overview
Dependencies
Maintainers
1
Versions
584
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ckeditor/ckeditor5-engine - npm Package Compare versions

Comparing version 20.0.0 to 21.0.0

src/view/rawelement.js

34

package.json
{
"name": "@ckeditor/ckeditor5-engine",
"version": "20.0.0",
"version": "21.0.0",
"description": "The editing engine of CKEditor 5 – the best browser-based rich text editor.",

@@ -24,21 +24,21 @@ "keywords": [

"dependencies": {
"@ckeditor/ckeditor5-utils": "^20.0.0",
"@ckeditor/ckeditor5-utils": "^21.0.0",
"lodash-es": "^4.17.15"
},
"devDependencies": {
"@ckeditor/ckeditor5-basic-styles": "^20.0.0",
"@ckeditor/ckeditor5-block-quote": "^20.0.0",
"@ckeditor/ckeditor5-core": "^20.0.0",
"@ckeditor/ckeditor5-editor-classic": "^20.0.0",
"@ckeditor/ckeditor5-enter": "^20.0.0",
"@ckeditor/ckeditor5-essentials": "^20.0.0",
"@ckeditor/ckeditor5-heading": "^20.0.0",
"@ckeditor/ckeditor5-link": "^20.0.0",
"@ckeditor/ckeditor5-list": "^20.0.0",
"@ckeditor/ckeditor5-paragraph": "^20.0.0",
"@ckeditor/ckeditor5-table": "^20.0.0",
"@ckeditor/ckeditor5-theme-lark": "^20.0.0",
"@ckeditor/ckeditor5-typing": "^20.0.0",
"@ckeditor/ckeditor5-undo": "^20.0.0",
"@ckeditor/ckeditor5-widget": "^20.0.0"
"@ckeditor/ckeditor5-basic-styles": "^21.0.0",
"@ckeditor/ckeditor5-block-quote": "^21.0.0",
"@ckeditor/ckeditor5-core": "^21.0.0",
"@ckeditor/ckeditor5-editor-classic": "^21.0.0",
"@ckeditor/ckeditor5-enter": "^21.0.0",
"@ckeditor/ckeditor5-essentials": "^21.0.0",
"@ckeditor/ckeditor5-heading": "^21.0.0",
"@ckeditor/ckeditor5-link": "^21.0.0",
"@ckeditor/ckeditor5-list": "^21.0.0",
"@ckeditor/ckeditor5-paragraph": "^21.0.0",
"@ckeditor/ckeditor5-table": "^21.0.0",
"@ckeditor/ckeditor5-theme-lark": "^21.0.0",
"@ckeditor/ckeditor5-typing": "^21.0.0",
"@ckeditor/ckeditor5-undo": "^21.0.0",
"@ckeditor/ckeditor5-widget": "^21.0.0"
},

@@ -45,0 +45,0 @@ "engines": {

@@ -93,3 +93,4 @@ /**

this.downcastDispatcher = new DowncastDispatcher( {
mapper: this.mapper
mapper: this.mapper,
schema: model.schema
} );

@@ -136,2 +137,3 @@ this.downcastDispatcher.on( 'insert:$text', insertText(), { priority: 'lowest' } );

this.decorate( 'init' );
this.decorate( 'set' );

@@ -321,2 +323,3 @@ // Fire `ready` event when initialisation has completed. Such low level listener gives possibility

*
* @fires set
* @param {String|Object.<String,String>} data Input data as a string or an object containing `rootName` - `data`

@@ -457,2 +460,11 @@ * pairs to set data on multiple roots at once.

*/
/**
* Event fired after {@link #set set() method} has been run.
*
* The `set` event is fired by decorated {@link #set} method.
* See {@link module:utils/observablemixin~ObservableMixin#decorate} for more information and samples.
*
* @event set
*/
}

@@ -459,0 +471,0 @@

@@ -68,3 +68,4 @@ /**

this.downcastDispatcher = new DowncastDispatcher( {
mapper: this.mapper
mapper: this.mapper,
schema: model.schema
} );

@@ -71,0 +72,0 @@

@@ -340,3 +340,3 @@ /**

*
* if ( viewElement.is( 'span' ) && fontWeight && /\d+/.test() && Number( fontWeight ) > 500 ) {
* if ( viewElement.is( 'element', 'span' ) && fontWeight && /\d+/.test() && Number( fontWeight ) > 500 ) {
* // Returned value can be an object with the matched properties.

@@ -392,3 +392,3 @@ * // These properties will be "consumed" during the conversion.

*
* if ( viewElement.is( 'span' ) && size > 10 ) {
* if ( viewElement.is( 'element', 'span' ) && size > 10 ) {
* // Returned value can be an object with the matched properties.

@@ -418,3 +418,3 @@ * // These properties will be "consumed" during the conversion.

*
* if ( viewElement.is( 'span' ) && size < 10 ) {
* if ( viewElement.is( 'element', 'span' ) && size < 10 ) {
* // Returned value can be an object with the matched properties.

@@ -421,0 +421,0 @@ * // These properties will be "consumed" during the conversion.

@@ -662,2 +662,8 @@ /**

/**
* The {@link module:engine/model/schema~Schema} instance set for the model that is downcast.
*
* @member {module:engine/model/schema~Schema} #schema
*/
/**
* The {@link module:engine/view/downcastwriter~DowncastWriter} instance used to manipulate data during conversion.

@@ -664,0 +670,0 @@ *

@@ -107,3 +107,3 @@ /**

data.viewPosition = this._findPositionIn( viewContainer, data.modelPosition.offset );
data.viewPosition = this.findPositionIn( viewContainer, data.modelPosition.offset );
}, { priority: 'low' } );

@@ -449,3 +449,3 @@

// If the position is a text it is simple ("ba|r" -> 2).
if ( viewParent.is( 'text' ) ) {
if ( viewParent.is( '$text' ) ) {
return viewOffset;

@@ -493,3 +493,3 @@ }

return 1;
} else if ( viewNode.is( 'text' ) ) {
} else if ( viewNode.is( '$text' ) ) {
return viewNode.data.length;

@@ -516,3 +516,3 @@ } else if ( viewNode.is( 'uiElement' ) ) {

*
* _findPositionIn( p, 4 ):
* findPositionIn( p, 4 ):
* <p>|fo<b>bar</b>bom</p> -> expected offset: 4, actual offset: 0

@@ -522,11 +522,10 @@ * <p>fo|<b>bar</b>bom</p> -> expected offset: 4, actual offset: 2

*
* _findPositionIn( b, 4 - ( 5 - 3 ) ):
* findPositionIn( b, 4 - ( 5 - 3 ) ):
* <p>fo<b>|bar</b>bom</p> -> expected offset: 2, actual offset: 0
* <p>fo<b>bar|</b>bom</p> -> expected offset: 2, actual offset: 3 -> we are too far
*
* _findPositionIn( bar, 2 - ( 3 - 3 ) ):
* findPositionIn( bar, 2 - ( 3 - 3 ) ):
* We are in the text node so we can simple find the offset.
* <p>fo<b>ba|r</b>bom</p> -> expected offset: 2, actual offset: 2 -> position found
*
* @private
* @param {module:engine/view/element~Element} viewParent Tree view element in which we are looking for the position.

@@ -536,3 +535,3 @@ * @param {Number} expectedOffset Expected offset.

*/
_findPositionIn( viewParent, expectedOffset ) {
findPositionIn( viewParent, expectedOffset ) {
// Last scanned view node.

@@ -547,3 +546,3 @@ let viewNode;

// In the text node it is simple: offset in the model equals offset in the text.
if ( viewParent.is( 'text' ) ) {
if ( viewParent.is( '$text' ) ) {
return new ViewPosition( viewParent, expectedOffset );

@@ -570,3 +569,3 @@ }

// so we subtract it from the expected offset to fine the offset in the child.
return this._findPositionIn( viewNode, expectedOffset - ( modelOffset - lastLength ) );
return this.findPositionIn( viewNode, expectedOffset - ( modelOffset - lastLength ) );
}

@@ -643,3 +642,3 @@ }

* // Check if this is the element we are interested in.
* if ( !sibling.is( 'customElement' ) ) {
* if ( !sibling.is( 'element', 'customElement' ) ) {
* return;

@@ -646,0 +645,0 @@ * }

@@ -240,3 +240,3 @@ /**

this.fire( 'element:' + viewItem.name, data, this.conversionApi );
} else if ( viewItem.is( 'text' ) ) {
} else if ( viewItem.is( '$text' ) ) {
this.fire( 'text', data, this.conversionApi );

@@ -243,0 +243,0 @@ } else {

@@ -12,3 +12,8 @@ /**

import ModelSelection from '../model/selection';
import { attachLinkToDocumentation } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
import priorities from '@ckeditor/ckeditor5-utils/src/priorities';
/* global console */
/**

@@ -291,2 +296,4 @@ * Contains {@link module:engine/view/view view} to {@link module:engine/model/model model} converters for

*
* **Note**: This method was deprecated. Please use {@link #dataToMarker} instead.
*
* This conversion results in creating a model marker. For example, if the marker was stored in a view as an element:

@@ -326,2 +333,3 @@ * `<p>Fo<span data-marker="comment" data-comment-id="7"></span>o</p><p>B<span data-marker="comment" data-comment-id="7"></span>ar</p>`,

*
* @deprecated
* @method #elementToMarker

@@ -336,4 +344,89 @@ * @param {Object} config Conversion configuration.

elementToMarker( config ) {
/**
* The {@link module:engine/conversion/upcasthelpers~UpcastHelpers#elementToMarker `UpcastHelpers#elementToMarker()`}
* method has been deprecated and will be removed in the near future.
* Please use {@link module:engine/conversion/upcasthelpers~UpcastHelpers#dataToMarker `UpcastHelpers#dataToMarker()`} instead.
*
* @error upcast-helpers-element-to-marker-deprecated
*/
console.warn(
attachLinkToDocumentation(
'upcast-helpers-element-to-marker-deprecated: ' +
'The UpcastHelpers#elementToMarker() method has been deprecated and will be removed in the near future. ' +
'Please use UpcastHelpers#dataToMarker() instead.'
)
);
return this.add( upcastElementToMarker( config ) );
}
/**
* View to model marker conversion helper.
*
* Converts view data created by {@link module:engine/conversion/downcasthelpers~DowncastHelpers#markerToData `#markerToData()`}
* back to a model marker.
*
* This converter looks for specific view elements and view attributes that mark marker boundaries. See
* {@link module:engine/conversion/downcasthelpers~DowncastHelpers#markerToData `#markerToData()`} to learn what view data
* is expected by this converter.
*
* The `config.view` property is equal to the marker group name to convert.
*
* By default, this converter creates markers with `group:name` name convention (to match the default `markerToData` conversion).
*
* The conversion configuration can take a function that will generate a marker name.
* If such function is set as the `config.model` parameter, it is passed the `name` part from the view element or attribute and it is
* expected to return a string with the marker name.
*
* Basic usage:
*
* // Using the default conversion.
* // In this case, all markers from `comment` group will be converted.
* // The conversion will look for `<comment-start>` and `<comment-end>` tags and
* // `data-comment-start-before`, `data-comment-start-after`,
* // `data-comment-end-before` and `data-comment-end-after` attributes.
* editor.conversion.for( 'upcast' ).dataToMarker( {
* view: 'comment'
* } );
*
* An example of a model that may be generated by this conversion:
*
* // View:
* <p>Foo<comment-start name="commentId:uid"></comment-start>bar</p>
* <figure data-comment-end-after="commentId:uid" class="image"><img src="abc.jpg" /></figure>
*
* // Model:
* <paragraph>Foo[bar</paragraph>
* <image src="abc.jpg"></image>]
*
* Where `[]` are boundaries of a marker that will receive `comment:commentId:uid` name.
*
* Other examples of usage:
*
* // Using custom function which is the same as the default conversion:
* editor.conversion.for( 'upcast' ).dataToMarker( {
* view: 'comment',
* model: name => 'comment:' + name,
* } );
*
* // Using converter priority:
* editor.conversion.for( 'upcast' ).dataToMarker( {
* view: 'comment',
* model: name => 'comment:' + name,
* converterPriority: 'high'
* } );
*
* See {@link module:engine/conversion/conversion~Conversion#for `conversion.for()`} to learn how to add a converter
* to the conversion process.
*
* @method #dataToMarker
* @param {Object} config Conversion configuration.
* @param {String} config.view Marker group name to convert.
* @param {Function} [config.model] Function that takes `name` part from the view element or attribute and returns the marker name.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {module:engine/conversion/upcasthelpers~UpcastHelpers}
*/
dataToMarker( config ) {
return this.add( upcastDataToMarker( config ) );
}
}

@@ -519,3 +612,3 @@

normalizeToMarkerConfig( config );
normalizeElementToMarkerConfig( config );

@@ -525,2 +618,105 @@ return upcastElementToElement( config );

// View data to model marker conversion helper.
//
// See {@link ~UpcastHelpers#dataToMarker} to learn more.
//
// @param {Object} config
// @param {String} config.view
// @param {Function} [config.model]
// @param {module:utils/priorities~PriorityString} [config.converterPriority='normal']
// @returns {Function} Conversion helper.
function upcastDataToMarker( config ) {
config = cloneDeep( config );
// Default conversion.
if ( !config.model ) {
config.model = name => {
return name ? config.view + ':' + name : config.view;
};
}
const converterStart = prepareToElementConverter( normalizeDataToMarkerConfig( config, 'start' ) );
const converterEnd = prepareToElementConverter( normalizeDataToMarkerConfig( config, 'end' ) );
return dispatcher => {
dispatcher.on( 'element:' + config.view + '-start', converterStart, { priority: config.converterPriority || 'normal' } );
dispatcher.on( 'element:' + config.view + '-end', converterEnd, { priority: config.converterPriority || 'normal' } );
// Below is a hack that is needed to properly handle `converterPriority` for both elements and attributes.
// Attribute conversion needs to be performed *after* element conversion.
// This converter handles both element conversion and attribute conversion, which means that if a single
// `config.converterPriority` is used, it will lead to problems. For example, if `'high'` priority is used,
// then attribute conversion will be performed before a lot of element upcast converters.
// On the other hand we want to support `config.converterPriority` and overwriting conveters.
//
// To have it work, we need to do some extra processing for priority for attribute converter.
// Priority `'low'` value should be the base value and then we will change it depending on `config.converterPriority` value.
//
// This hack probably would not be needed if attributes are upcasted separately.
//
const basePriority = priorities.get( 'low' );
const maxPriority = priorities.get( 'highest' );
const priorityFactor = priorities.get( config.converterPriority ) / maxPriority; // Number in range [ -1, 1 ].
dispatcher.on( 'element', upcastAttributeToMarker( config ), { priority: basePriority + priorityFactor } );
};
}
// Function factory, returns a callback function which converts view attributes to a model marker.
//
// The converter looks for elements with `data-group-start-before`, `data-group-start-after`, `data-group-end-before`
// and `data-group-end-after` attributes and inserts `$marker` model elements before/after those elements.
// `group` part is specified in `config.view`.
//
// @param {Object} config
// @param {String} config.view
// @param {Function} [config.model]
// @returns {Function} Marker converter.
function upcastAttributeToMarker( config ) {
return ( evt, data, conversionApi ) => {
const attrName = `data-${ config.view }`;
// This converter wants to add a model element, marking a marker, before/after an element (or maybe even group of elements).
// To do that, we can use `data.modelRange` which is set on an element (or a group of elements) that has been upcasted.
// But, if the processed view element has not been upcasted yet (it does not have been converted), we need to
// fire conversion for its children first, then we will have `data.modelRange` available.
if ( !data.modelRange ) {
data = Object.assign( data, conversionApi.convertChildren( data.viewItem, data.modelCursor ) );
}
if ( conversionApi.consumable.consume( data.viewItem, { attributes: attrName + '-end-after' } ) ) {
addMarkerElements( data.modelRange.end, data.viewItem.getAttribute( attrName + '-end-after' ).split( ',' ) );
}
if ( conversionApi.consumable.consume( data.viewItem, { attributes: attrName + '-start-after' } ) ) {
addMarkerElements( data.modelRange.end, data.viewItem.getAttribute( attrName + '-start-after' ).split( ',' ) );
}
if ( conversionApi.consumable.consume( data.viewItem, { attributes: attrName + '-end-before' } ) ) {
addMarkerElements( data.modelRange.start, data.viewItem.getAttribute( attrName + '-end-before' ).split( ',' ) );
}
if ( conversionApi.consumable.consume( data.viewItem, { attributes: attrName + '-start-before' } ) ) {
addMarkerElements( data.modelRange.start, data.viewItem.getAttribute( attrName + '-start-before' ).split( ',' ) );
}
function addMarkerElements( position, markerViewNames ) {
for ( const markerViewName of markerViewNames ) {
const markerName = config.model( markerViewName );
const element = conversionApi.writer.createElement( '$marker', { 'data-name': markerName } );
conversionApi.writer.insert( element, position );
if ( data.modelCursor.isEqual( position ) ) {
data.modelCursor = data.modelCursor.getShiftedBy( 1 );
} else {
data.modelCursor = data.modelCursor._getTransformedByInsertion( position, 1 );
}
data.modelRange = data.modelRange._getTransformedByInsertion( position, 1 )[ 0 ];
}
}
};
}
// Helper function for from-view-element conversion. Checks if `config.view` directly specifies converted view element's name

@@ -788,6 +984,6 @@ // and if so, returns it.

// Helper function for upcasting-to-marker conversion. Takes the config in a format requested by `upcastElementToMarker()`
// function and converts it to a format that is supported by `_upcastElementToElement()` function.
// function and converts it to a format that is supported by `upcastElementToElement()` function.
//
// @param {Object} config Conversion configuration.
function normalizeToMarkerConfig( config ) {
function normalizeElementToMarkerConfig( config ) {
const oldModel = config.model;

@@ -801,1 +997,21 @@

}
// Helper function for upcasting-to-marker conversion. Takes the config in a format requested by `upcastDataToMarker()`
// function and converts it to a format that is supported by `upcastElementToElement()` function.
//
// @param {Object} config Conversion configuration.
function normalizeDataToMarkerConfig( config, type ) {
const configForElements = {};
// Upcast <markerGroup-start> and <markerGroup-end> elements.
configForElements.view = config.view + '-' + type;
configForElements.model = ( viewElement, modelWriter ) => {
const viewName = viewElement.getAttribute( 'name' );
const markerName = config.model( viewName );
return modelWriter.createElement( '$marker', { 'data-name': markerName } );
};
return configForElements;
}

@@ -83,3 +83,3 @@ /**

// For text nodes and document fragments just mark them as consumable.
if ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {
if ( element.is( '$text' ) || element.is( 'documentFragment' ) ) {
this._consumables.set( element, true );

@@ -138,3 +138,3 @@

// For text nodes and document fragments return stored boolean value.
if ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {
if ( element.is( '$text' ) || element.is( 'documentFragment' ) ) {
return elementConsumables;

@@ -177,3 +177,3 @@ }

if ( this.test( element, consumables ) ) {
if ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {
if ( element.is( '$text' ) || element.is( 'documentFragment' ) ) {
// For text nodes and document fragments set value to false.

@@ -224,3 +224,3 @@ this._consumables.set( element, false );

if ( elementConsumables !== undefined ) {
if ( element.is( 'text' ) || element.is( 'documentFragment' ) ) {
if ( element.is( '$text' ) || element.is( 'documentFragment' ) ) {
// For text nodes and document fragments - set consumable to true.

@@ -294,3 +294,3 @@ this._consumables.set( element, true );

if ( from.is( 'text' ) ) {
if ( from.is( '$text' ) ) {
instance.add( from );

@@ -297,0 +297,0 @@

@@ -231,3 +231,3 @@ /**

downcastDispatcher.on( 'attribute', ( evt, data, conversionApi ) => {
if ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection || data.item.is( 'textProxy' ) ) {
if ( data.item instanceof ModelSelection || data.item instanceof DocumentSelection || data.item.is( '$textProxy' ) ) {
const converter = wrap( ( modelAttributeValue, viewWriter ) => {

@@ -234,0 +234,0 @@ return viewWriter.createAttributeElement(

@@ -28,2 +28,3 @@ /**

import UIElement from '../view/uielement';
import RawElement from '../view/rawelement';
import { StylesProcessor } from '../view/stylesmap';

@@ -39,3 +40,4 @@

'empty': EmptyElement,
'ui': UIElement
'ui': UIElement,
'raw': RawElement
};

@@ -60,2 +62,4 @@

* {@link module:engine/view/uielement~UIElement} will be printed.
* @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
* {@link module:engine/view/rawelement~RawElement} will be printed.
* @returns {String} The stringified data.

@@ -76,2 +80,3 @@ */

renderUIElements: options.renderUIElements,
renderRawElements: options.renderRawElements,
ignoreRoot: true

@@ -241,2 +246,4 @@ };

* {@link module:engine/view/uielement~UIElement} will be printed.
* @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
* {@link module:engine/view/rawelement~RawElement} will be printed.
* @returns {String} An HTML-like string representing the view.

@@ -460,3 +467,3 @@ */

if ( node.is( 'text' ) ) {
if ( node.is( '$text' ) ) {
const regexp = new RegExp(

@@ -631,2 +638,4 @@ `[${ TEXT_RANGE_START_TOKEN }${ TEXT_RANGE_END_TOKEN }\\${ ELEMENT_RANGE_END_TOKEN }\\${ ELEMENT_RANGE_START_TOKEN }]`,

* {@link module:engine/view/uielement~UIElement} will be printed.
* @param {Boolean} [options.renderRawElements=false] When set to `true`, the inner content of each
* {@link module:engine/view/rawelement~RawElement} will be printed.
*/

@@ -648,2 +657,3 @@ constructor( root, selection, options ) {

this.renderUIElements = !!options.renderUIElements;
this.renderRawElements = !!options.renderRawElements;
}

@@ -681,4 +691,11 @@

if ( this.renderUIElements && root.is( 'uiElement' ) ) {
if ( ( this.renderUIElements && root.is( 'uiElement' ) ) ) {
callback( root.render( document ).innerHTML );
} else if ( this.renderRawElements && root.is( 'rawElement' ) ) {
// There's no DOM element for "root" to pass to render(). Creating
// a surrogate container to render the children instead.
const rawContentContainer = document.createElement( 'div' );
root.render( rawContentContainer );
callback( rawContentContainer.innerHTML );
} else {

@@ -700,3 +717,3 @@ let offset = 0;

if ( root.is( 'text' ) ) {
if ( root.is( '$text' ) ) {
callback( this._stringifyTextRanges( root ) );

@@ -837,4 +854,5 @@ }

* * 'container' for {@link module:engine/view/containerelement~ContainerElement container elements},
* * 'empty' for {@link module:engine/view/emptyelement~EmptyElement empty elements}.
* * 'ui' for {@link module:engine/view/uielement~UIElement UI elements}.
* * 'empty' for {@link module:engine/view/emptyelement~EmptyElement empty elements},
* * 'ui' for {@link module:engine/view/uielement~UIElement UI elements},
* * 'raw' for {@link module:engine/view/rawelement~RawElement raw elements},
* * an empty string when the current configuration is preventing showing elements' types.

@@ -957,6 +975,6 @@ *

throw new Error( 'Parse error - cannot parse inside EmptyElement.' );
}
if ( convertedElement.is( 'uiElement' ) ) {
} else if ( convertedElement.is( 'uiElement' ) ) {
throw new Error( 'Parse error - cannot parse inside UIElement.' );
} else if ( convertedElement.is( 'rawElement' ) ) {
throw new Error( 'Parse error - cannot parse inside RawElement.' );
}

@@ -963,0 +981,0 @@

@@ -1042,3 +1042,3 @@ /**

for ( const child of children ) {
if ( child.is( 'text' ) ) {
if ( child.is( '$text' ) ) {
for ( let i = 0; i < child.data.length; i++ ) {

@@ -1045,0 +1045,0 @@ snapshot.push( {

@@ -338,3 +338,3 @@ /**

// @if CK_DEBUG_ENGINE // if ( child.is( 'text' ) ) {
// @if CK_DEBUG_ENGINE // if ( child.is( '$text' ) ) {
// @if CK_DEBUG_ENGINE // const textAttrs = stringifyMap( child._attrs );

@@ -341,0 +341,0 @@

@@ -570,3 +570,2 @@ /**

//
class LiveSelection extends Selection {

@@ -606,6 +605,6 @@ // Creates an empty live selection for given {@link module:engine/model/document~Document}.

// Contains data required to fix ranges which have been moved to the graveyard.
// Position to which the selection should be set if the last selection range was moved to the graveyard.
// @private
// @member {Array} module:engine/model/liveselection~LiveSelection#_fixGraveyardRangesData
this._fixGraveyardRangesData = [];
// @member {module:engine/model/position~Position} module:engine/model/liveselection~LiveSelection#_selectionRestorePosition
this._selectionRestorePosition = null;

@@ -633,8 +632,10 @@ // Flag that informs whether the selection ranges have changed. It is changed on true when `LiveRange#change:range` event is fired.

while ( this._fixGraveyardRangesData.length ) {
const { liveRange, sourcePosition } = this._fixGraveyardRangesData.shift();
this._fixGraveyardSelection( liveRange, sourcePosition );
// Fix selection if the last range was removed from it and we have a position to which we can restore the selection.
if ( this._ranges.length == 0 && this._selectionRestorePosition ) {
this._fixGraveyardSelection( this._selectionRestorePosition );
}
// "Forget" the restore position even if it was not "used".
this._selectionRestorePosition = null;
if ( this._hasChangedRange ) {

@@ -833,11 +834,13 @@ this._hasChangedRange = false;

// If selection range is moved to the graveyard remove it from the selection object.
// Also, save some data that can be used to restore selection later, on `Model#applyOperation` event.
liveRange.on( 'change:range', ( evt, oldRange, data ) => {
this._hasChangedRange = true;
// If `LiveRange` is in whole moved to the graveyard, save necessary data. It will be fixed on `Model#applyOperation` event.
if ( liveRange.root == this._document.graveyard ) {
this._fixGraveyardRangesData.push( {
liveRange,
sourcePosition: data.deletionPosition
} );
this._selectionRestorePosition = data.deletionPosition;
const index = this._ranges.indexOf( liveRange );
this._ranges.splice( index, 1 );
liveRange.detach();
}

@@ -1124,32 +1127,16 @@ } );

// Fixes a selection range after it ends up in graveyard root.
// Fixes the selection after all its ranges got removed.
//
// @private
// @param {module:engine/model/liverange~LiveRange} liveRange The range from selection, that ended up in the graveyard root.
// @param {module:engine/model/position~Position} removedRangeStart Start position of a range which was removed.
_fixGraveyardSelection( liveRange, removedRangeStart ) {
// The start of the removed range is the closest position to the `liveRange` - the original selection range.
// This is a good candidate for a fixed selection range.
const positionCandidate = removedRangeStart.clone();
// @param {module:engine/model/position~Position} deletionPosition Position where the deletion happened.
_fixGraveyardSelection( deletionPosition ) {
// Find a range that is a correct selection range and is closest to the position where the deletion happened.
const selectionRange = this._model.schema.getNearestSelectionRange( deletionPosition );
// Find a range that is a correct selection range and is closest to the start of removed range.
const selectionRange = this._model.schema.getNearestSelectionRange( positionCandidate );
// Remove the old selection range before preparing and adding new selection range. This order is important,
// because new range, in some cases, may intersect with old range (it depends on `getNearestSelectionRange()` result).
const index = this._ranges.indexOf( liveRange );
this._ranges.splice( index, 1 );
liveRange.detach();
// If nearest valid selection range has been found - add it in the place of old range.
// If range is equal to any other selection ranges then it is probably due to contents
// of a multi-range selection being removed. See ckeditor/ckeditor5#6501.
if ( selectionRange && !isRangeCollidingWithSelection( selectionRange, this ) ) {
if ( selectionRange ) {
// Check the range, convert it to live range, bind events, etc.
const newRange = this._prepareRange( selectionRange );
// Add new range in the place of old range.
this._ranges.splice( index, 0, newRange );
this._pushRange( selectionRange );
}
// If nearest valid selection range cannot be found or is intersecting with other selection ranges removing the old range is fine.
// If nearest valid selection range cannot be found don't add any range. Selection will be set to the default range.
}

@@ -1199,6 +1186,1 @@ }

}
// Checks if range collides with any of selection ranges.
function isRangeCollidingWithSelection( range, selection ) {
return !selection._ranges.every( selectionRange => !range.isEqual( selectionRange ) );
}

@@ -107,10 +107,9 @@ /**

*
* element.is( 'image' ); // -> true if this is an <image> element
* element.is( 'element', 'image' ); // -> true if this is an <image> element
* element.is( 'element', 'image' ); // -> same as above
* text.is( 'image' ); -> false
* text.is( 'element', '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} type Type to check.
* @param {String} [name] Element name.

@@ -122,3 +121,2 @@ * @returns {Boolean}

return type === 'element' || type === 'model:element' ||
type === this.name || type === 'model:' + this.name ||
// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.

@@ -215,2 +213,24 @@ type === 'node' || type === 'model:node';

/**
* Returns the parent element of the given name. Returns null if the element is not inside the desired parent.
*
* @param {String} parentName The name of the parent element to find.
* @param {Object} [options] Options object.
* @param {Boolean} [options.includeSelf=false] When set to `true` this node will be also included while searching.
* @returns {module:engine/model/element~Element|null}
*/
findAncestor( parentName, options = { includeSelf: false } ) {
let parent = options.includeSelf ? this : this.parent;
while ( parent ) {
if ( parent.name === parentName ) {
return parent;
}
parent = parent.parent;
}
return null;
}
/**
* Converts `Element` instance to plain object and returns it. Takes care of converting all of this element's children.

@@ -365,3 +385,3 @@ *

// @if CK_DEBUG_ENGINE // if ( child.is( 'text' ) ) {
// @if CK_DEBUG_ENGINE // if ( child.is( '$text' ) ) {
// @if CK_DEBUG_ENGINE // const textAttrs = convertMapToTags( child._attrs );

@@ -368,0 +388,0 @@

@@ -95,2 +95,12 @@ /**

const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
if ( markerName.includes( ',' ) ) {
/**
* Marker name cannot contain the "," character.
*
* @error markercollection-incorrect-marker-name
*/
throw new CKEditorError( 'markercollection-incorrect-marker-name: Marker name cannot contain "," character.', this );
}
const oldMarker = this._markers.get( markerName );

@@ -97,0 +107,0 @@

@@ -576,3 +576,3 @@ /**

for ( const item of range.getItems() ) {
if ( item.is( 'textProxy' ) ) {
if ( item.is( '$textProxy' ) ) {
if ( !ignoreWhitespaces ) {

@@ -579,0 +579,0 @@ return true;

@@ -409,3 +409,3 @@ /**

*
* imageElement.is( 'image' ); // -> true
* imageElement.is( 'element', 'image' ); // -> true
* imageElement.is( 'element', 'image' ); // -> same as above

@@ -431,3 +431,3 @@ * imageElement.is( 'model:element', 'image' ); // -> same as above, but more precise

* @method #is
* @param {String} type
* @param {String} type Type to check.
* @returns {Boolean}

@@ -434,0 +434,0 @@ */

@@ -146,3 +146,3 @@ /**

// So, we can operate on those text proxies' text nodes.
const node = item.is( 'textProxy' ) ? item.textNode : item;
const node = item.is( '$textProxy' ) ? item.textNode : item;

@@ -223,3 +223,3 @@ if ( value !== null ) {

// Check if both of those nodes are text objects with same attributes.
if ( nodeBefore && nodeAfter && nodeBefore.is( 'text' ) && nodeAfter.is( 'text' ) && _haveSameAttributes( nodeBefore, nodeAfter ) ) {
if ( nodeBefore && nodeAfter && nodeBefore.is( '$text' ) && nodeAfter.is( '$text' ) && _haveSameAttributes( nodeBefore, nodeAfter ) ) {
// Append text of text node after index to the before one.

@@ -226,0 +226,0 @@ const mergedNode = new Text( nodeBefore.data + nodeAfter.data, nodeBefore.getAttributes() );

@@ -149,5 +149,2 @@ /**

/**
* @param {Number} newOffset
*/
set offset( newOffset ) {

@@ -180,3 +177,3 @@ this.path[ this.path.length - 1 ] = newOffset;

if ( parent.is( 'text' ) ) {
if ( parent.is( '$text' ) ) {
/**

@@ -360,2 +357,18 @@ * The position's path is incorrect. This means that a position does not point to

/**
* Returns the parent element of the given name. Returns null if the position is not inside the desired parent.
*
* @param {String} parentName The name of the parent element to find.
* @returns {module:engine/model/element~Element|null}
*/
findAncestor( parentName ) {
const parent = this.parent;
if ( parent.is( 'element' ) ) {
return parent.findAncestor( parentName, { includeSelf: true } );
}
return null;
}
/**
* Returns the slice of two position {@link #path paths} which is identical. The {@link #root roots}

@@ -1096,3 +1109,3 @@ * of these two paths must be identical.

if ( node && node.is( 'text' ) && node.startOffset < position.offset ) {
if ( node && node.is( '$text' ) && node.startOffset < position.offset ) {
return node;

@@ -1099,0 +1112,0 @@ }

@@ -280,2 +280,59 @@ /**

/**
* Returns a range created by joining this {@link ~Range range} with the given {@link ~Range range}.
* If ranges have no common part, returns `null`.
*
* Examples:
*
* let range = model.createRange(
* model.createPositionFromPath( root, [ 2, 7 ] ),
* model.createPositionFromPath( root, [ 4, 0, 1 ] )
* );
* let otherRange = model.createRange(
* model.createPositionFromPath( root, [ 1 ] ),
* model.createPositionFromPath( root, [ 2 ] )
* );
* let transformed = range.getJoined( otherRange ); // null - ranges have no common part
*
* otherRange = model.createRange(
* model.createPositionFromPath( root, [ 3 ] ),
* model.createPositionFromPath( root, [ 5 ] )
* );
* transformed = range.getJoined( otherRange ); // range from [ 2, 7 ] to [ 5 ]
*
* @param {module:engine/model/range~Range} otherRange Range to be joined.
* @param {Boolean} [loose=false] Whether the intersection check is loose or strict. If the check is strict (`false`),
* ranges are tested for intersection or whether start/end positions are equal. If the check is loose (`true`),
* compared range is also checked if it's {@link module:engine/model/position~Position#isTouching touching} current range.
* @returns {module:engine/model/range~Range|null} A sum of given ranges or `null` if ranges have no common part.
*/
getJoined( otherRange, loose = false ) {
let shouldJoin = this.isIntersecting( otherRange );
if ( !shouldJoin ) {
if ( this.start.isBefore( otherRange.start ) ) {
shouldJoin = loose ? this.end.isTouching( otherRange.start ) : this.end.isEqual( otherRange.start );
} else {
shouldJoin = loose ? otherRange.end.isTouching( this.start ) : otherRange.end.isEqual( this.start );
}
}
if ( !shouldJoin ) {
return null;
}
let startPosition = this.start;
let endPosition = this.end;
if ( otherRange.start.isBefore( startPosition ) ) {
startPosition = otherRange.start;
}
if ( otherRange.end.isAfter( endPosition ) ) {
endPosition = otherRange.end;
}
return new Range( startPosition, endPosition );
}
/**
* Computes and returns the smallest set of {@link #isFlat flat} ranges, that covers this range in whole.

@@ -282,0 +339,0 @@ *

@@ -71,10 +71,7 @@ /**

*
* rootElement.is( '$root' ); // -> true if this is a $root element
* rootElement.is( 'rootElement', '$root' ); // -> same as above
* text.is( '$root' ); -> 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} type Type to check.
* @param {String} [name] Element name.

@@ -88,3 +85,2 @@ * @returns {Boolean}

type === 'element' || type === 'model:element' ||
type === this.name || type === 'model:' + this.name ||
type === 'node' || type === 'model:node';

@@ -91,0 +87,0 @@ }

@@ -189,3 +189,3 @@ /**

itemName = item;
} else if ( item.is && ( item.is( 'text' ) || item.is( 'textProxy' ) ) ) {
} else if ( item.is && ( item.is( '$text' ) || item.is( '$textProxy' ) ) ) {
itemName = '$text';

@@ -224,3 +224,3 @@ }

*
* See the {@glink framework/guides/deep-dive/schema#block-elements Block elements} section of the Schema deep dive}
* See the {@glink framework/guides/deep-dive/schema#block-elements Block elements} section of the Schema deep dive
* guide for more details.

@@ -250,3 +250,3 @@ *

*
* See the {@glink framework/guides/deep-dive/schema#limit-elements Limit elements} section of the Schema deep dive}
* See the {@glink framework/guides/deep-dive/schema#limit-elements Limit elements} section of the Schema deep dive
* guide for more details.

@@ -280,3 +280,3 @@ *

*
* See the {@glink framework/guides/deep-dive/schema#object-elements Object elements} section of the Schema deep dive}
* See the {@glink framework/guides/deep-dive/schema#object-elements Object elements} section of the Schema deep dive
* guide for more details.

@@ -302,3 +302,3 @@ *

*
* See the {@glink framework/guides/deep-dive/schema#inline-elements Inline elements} section of the Schema deep dive}
* See the {@glink framework/guides/deep-dive/schema#inline-elements Inline elements} section of the Schema deep dive
* guide for more details.

@@ -782,3 +782,3 @@ *

// When node is a `Text` it has no children, so just filter it out.
if ( node.is( 'text' ) ) {
if ( node.is( '$text' ) ) {
removeDisallowedAttributeFromNode( this, node, writer );

@@ -785,0 +785,0 @@ }

@@ -70,8 +70,8 @@ /**

*
* text.is( 'text' ); // -> true
* text.is( '$text' ); // -> true
* text.is( 'node' ); // -> true
* text.is( 'model:text' ); // -> true
* text.is( 'model:$text' ); // -> true
* text.is( 'model:node' ); // -> true
*
* text.is( 'view:text' ); // -> false
* text.is( 'view:$text' ); // -> false
* text.is( 'documentSelection' ); // -> false

@@ -81,8 +81,12 @@ *

*
* @param {String} type Type to check when `name` parameter is present.
* Otherwise, it acts like the `name` parameter.
* **Note:** Until version 20.0.0 this method wasn't accepting `'$text'` type. The legacy `'text'` type is still
* accepted for backward compatibility.
*
* @param {String} type Type to check.
* @returns {Boolean}
*/
is( type ) {
return type === 'text' || type === 'model:text' ||
return type === '$text' || type === 'model:$text' ||
// This are legacy values kept for backward compatibility.
type === 'text' || type === 'model:text' ||
// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.

@@ -89,0 +93,0 @@ type === 'node' || type === 'model:node';

@@ -169,6 +169,6 @@ /**

*
* textProxy.is( 'textProxy' ); // -> true
* textProxy.is( 'model:textProxy' ); // -> true
* textProxy.is( '$textProxy' ); // -> true
* textProxy.is( 'model:$textProxy' ); // -> true
*
* textProxy.is( 'view:textProxy' ); // -> false
* textProxy.is( 'view:$textProxy' ); // -> false
* textProxy.is( 'range' ); // -> false

@@ -178,7 +178,12 @@ *

*
* @param {String} type
* **Note:** Until version 20.0.0 this method wasn't accepting `'$textProxy'` type. The legacy `'textProxt'` type is still
* accepted for backward compatibility.
*
* @param {String} type Type to check.
* @returns {Boolean}
*/
is( type ) {
return type === 'textProxy' || type === 'model:textProxy';
return type === '$textProxy' || type === 'model:$textProxy' ||
// This are legacy values kept for backward compatibility.
type === 'textProxy' || type === 'model:textProxy';
}

@@ -185,0 +190,0 @@

@@ -413,3 +413,3 @@ /**

*
* @typedef {'forward'|'backward'} module:engine/view/treewalker~TreeWalkerDirection
* @typedef {'forward'|'backward'} module:engine/model/treewalker~TreeWalkerDirection
*/

@@ -73,3 +73,3 @@ /**

for ( const item of flatSubtreeRange.getItems( { shallow: true } ) ) {
if ( item.is( 'textProxy' ) ) {
if ( item.is( '$textProxy' ) ) {
writer.appendText( item.data, item.getAttributes(), frag );

@@ -76,0 +76,0 @@ } else {

@@ -176,3 +176,3 @@ /**

// Scan only text nodes. Ignore inline elements (like `<softBreak>`).
if ( nextNode && nextNode.is( 'text' ) ) {
if ( nextNode && nextNode.is( '$text' ) ) {
// Check boundary char of an adjacent text node.

@@ -179,0 +179,0 @@ const boundaryChar = nextNode.data.charAt( isForward ? 0 : nextNode.data.length - 1 );

@@ -148,10 +148,9 @@ /**

*
* attributeElement.is( 'b' ); // -> true if this is a bold element
* attributeElement.is( 'element', 'b' ); // -> true if this is a bold element
* attributeElement.is( 'attributeElement', 'b' ); // -> same as above
* text.is( 'b' ); -> false
* text.is( 'element', 'b' ); -> false
*
* {@link module:engine/view/node~Node#is Check the entire list of view 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} type Type to check.
* @param {String} [name] Element name.

@@ -164,3 +163,2 @@ * @returns {Boolean}

// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.
type === this.name || type === 'view:' + this.name ||
type === 'element' || type === 'view:element' ||

@@ -167,0 +165,0 @@ type === 'node' || type === 'view:node';

@@ -74,10 +74,9 @@ /**

*
* containerElement.is( 'div' ); // -> true if this is a div container element
* containerElement.is( 'element', 'div' ); // -> true if this is a div container element
* containerElement.is( 'contaienrElement', 'div' ); // -> same as above
* text.is( 'div' ); -> false
* text.is( 'element', 'div' ); -> false
*
* {@link module:engine/view/node~Node#is Check the entire list of view 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} type Type to check.
* @param {String} [name] Element name.

@@ -90,3 +89,2 @@ * @returns {Boolean}

// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.
type === this.name || type === 'view:' + this.name ||
type === 'element' || type === 'view:element' ||

@@ -93,0 +91,0 @@ type === 'node' || type === 'view:node';

@@ -227,3 +227,3 @@ /**

// @if CK_DEBUG_ENGINE // for ( const child of this.getChildren() ) {
// @if CK_DEBUG_ENGINE // if ( child.is( 'text' ) ) {
// @if CK_DEBUG_ENGINE // if ( child.is( '$text' ) ) {
// @if CK_DEBUG_ENGINE // string += '\n' + '\t'.repeat( 1 ) + child.data;

@@ -230,0 +230,0 @@ // @if CK_DEBUG_ENGINE // } else {

@@ -32,12 +32,12 @@ /**

/**
* DomConverter is a set of tools to do transformations between DOM nodes and view nodes. It also handles
* {@link module:engine/view/domconverter~DomConverter#bindElements binding} these nodes.
* `DomConverter` is a set of tools to do transformations between DOM nodes and view nodes. It also handles
* {@link module:engine/view/domconverter~DomConverter#bindElements bindings} between these nodes.
*
* The instance of DOMConverter is available in {@link module:engine/view/view~View#domConverter `editor.editing.view.domConverter`}.
* The instance of `DOMConverter` is available under {@link module:engine/view/view~View#domConverter `editor.editing.view.domConverter`}.
*
* DomConverter does not check which nodes should be rendered (use {@link module:engine/view/renderer~Renderer}), does not keep a
* `DomConverter` does not check which nodes should be rendered (use {@link module:engine/view/renderer~Renderer}), does not keep a
* state of a tree nor keeps synchronization between tree view and DOM tree (use {@link module:engine/view/document~Document}).
*
* DomConverter keeps DOM elements to View element bindings, so when the converter will be destroyed, the binding will
* be lost. Two converters will keep separate binding maps, so one tree view can be bound with two DOM trees.
* `DomConverter` keeps DOM elements to View element bindings, so when the converter gets destroyed, the bindings are lost.
* Two converters will keep separate binding maps, so one tree view can be bound with two DOM trees.
*/

@@ -86,3 +86,3 @@ export default class DomConverter {

*/
this.blockElements = [ 'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'dd', 'dt', 'figcaption' ];
this.blockElements = [ 'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'dd', 'dt', 'figcaption', 'td', 'th' ];

@@ -206,3 +206,3 @@ /**

viewToDom( viewNode, domDocument, options = {} ) {
if ( viewNode.is( 'text' ) ) {
if ( viewNode.is( '$text' ) ) {
const textData = this._processDataFromViewText( viewNode );

@@ -242,2 +242,8 @@

// RawElement take care of their children in RawElement#render() method which can be customized
// (see https://github.com/ckeditor/ckeditor5/issues/4469).
if ( viewNode.is( 'rawElement' ) ) {
viewNode.render( domElement );
}
if ( options.bind ) {

@@ -324,3 +330,3 @@ this.bindElements( domElement, viewNode );

if ( viewParent.is( 'text' ) ) {
if ( viewParent.is( '$text' ) ) {
const domParent = this.findCorrespondingDomText( viewParent );

@@ -356,3 +362,3 @@

domBefore = nodeBefore.is( 'text' ) ?
domBefore = nodeBefore.is( '$text' ) ?
this.findCorrespondingDomText( nodeBefore ) :

@@ -401,7 +407,7 @@ this.mapViewToDom( viewPosition.nodeBefore );

// When node is inside UIElement return that UIElement as it's view representation.
const uiElement = this.getParentUIElement( domNode, this._domToViewMapping );
// When node is inside a UIElement or a RawElement return that parent as it's view representation.
const hostElement = this.getHostViewElement( domNode, this._domToViewMapping );
if ( uiElement ) {
return uiElement;
if ( hostElement ) {
return hostElement;
}

@@ -560,6 +566,6 @@

// If position is somewhere inside UIElement - return position before that element.
// If position is somewhere inside UIElement or a RawElement - return position before that element.
const viewElement = this.mapDomToView( domParent );
if ( viewElement && viewElement.is( 'uiElement' ) ) {
if ( viewElement && ( viewElement.is( 'uiElement' ) || viewElement.is( 'rawElement' ) ) ) {
return ViewPosition._createBefore( viewElement );

@@ -616,4 +622,6 @@ }

* to the given DOM - `undefined` is returned.
* For all DOM elements rendered by {@link module:engine/view/uielement~UIElement} that UIElement will be returned.
*
* For all DOM elements rendered by a {@link module:engine/view/uielement~UIElement} or
* a {@link module:engine/view/rawelement~RawElement}, the parent `UIElement` or `RawElement` will be returned.
*
* @param {DocumentFragment|Element} domElementOrDocumentFragment DOM element or document fragment.

@@ -624,3 +632,5 @@ * @returns {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment|undefined}

mapDomToView( domElementOrDocumentFragment ) {
return this.getParentUIElement( domElementOrDocumentFragment ) || this._domToViewMapping.get( domElementOrDocumentFragment );
const hostElement = this.getHostViewElement( domElementOrDocumentFragment );
return hostElement || this._domToViewMapping.get( domElementOrDocumentFragment );
}

@@ -638,3 +648,4 @@

*
* For all text nodes rendered by {@link module:engine/view/uielement~UIElement} that UIElement will be returned.
* For all text nodes rendered by a {@link module:engine/view/uielement~UIElement} or
* a {@link module:engine/view/rawelement~RawElement}, the parent `UIElement` or `RawElement` will be returned.
*

@@ -654,7 +665,7 @@ * Otherwise `null` is returned.

// If DOM text was rendered by UIElement - return that element.
const uiElement = this.getParentUIElement( domText );
// If DOM text was rendered by a UIElement or a RawElement - return this parent element.
const hostElement = this.getHostViewElement( domText );
if ( uiElement ) {
return uiElement;
if ( hostElement ) {
return hostElement;
}

@@ -873,9 +884,9 @@

/**
* Returns parent {@link module:engine/view/uielement~UIElement} for provided DOM node. Returns `null` if there is no
* parent UIElement.
* Returns a parent {@link module:engine/view/uielement~UIElement} or {@link module:engine/view/rawelement~RawElement}
* that hosts the provided DOM node. Returns `null` if there is no such parent.
*
* @param {Node} domNode
* @returns {module:engine/view/uielement~UIElement|null}
* @returns {module:engine/view/uielement~UIElement|module:engine/view/rawelement~RawElement|null}
*/
getParentUIElement( domNode ) {
getHostViewElement( domNode ) {
const ancestors = getAncestors( domNode );

@@ -890,3 +901,3 @@

if ( viewNode && viewNode.is( 'uiElement' ) ) {
if ( viewNode && ( viewNode.is( 'uiElement' ) || viewNode.is( 'rawElement' ) ) ) {
return viewNode;

@@ -903,4 +914,6 @@ }

* The following places are considered as incorrect for selection boundaries:
*
* * before or in the middle of the inline filler sequence,
* * inside the DOM element which represents {@link module:engine/view/uielement~UIElement a view ui element}.
* * inside a DOM element which represents {@link module:engine/view/uielement~UIElement a view UI element},
* * inside a DOM element which represents {@link module:engine/view/rawelement~RawElement a view raw element}.
*

@@ -937,5 +950,6 @@ * @param {Selection} domSelection DOM Selection object to be checked.

// If selection is in `view.UIElement`, it is incorrect. Note that `mapDomToView()` returns `view.UIElement`
// also for any dom element that is inside the view ui element (so we don't need to perform any additional checks).
if ( viewParent && viewParent.is( 'uiElement' ) ) {
// The position is incorrect when anchored inside a UIElement or a RawElement.
// Note: In case of UIElement and RawElement, mapDomToView() returns a parent element for any DOM child
// so there's no need to perform any additional checks.
if ( viewParent && ( viewParent.is( 'uiElement' ) || viewParent.is( 'rawElement' ) ) ) {
return false;

@@ -1154,7 +1168,7 @@ }

// <br> found – it works like a block boundary, so do not scan further.
else if ( value.item.is( 'br' ) ) {
else if ( value.item.is( 'element', 'br' ) ) {
return null;
}
// Found a text node in the same container element.
else if ( value.item.is( 'textProxy' ) ) {
else if ( value.item.is( '$textProxy' ) ) {
return value.item;

@@ -1161,0 +1175,0 @@ }

@@ -86,10 +86,9 @@ /**

*
* editableElement.is( 'div' ); // -> true if this is a div element
* editableElement.is( 'element', 'div' ); // -> true if this is a div element
* editableElement.is( 'editableElement', 'div' ); // -> same as above
* text.is( 'div' ); -> false
* text.is( 'element', 'div' ); -> false
*
* {@link module:engine/view/node~Node#is Check the entire list of view 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} type Type to check.
* @param {String} [name] Element name.

@@ -103,3 +102,2 @@ * @returns {Boolean}

type === 'containerElement' || type === 'view:containerElement' ||
type === this.name || type === 'view:' + this.name ||
type === 'element' || type === 'view:element' ||

@@ -106,0 +104,0 @@ type === 'node' || type === 'view:node';

@@ -167,10 +167,8 @@ /**

*
* element.is( 'img' ); // -> true if this is an <img> element
* element.is( 'element', 'img' ); // -> same as above
* text.is( 'img' ); -> false
* element.is( 'element', 'img' ); // -> true if this is an <img> element
* text.is( 'element', 'img' ); -> false
*
* {@link module:engine/view/node~Node#is Check the entire list of view 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} type Type to check.
* @param {String} [name] Element name.

@@ -181,4 +179,3 @@ * @returns {Boolean}

if ( !name ) {
return type === this.name || type === 'view:' + this.name ||
type === 'element' || type === 'view:element' ||
return type === 'element' || type === 'view:element' ||
// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.

@@ -839,3 +836,3 @@ type === 'node' || type === 'view:node';

// @if CK_DEBUG_ENGINE // for ( const child of this.getChildren() ) {
// @if CK_DEBUG_ENGINE // if ( child.is( 'text' ) ) {
// @if CK_DEBUG_ENGINE // if ( child.is( '$text' ) ) {
// @if CK_DEBUG_ENGINE // string += '\n' + '\t'.repeat( level + 1 ) + child.data;

@@ -842,0 +839,0 @@ // @if CK_DEBUG_ENGINE // } else {

@@ -65,10 +65,9 @@ /**

*
* emptyElement.is( 'img' ); // -> true if this is a img element
* emptyElement.is( 'element', 'img' ); // -> true if this is a img element
* emptyElement.is( 'emptyElement', 'img' ); // -> same as above
* text.is( 'img' ); -> false
* text.is( 'element', 'img' ); -> false
*
* {@link module:engine/view/node~Node#is Check the entire list of view 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} type Type to check.
* @param {String} [name] Element name.

@@ -81,3 +80,2 @@ * @returns {Boolean}

// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.
type === this.name || type === 'view:' + this.name ||
type === 'element' || type === 'view:element' ||

@@ -84,0 +82,0 @@ type === 'node' || type === 'view:node';

@@ -67,2 +67,4 @@ /**

* Inline filler which is a sequence of the zero width spaces.
*
* @type {String}
*/

@@ -69,0 +71,0 @@ export const INLINE_FILLER = ( () => {

@@ -315,4 +315,3 @@ /**

*
* imgElement.is( 'img' ); // -> true
* imgElement.is( 'element', 'img' ); // -> same as above
* imgElement.is( 'element', 'img' ); // -> true
* imgElement.is( 'view:element', 'img' ); // -> same as above, but more precise

@@ -339,3 +338,3 @@ *

* @method #is
* @param {String} type
* @param {String} type Type to check.
* @returns {Boolean}

@@ -342,0 +341,0 @@ */

@@ -153,4 +153,4 @@ /**

// Do not collect mutations from UIElements.
if ( element && element.is( 'uiElement' ) ) {
// Do not collect mutations from UIElements and RawElements.
if ( element && ( element.is( 'uiElement' ) || element.is( 'rawElement' ) ) ) {
continue;

@@ -169,4 +169,4 @@ }

// Do not collect mutations from UIElements.
if ( element && element.is( 'uiElement' ) ) {
// Do not collect mutations from UIElements and RawElements.
if ( element && ( element.is( 'uiElement' ) || element.is( 'rawElement' ) ) ) {
continue;

@@ -269,3 +269,3 @@ }

// Texts.
else if ( child1.is( 'text' ) && child2.is( 'text' ) ) {
else if ( child1.is( '$text' ) && child2.is( '$text' ) ) {
return child1.data === child2.data;

@@ -272,0 +272,0 @@ }

@@ -62,3 +62,3 @@ /**

get nodeAfter() {
if ( this.parent.is( 'text' ) ) {
if ( this.parent.is( '$text' ) ) {
return null;

@@ -78,3 +78,3 @@ }

get nodeBefore() {
if ( this.parent.is( 'text' ) ) {
if ( this.parent.is( '$text' ) ) {
return null;

@@ -103,3 +103,3 @@ }

get isAtEnd() {
const endOffset = this.parent.is( 'text' ) ? this.parent.data.length : this.parent.childCount;
const endOffset = this.parent.is( '$text' ) ? this.parent.data.length : this.parent.childCount;

@@ -352,3 +352,3 @@ return this.offset === endOffset;

if ( offset == 'end' ) {
offset = node.is( 'text' ) ? node.data.length : node.childCount;
offset = node.is( '$text' ) ? node.data.length : node.childCount;
} else if ( offset == 'before' ) {

@@ -385,3 +385,3 @@ return this._createBefore( node );

// TextProxy is not a instance of Node so we need do handle it in specific way.
if ( item.is( 'textProxy' ) ) {
if ( item.is( '$textProxy' ) ) {
return new Position( item.textNode, item.offsetInText + item.data.length );

@@ -412,3 +412,3 @@ }

// TextProxy is not a instance of Node so we need do handle it in specific way.
if ( item.is( 'textProxy' ) ) {
if ( item.is( '$textProxy' ) ) {
return new Position( item.textNode, item.offsetInText );

@@ -415,0 +415,0 @@ }

@@ -116,7 +116,7 @@ /**

// Fix positions, in case if they are in Text node.
if ( start.parent.is( 'text' ) && start.isAtStart ) {
if ( start.parent.is( '$text' ) && start.isAtStart ) {
start = Position._createBefore( start.parent );
}
if ( end.parent.is( 'text' ) && end.isAtEnd ) {
if ( end.parent.is( '$text' ) && end.isAtEnd ) {
end = Position._createAfter( end.parent );

@@ -157,7 +157,7 @@ }

// Because TreeWalker prefers positions next to text node, we need to move them manually into these text nodes.
if ( nodeAfterStart && nodeAfterStart.is( 'text' ) ) {
if ( nodeAfterStart && nodeAfterStart.is( '$text' ) ) {
start = new Position( nodeAfterStart, 0 );
}
if ( nodeBeforeEnd && nodeBeforeEnd.is( 'text' ) ) {
if ( nodeBeforeEnd && nodeBeforeEnd.is( '$text' ) ) {
end = new Position( nodeBeforeEnd, nodeBeforeEnd.data.length );

@@ -364,7 +364,7 @@ }

//
if ( this.start.parent.is( 'text' ) && this.start.isAtEnd && this.start.parent.nextSibling ) {
if ( this.start.parent.is( '$text' ) && this.start.isAtEnd && this.start.parent.nextSibling ) {
nodeAfterStart = this.start.parent.nextSibling;
}
if ( this.end.parent.is( 'text' ) && this.end.isAtStart && this.end.parent.previousSibling ) {
if ( this.end.parent.is( '$text' ) && this.end.isAtStart && this.end.parent.previousSibling ) {
nodeBeforeEnd = this.end.parent.previousSibling;

@@ -523,3 +523,3 @@ }

static _createOn( item ) {
const size = item.is( 'textProxy' ) ? item.offsetSize : 1;
const size = item.is( '$textProxy' ) ? item.offsetSize : 1;

@@ -526,0 +526,0 @@ return this._createFromPositionAndShift( Position._createBefore( item ), size );

@@ -276,6 +276,6 @@ /**

// The 'uiElement' is a special one and its children are not stored in a view (#799),
// so we cannot use it with replacing flow (since it uses view children during rendering
// which will always result in rendering empty element).
if ( viewChild && !viewChild.is( 'uiElement' ) ) {
// UIElement and RawElement are special cases. Their children are not stored in a view (#799)
// so we cannot use them with replacing flow (since they use view children during rendering
// which will always result in rendering empty elements).
if ( viewChild && !( viewChild.is( 'uiElement' ) || viewChild.is( 'rawElement' ) ) ) {
this._updateElementMappings( viewChild, actualDomChildren[ deleteIndex ] );

@@ -336,3 +336,3 @@ }

if ( firstPos.parent.is( 'text' ) ) {
if ( firstPos.parent.is( '$text' ) ) {
return ViewPosition._createBefore( this.selection.getFirstPosition().parent );

@@ -664,3 +664,3 @@ } else {

if ( viewNode.is( 'text' ) ) {
if ( viewNode.is( '$text' ) ) {
this.markedTexts.add( viewNode );

@@ -667,0 +667,0 @@ } else if ( viewNode.is( 'element' ) ) {

@@ -58,10 +58,9 @@ /**

*
* rootEditableElement.is( 'div' ); // -> true if this is a div root editable element
* rootEditableElement.is( 'element', 'div' ); // -> true if this is a div root editable element
* rootEditableElement.is( 'rootElement', 'div' ); // -> same as above
* text.is( 'div' ); -> false
* text.is( 'element', 'div' ); -> false
*
* {@link module:engine/view/node~Node#is Check the entire list of view 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} type Type to check.
* @param {String} [name] Element name.

@@ -76,3 +75,2 @@ * @returns {Boolean}

type === 'containerElement' || type === 'view:containerElement' ||
type === this.name || type === 'view:' + this.name ||
type === 'element' || type === 'view:element' ||

@@ -79,0 +77,0 @@ type === 'node' || type === 'view:node';

@@ -48,8 +48,8 @@ /**

*
* text.is( 'text' ); // -> true
* text.is( '$text' ); // -> true
* text.is( 'node' ); // -> true
* text.is( 'view:text' ); // -> true
* text.is( 'view:$text' ); // -> true
* text.is( 'view:node' ); // -> true
*
* text.is( 'model:text' ); // -> false
* text.is( 'model:$text' ); // -> false
* text.is( 'element' ); // -> false

@@ -60,7 +60,12 @@ * text.is( 'range' ); // -> false

*
* @param {String} type
* **Note:** Until version 20.0.0 this method wasn't accepting `'$text'` type. The legacy `'text'` type is still
* accepted for backward compatibility.
*
* @param {String} type Type to check.
* @returns {Boolean}
*/
is( type ) {
return type === 'text' || type === 'view:text' ||
return type === '$text' || type === 'view:$text' ||
// This are legacy values kept for backward compatibility.
type === 'text' || type === 'view:text' ||
// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.

@@ -81,4 +86,6 @@ type === 'node' || type === 'view:node';

/**
* This getter is required when using the addition assignment operator on protected property:
* The `_data` property is controlled by a getter and a setter.
*
* The getter is required when using the addition assignment operator on protected property:
*
* const foo = downcastWriter.createText( 'foo' );

@@ -92,2 +99,4 @@ * const bar = downcastWriter.createText( 'bar' );

*
* The setter sets data and fires the {@link module:engine/view/node~Node#event:change:text change event}.
*
* @protected

@@ -100,9 +109,2 @@ * @type {String}

/**
* Sets data and fires the {@link module:engine/view/node~Node#event:change:text change event}.
*
* @protected
* @fires change:text
* @param {String} data New data for the text node.
*/
set _data( data ) {

@@ -109,0 +111,0 @@ this._fireChange( 'text', this );

@@ -146,6 +146,6 @@ /**

*
* textProxy.is( 'textProxy' ); // -> true
* textProxy.is( 'view:textProxy' ); // -> true
* textProxy.is( '$textProxy' ); // -> true
* textProxy.is( 'view:$textProxy' ); // -> true
*
* textProxy.is( 'model:textProxy' ); // -> false
* textProxy.is( 'model:$textProxy' ); // -> false
* textProxy.is( 'element' ); // -> false

@@ -156,7 +156,12 @@ * textProxy.is( 'range' ); // -> false

*
* @param {String} type
* **Note:** Until version 20.0.0 this method wasn't accepting `'$textProxy'` type. The legacy `'textProxy'` type is still
* accepted for backward compatibility.
*
* @param {String} type Type to check.
* @returns {Boolean}
*/
is( type ) {
return type === 'textProxy' || type === 'view:textProxy';
return type === '$textProxy' || type === 'view:$textProxy' ||
// This are legacy values kept for backward compatibility.
type === 'textProxy' || type === 'view:textProxy';
}

@@ -163,0 +168,0 @@

@@ -78,10 +78,9 @@ /**

*
* uiElement.is( 'span' ); // -> true if this is a span ui element
* uiElement.is( 'element', 'span' ); // -> true if this is a span ui element
* uiElement.is( 'uiElement', 'span' ); // -> same as above
* text.is( 'span' ); -> false
* text.is( 'element', 'span' ); -> false
*
* {@link module:engine/view/node~Node#is Check the entire list of view 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} type Type to check.
* @param {String} [name] Element name.

@@ -94,3 +93,2 @@ * @returns {Boolean}

// From super.is(). This is highly utilised method and cannot call super. See ckeditor/ckeditor5#6529.
type === this.name || type === 'view:' + this.name ||
type === 'element' || type === 'view:element' ||

@@ -97,0 +95,0 @@ type === 'node' || type === 'view:node';

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc