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 33.0.0 to 34.0.0

src/model/utils/findoptimalinsertionrange.js

44

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

@@ -26,26 +26,26 @@ "keywords": [

"dependencies": {
"@ckeditor/ckeditor5-utils": "^33.0.0",
"@ckeditor/ckeditor5-utils": "^34.0.0",
"lodash-es": "^4.17.15"
},
"devDependencies": {
"@ckeditor/ckeditor5-basic-styles": "^33.0.0",
"@ckeditor/ckeditor5-block-quote": "^33.0.0",
"@ckeditor/ckeditor5-clipboard": "^33.0.0",
"@ckeditor/ckeditor5-cloud-services": "^33.0.0",
"@ckeditor/ckeditor5-core": "^33.0.0",
"@ckeditor/ckeditor5-editor-classic": "^33.0.0",
"@ckeditor/ckeditor5-enter": "^33.0.0",
"@ckeditor/ckeditor5-essentials": "^33.0.0",
"@ckeditor/ckeditor5-heading": "^33.0.0",
"@ckeditor/ckeditor5-image": "^33.0.0",
"@ckeditor/ckeditor5-link": "^33.0.0",
"@ckeditor/ckeditor5-list": "^33.0.0",
"@ckeditor/ckeditor5-mention": "^33.0.0",
"@ckeditor/ckeditor5-paragraph": "^33.0.0",
"@ckeditor/ckeditor5-table": "^33.0.0",
"@ckeditor/ckeditor5-theme-lark": "^33.0.0",
"@ckeditor/ckeditor5-typing": "^33.0.0",
"@ckeditor/ckeditor5-ui": "^33.0.0",
"@ckeditor/ckeditor5-undo": "^33.0.0",
"@ckeditor/ckeditor5-widget": "^33.0.0",
"@ckeditor/ckeditor5-basic-styles": "^34.0.0",
"@ckeditor/ckeditor5-block-quote": "^34.0.0",
"@ckeditor/ckeditor5-clipboard": "^34.0.0",
"@ckeditor/ckeditor5-cloud-services": "^34.0.0",
"@ckeditor/ckeditor5-core": "^34.0.0",
"@ckeditor/ckeditor5-editor-classic": "^34.0.0",
"@ckeditor/ckeditor5-enter": "^34.0.0",
"@ckeditor/ckeditor5-essentials": "^34.0.0",
"@ckeditor/ckeditor5-heading": "^34.0.0",
"@ckeditor/ckeditor5-image": "^34.0.0",
"@ckeditor/ckeditor5-link": "^34.0.0",
"@ckeditor/ckeditor5-list": "^34.0.0",
"@ckeditor/ckeditor5-mention": "^34.0.0",
"@ckeditor/ckeditor5-paragraph": "^34.0.0",
"@ckeditor/ckeditor5-table": "^34.0.0",
"@ckeditor/ckeditor5-theme-lark": "^34.0.0",
"@ckeditor/ckeditor5-typing": "^34.0.0",
"@ckeditor/ckeditor5-ui": "^34.0.0",
"@ckeditor/ckeditor5-undo": "^34.0.0",
"@ckeditor/ckeditor5-widget": "^34.0.0",
"webpack": "^5.58.1",

@@ -52,0 +52,0 @@ "webpack-cli": "^4.9.0"

@@ -6,3 +6,4 @@ CKEditor 5 editing engine

[![Coverage Status](https://coveralls.io/repos/github/ckeditor/ckeditor5/badge.svg?branch=master)](https://coveralls.io/github/ckeditor/ckeditor5?branch=master)
[![Build Status](https://travis-ci.com/ckeditor/ckeditor5.svg?branch=master)](https://travis-ci.com/ckeditor/ckeditor5)
[![Build Status](https://travis-ci.com/ckeditor/ckeditor5.svg?branch=master)](https://app.travis-ci.com/github/ckeditor/ckeditor5)
![Dependency Status](https://img.shields.io/librariesio/release/npm/@ckeditor/ckeditor5-engine)

@@ -9,0 +10,0 @@ The CKEditor 5 editing engine implements a flexible MVC-based architecture for creating rich text editing features.

@@ -124,5 +124,5 @@ /**

*
* @error mapping-view-position-parent-not-found
* @error mapping-model-position-view-parent-not-found
*/
throw new CKEditorError( 'mapping-view-position-parent-not-found', this, { modelPosition: data.modelPosition } );
throw new CKEditorError( 'mapping-model-position-view-parent-not-found', this, { modelPosition: data.modelPosition } );
}

@@ -129,0 +129,0 @@

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

/**
* The list of elements that were created during splitting but should not get removed on conversion end even if they are empty.
*
* After the conversion process the list is cleared.
*
* @private
* @type {Set.<module:engine/model/element~Element>}
*/
this._emptyElementsToKeep = new Set();
/**
* An interface passed by the dispatcher to the event callbacks.

@@ -171,2 +181,3 @@ *

this.conversionApi.getSplitParts = this._getSplitParts.bind( this );
this.conversionApi.keepEmptyElement = this._keepEmptyElement.bind( this );
}

@@ -231,2 +242,3 @@

this._cursorParents.clear();
this._emptyElementsToKeep.clear();

@@ -458,2 +470,11 @@ // Clear conversion API.

/**
* Mark an element that were created during splitting that it should not get removed on conversion end even if it's empty.
*
* @private
*/
_keepEmptyElement( element ) {
this._emptyElementsToKeep.add( element );
}
/**
* Checks if there are any empty elements created while splitting and removes them.

@@ -470,3 +491,3 @@ *

for ( const element of this._splitParts.keys() ) {
if ( element.isEmpty ) {
if ( element.isEmpty && !this._emptyElementsToKeep.has( element ) ) {
this.conversionApi.writer.remove( element );

@@ -766,2 +787,11 @@ this._splitParts.delete( element );

/**
* Mark an element that was created during splitting that it should not get removed on conversion end even if it's empty.
*
* **Note:** This is an advanced method. For most cases you will not need to keep the split empty element.
*
* @method #keepEmptyElement
* @param {module:engine/model/element~Element} element
*/
/**
* Stores information about what parts of the processed view item are still waiting to be handled. After a piece of view item

@@ -768,0 +798,0 @@ * was converted, an appropriate consumable value should be

@@ -31,3 +31,6 @@ /**

export { default as Element } from './model/element';
export { default as Position } from './model/position';
export { default as DocumentFragment } from './model/documentfragment';
export { default as History } from './model/history';
export { default as Text } from './model/text';

@@ -37,2 +40,5 @@ export { default as DomConverter } from './view/domconverter';

export { default as ViewDocument } from './view/document';
export { default as ViewText } from './view/text';
export { default as ViewElement } from './view/element';
export { default as ViewDocumentFragment } from './view/documentfragment';

@@ -39,0 +45,0 @@ export { getFillerOffset } from './view/containerelement';

@@ -339,2 +339,6 @@ /**

hasDataChanges() {
if ( this._changesInElement.size > 0 ) {
return true;
}
for ( const { newMarkerData, oldMarkerData } of this._changedMarkers.values() ) {

@@ -346,13 +350,13 @@ if ( newMarkerData.affectsData !== oldMarkerData.affectsData ) {

if ( newMarkerData.affectsData ) {
// Skip markers, which ranges have not changed.
if ( newMarkerData.range && oldMarkerData.range && newMarkerData.range.isEqual( oldMarkerData.range ) ) {
return false;
const markerAdded = newMarkerData.range && !oldMarkerData.range;
const markerRemoved = !newMarkerData.range && oldMarkerData.range;
const markerChanged = newMarkerData.range && oldMarkerData.range && !newMarkerData.range.isEqual( oldMarkerData.range );
if ( markerAdded || markerRemoved || markerChanged ) {
return true;
}
return true;
}
}
// If markers do not affect the data, check whether there are some changes in elements.
return this._changesInElement.size > 0;
return false;
}

@@ -424,3 +428,3 @@

// Generate diff item for this element and insert it into the diff set.
diffSet.push( this._getInsertDiff( element, i, elementChildren[ i ].name ) );
diffSet.push( this._getInsertDiff( element, i, elementChildren[ i ] ) );

@@ -430,3 +434,3 @@ i++;

// Generate diff item for this element and insert it into the diff set.
diffSet.push( this._getRemoveDiff( element, i, snapshotChildren[ j ].name ) );
diffSet.push( this._getRemoveDiff( element, i, snapshotChildren[ j ] ) );

@@ -932,10 +936,11 @@ j++;

* @param {Number} offset The offset at which change happened.
* @param {String} name The name of the removed element or `'$text'` for a character.
* @param {Object} elementSnapshot The snapshot of the removed element a character.
* @returns {Object} The diff item.
*/
_getInsertDiff( parent, offset, name ) {
_getInsertDiff( parent, offset, elementSnapshot ) {
return {
type: 'insert',
position: Position._createAt( parent, offset ),
name,
name: elementSnapshot.name,
attributes: new Map( elementSnapshot.attributes ),
length: 1,

@@ -952,10 +957,11 @@ changeCount: this._changeCount++

* @param {Number} offset The offset at which change happened.
* @param {String} name The name of the removed element or `'$text'` for a character.
* @param {Object} elementSnapshot The snapshot of the removed element a character.
* @returns {Object} The diff item.
*/
_getRemoveDiff( parent, offset, name ) {
_getRemoveDiff( parent, offset, elementSnapshot ) {
return {
type: 'remove',
position: Position._createAt( parent, offset ),
name,
name: elementSnapshot.name,
attributes: new Map( elementSnapshot.attributes ),
length: 1,

@@ -1239,2 +1245,8 @@ changeCount: this._changeCount++

/**
* Map of attributes that were set on the item while it was inserted.
*
* @member {Map.<String,*>} module:engine/model/differ~DiffItemInsert#attributes
*/
/**
* The position where the node was inserted.

@@ -1271,2 +1283,8 @@ *

/**
* Map of attributes that were set on the item while it was removed.
*
* @member {Map.<String,*>} module:engine/model/differ~DiffItemRemove#attributes
*/
/**
* The position where the node was removed.

@@ -1273,0 +1291,0 @@ *

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

import insertContent from './utils/insertcontent';
import insertObject from './utils/insertobject';
import deleteContent from './utils/deletecontent';

@@ -84,3 +85,3 @@ import modifySelection from './utils/modifyselection';

[ 'insertContent', 'deleteContent', 'modifySelection', 'getSelectedContent', 'applyOperation' ]
[ 'insertContent', 'insertObject', 'deleteContent', 'modifySelection', 'getSelectedContent', 'applyOperation' ]
.forEach( methodName => this.decorate( methodName ) );

@@ -101,7 +102,24 @@

this.schema.register( '$container', {
allowIn: [ '$root', '$container' ]
} );
this.schema.register( '$block', {
allowIn: '$root',
allowIn: [ '$root', '$container' ],
isBlock: true
} );
this.schema.register( '$blockObject', {
allowWhere: '$block',
isBlock: true,
isObject: true
} );
this.schema.register( '$inlineObject', {
allowWhere: '$text',
allowAttributesOf: '$text',
isInline: true,
isObject: true
} );
this.schema.register( '$text', {

@@ -310,2 +328,5 @@ allowIn: '$block',

*
* **Note**: If you want to insert an {@glink framework/guides/deep-dive/schema#object-elements object element}
* (e.g. a {@link module:widget/utils~toWidget widget}), see {@link #insertObject} instead.
*
* This is a high-level method. It takes the {@link #schema schema} into consideration when inserting

@@ -443,2 +464,85 @@ * the content, clears the given selection's content before inserting nodes and moves the selection

/**
* Inserts an {@glink framework/guides/deep-dive/schema#object-elements object element} at a specific position in the editor content.
*
* This is a high-level API:
* * It takes the {@link #schema schema} into consideration,
* * It clears the content of passed `selectable` before inserting,
* * It can move the selection at the end of the process,
* * It will copy the selected block's attributes to preserve them upon insertion,
* * It can split elements or wrap inline objects with paragraphs if they are not allowed in target position,
* * etc.
*
* # Notes
*
* * If you want to insert a non-object content, see {@link #insertContent} instead.
* * For lower-level API, see {@link module:engine/model/writer~Writer `Writer`}.
* * Unlike {@link module:engine/model/writer~Writer `Writer`}, this method does not have to be used inside
* a {@link #change `change()` block}.
* * Inserting object into the model is not enough to make CKEditor 5 render that content to the user.
* CKEditor 5 implements a model-view-controller architecture and what `model.insertObject()` does
* is only adding nodes to the model. Additionally, you need to define
* {@glink framework/guides/architecture/editing-engine#conversion converters} between the model and view
* and define those nodes in the {@glink framework/guides/architecture/editing-engine#schema schema}.
*
* # Examples
*
* Use the following code to insert an object at the current selection and keep the selection on the inserted element:
*
* const rawHtmlEmbedElement = writer.createElement( 'rawHtml' );
*
* model.insertObject( rawHtmlEmbedElement, null, null, {
* setSelection: 'on'
* } );
*
* Use the following code to insert an object at the current selection and nudge the selection after the inserted object:
*
* const pageBreakElement = writer.createElement( 'pageBreak' );
*
* model.insertObject( pageBreakElement, null, null, {
* setSelection: 'after'
* } );
*
* Use the following code to insert an object at the current selection and avoid splitting the content (non-destructive insertion):
*
* const tableElement = writer.createElement( 'table' );
*
* model.insertObject( tableElement, null, null, {
* findOptimalPosition: 'auto'
* } );
*
* Use the following code to insert an object at the specific range (also: replace the content of the range):
*
* const tableElement = writer.createElement( 'table' );
* const range = model.createRangeOn( model.document.getRoot().getChild( 1 ) );
*
* model.insertObject( tableElement, range );
*
* @param {module:engine/model/element~Element} object An object to be inserted into the model document.
* @param {module:engine/model/selection~Selectable} [selectable=model.document.selection]
* A selectable where the content should be inserted. If not specified, the current
* {@link module:engine/model/document~Document#selection document selection} will be used instead.
* @param {Number|'before'|'end'|'after'|'on'|'in'} placeOrOffset Specifies the exact place or offset for the insertion to take place,
* relative to `selectable`.
* @param {Object} [options] Additional options.
* @param {'auto'|'before'|'after'} [options.findOptimalPosition] An option that, when set, adjusts the insertion position (relative to
* `selectable` and `placeOrOffset`) so that the content of `selectable` is not split upon insertion (a.k.a. non-destructive insertion).
* * When `'auto'`, the algorithm will decide whether to insert the object before or after `selectable` to avoid content splitting.
* * When `'before'`, the closest position before `selectable` will be used that will not result in content splitting.
* * When `'after'`, the closest position after `selectable` will be used that will not result in content splitting.
*
* Note that this option works only for block objects. Inline objects are inserted into text and do not split blocks.
* @param {'on'|'after'} [options.setSelection] An option that, when set, moves the
* {@link module:engine/model/document~Document#selection document selection} after inserting the object.
* * When `'on'`, the document selection will be set on the inserted object.
* * When `'after'`, the document selection will move to the closest text node after the inserted object. If there is no
* such text node, a paragraph will be created and the document selection will be moved inside it.
* @returns {module:engine/model/range~Range} A range which contains all the performed changes. This is a range that, if removed,
* would return the model to the state before the insertion. If no changes were preformed by `insertObject()`, returns a range collapsed
* at the insertion position.
*/
insertObject( object, selectable, placeOrOffset, options ) {
return insertObject( this, object, selectable, placeOrOffset, options );
}
/**
* Deletes content of the selection and merge siblings. The resulting selection is always collapsed.

@@ -911,3 +1015,3 @@ *

* **Note** The `selectable` parameter for the {@link #insertContent} is optional. When `undefined` value is passed the method uses
* `model.document.selection`.
* {@link module:engine/model/document~Document#selection document selection}.
*

@@ -919,2 +1023,15 @@ * @event insertContent

/**
* Event fired when {@link #insertObject} method is called.
*
* The {@link #insertObject default action of that method} is implemented as a
* listener to this event so it can be fully customized by the features.
*
* **Note** The `selectable` parameter for the {@link #insertObject} is optional. When `undefined` value is passed the method uses
* {@link module:engine/model/document~Document#selection document selection}.
*
* @event insertObject
* @param {Array} args The arguments passed to the original method.
*/
/**
* Event fired when {@link #deleteContent} method is called.

@@ -921,0 +1038,0 @@ *

@@ -236,5 +236,4 @@ /**

// Use a highly optimized version instead of checking the text node first and then getting the node after. See #6582.
const positionParent = position.parent;
const textNodeAtPosition = getTextNodeAtPosition( position, positionParent );
const node = textNodeAtPosition ? textNodeAtPosition : getNodeAfterPosition( position, positionParent, textNodeAtPosition );
const textNodeAtPosition = getTextNodeAtPosition( position, parent );
const node = textNodeAtPosition ? textNodeAtPosition : getNodeAfterPosition( position, parent, textNodeAtPosition );

@@ -241,0 +240,0 @@ if ( node instanceof Element ) {

@@ -83,2 +83,13 @@ /**

// Collect attributes to copy in case of autoparagraphing.
const attributesForAutoparagraph = {};
if ( !options.doNotAutoparagraph ) {
const selectedElement = selection.getSelectedElement();
if ( selectedElement ) {
Object.assign( attributesForAutoparagraph, schema.getAttributesWithProperty( selectedElement, 'copyOnReplace', true ) );
}
}
// Get the live positions for the range adjusted to span only blocks selected from the user perspective.

@@ -118,3 +129,3 @@ const [ startPosition, endPosition ] = getLivePositionsForSelectedBlocks( selRange );

if ( !options.doNotAutoparagraph && shouldAutoparagraph( schema, startPosition ) ) {
insertParagraph( writer, startPosition, selection );
insertParagraph( writer, startPosition, selection, attributesForAutoparagraph );
}

@@ -487,5 +498,7 @@

function insertParagraph( writer, position, selection ) {
function insertParagraph( writer, position, selection, attributes = {} ) {
const paragraph = writer.createElement( 'paragraph' );
writer.model.schema.setAllowedAttributes( paragraph, attributes, writer );
writer.insert( paragraph, position );

@@ -492,0 +505,0 @@

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

*
* **Note:** Attribute elements by default can wrap {@link module:engine/view/text~Text},
* {@link module:engine/view/emptyelement~EmptyElement}, {@link module:engine/view/uielement~UIElement},
* {@link module:engine/view/rawelement~RawElement} and other attribute elements with higher priority. Other elements while placed inside
* an attribute element will split it (or nest in case of an `AttributeElement`). This behavior can be modified by changing
* the `isAllowedInsideAttributeElement` option while creating
* {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement},
* {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement},
* {@link module:engine/view/downcastwriter~DowncastWriter#createUIElement} or
* {@link module:engine/view/downcastwriter~DowncastWriter#createRawElement}.
*
* @extends module:engine/view/element~Element

@@ -39,0 +29,0 @@ */

@@ -134,11 +134,2 @@ /**

/**
* Whether an element is allowed inside an AttributeElement and can be wrapped with
* {@link module:engine/view/attributeelement~AttributeElement} by {@link module:engine/view/downcastwriter~DowncastWriter}.
*
* @protected
* @member {Boolean}
*/
this._isAllowedInsideAttributeElement = false;
/**
* A list of attribute names that should be rendered in the editing pipeline even though filtering mechanisms

@@ -180,13 +171,2 @@ * implemented in the {@link module:engine/view/domconverter~DomConverter} (for instance,

/**
* Whether the element is allowed inside an AttributeElement and can be wrapped with
* {@link module:engine/view/attributeelement~AttributeElement} by {@link module:engine/view/downcastwriter~DowncastWriter}.
*
* @readonly
* @type {Boolean}
*/
get isAllowedInsideAttributeElement() {
return this._isAllowedInsideAttributeElement;
}
/**
* Checks whether this object is of the given.

@@ -355,7 +335,2 @@ *

// Check isAllowedInsideAttributeElement property.
if ( this.isAllowedInsideAttributeElement != otherElement.isAllowedInsideAttributeElement ) {
return false;
}
// Check number of attributes, classes and styles.

@@ -639,4 +614,2 @@ if ( this._attrs.size !== otherElement._attrs.size || this._classes.size !== otherElement._classes.size ||

cloned._isAllowedInsideAttributeElement = this.isAllowedInsideAttributeElement;
return cloned;

@@ -643,0 +616,0 @@ }

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

// Override the default of the base class.
this._isAllowedInsideAttributeElement = true;
/**

@@ -45,0 +42,0 @@ * Returns `null` because filler is not needed for EmptyElements.

@@ -742,3 +742,3 @@ /**

*
* Refer to the {@glink builds/guides/migration/migration-to-29##migration-to-ckeditor-5-v2910 Migration to v29.1.0} guide
* Refer to the {@glink updating/migration-to-29##migration-to-ckeditor-5-v2910 Migration to v29.1.0} guide
* and {@link module:engine/view/matcher~MatcherPattern} documentation.

@@ -773,3 +773,3 @@ *

*
* Refer to the {@glink builds/guides/migration/migration-to-29##migration-to-ckeditor-5-v2910 Migration to v29.1.0} guide
* Refer to the {@glink updating/migration-to-29##migration-to-ckeditor-5-v2910 Migration to v29.1.0} guide
* and the {@link module:engine/view/matcher~MatcherPattern} documentation.

@@ -776,0 +776,0 @@ *

@@ -1,2 +0,1 @@

/**

@@ -3,0 +2,0 @@ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.

/**
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

@@ -5,0 +5,0 @@

@@ -279,3 +279,3 @@ /**

if ( firstChild.is( 'element' ) && !firstChild.is( 'uiElement' ) ) {
if ( firstChild.is( 'element' ) && !firstChild.is( 'uiElement' ) && !firstChild.is( 'attributeElement' ) ) {
return firstChild;

@@ -282,0 +282,0 @@ }

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

// Override the default of the base class.
this._isAllowedInsideAttributeElement = true;
/**

@@ -55,0 +52,0 @@ * Returns `null` because filler is not needed for raw elements.

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

// Override the default of the base class.
this._isAllowedInsideAttributeElement = true;
/**

@@ -58,0 +55,0 @@ * Returns `null` because filler is not needed for UIElements.

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

import ArrowKeysObserver from './observer/arrowkeysobserver';
import TabObserver from './observer/tabobserver';

@@ -58,2 +59,4 @@ import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';

* * {@link module:engine/view/observer/compositionobserver~CompositionObserver}.
* * {@link module:engine/view/observer/arrowkeysobserver~ArrowKeysObserver}.
* * {@link module:engine/view/observer/tabobserver~TabObserver}.
*

@@ -191,2 +194,3 @@ * This class also {@link module:engine/view/view~View#attachDomRoot binds the DOM and the view elements}.

this.addObserver( ArrowKeysObserver );
this.addObserver( TabObserver );

@@ -193,0 +197,0 @@ if ( env.isAndroid ) {

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

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

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