Socket
Socket
Sign inDemoInstall

@ckeditor/ckeditor5-engine

Package Overview
Dependencies
Maintainers
1
Versions
662
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 0.0.0-nightly-20230726.0 to 0.0.0-nightly-20230727.0

4

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

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

"dependencies": {
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20230726.0",
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20230727.0",
"lodash-es": "4.17.21"

@@ -29,0 +29,0 @@ },

@@ -13,3 +13,3 @@ /**

import DowncastDispatcher from '../conversion/downcastdispatcher';
import { clearAttributes, convertCollapsedSelection, convertRangeSelection, insertAttributesAndChildren, insertText, remove } from '../conversion/downcasthelpers';
import { cleanSelection, convertCollapsedSelection, convertRangeSelection, insertAttributesAndChildren, insertText, remove } from '../conversion/downcasthelpers';
import { convertSelectionChange } from '../conversion/upcasthelpers';

@@ -71,3 +71,3 @@ import { tryFixingRange } from '../model/utils/selection-post-fixer';

// Attach default model selection converters.
this.downcastDispatcher.on('selection', clearAttributes(), { priority: 'high' });
this.downcastDispatcher.on('cleanSelection', cleanSelection());
this.downcastDispatcher.on('selection', convertRangeSelection(), { priority: 'low' });

@@ -74,0 +74,0 @@ this.downcastDispatcher.on('selection', convertCollapsedSelection(), { priority: 'low' });

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

};
cleanSelection: {
selection: Selection | DocumentSelection;
};
selection: {

@@ -438,2 +441,14 @@ selection: Selection | DocumentSelection;

/**
* Fired at the beginning of selection conversion, before
* {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:selection selection} events.
*
* Should be used to clean up the view state at the current selection position, before the selection is moved to another place.
*
* @eventName ~DowncastDispatcher#cleanSelection
* @param {module:engine/model/selection~Selection} selection Selection that is converted.
* @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface
* to be used by callback, passed in `DowncastDispatcher` constructor.
*/
export type DowncastCleanSelectionEvent = DowncastEvent<'cleanSelection'>;
/**
* Fired when a new marker is added to the model. Also fired when a collapsed model selection that is inside a marker is converted.

@@ -440,0 +455,0 @@ *

@@ -201,4 +201,12 @@ /**

convertSelection(selection, markers, writer) {
const conversionApi = this._createConversionApi(writer);
// First perform a clean-up at the current position of the selection.
this.fire('cleanSelection', { selection }, conversionApi);
// Don't convert selection if it is in a model root that does not have a view root (for now this is only the graveyard root).
const modelRoot = selection.getFirstPosition().root;
if (!conversionApi.mapper.toViewElement(modelRoot)) {
return;
}
// Now, perform actual selection conversion.
const markersAtSelection = Array.from(markers.getMarkersAtPosition(selection.getFirstPosition()));
const conversionApi = this._createConversionApi(writer);
this._addConsumablesForSelection(conversionApi.consumable, selection, markersAtSelection);

@@ -210,12 +218,13 @@ this.fire('selection', { selection }, conversionApi);

for (const marker of markersAtSelection) {
const markerRange = marker.getRange();
if (!shouldMarkerChangeBeConverted(selection.getFirstPosition(), marker, conversionApi.mapper)) {
continue;
}
const data = {
item: selection,
markerName: marker.name,
markerRange
};
// Do not fire event if the marker has been consumed.
if (conversionApi.consumable.test(selection, 'addMarker:' + marker.name)) {
const markerRange = marker.getRange();
if (!shouldMarkerChangeBeConverted(selection.getFirstPosition(), marker, conversionApi.mapper)) {
continue;
}
const data = {
item: selection,
markerName: marker.name,
markerRange
};
this.fire(`addMarker:${marker.name}`, data, conversionApi);

@@ -225,12 +234,12 @@ }

for (const key of selection.getAttributeKeys()) {
const data = {
item: selection,
range: selection.getFirstRange(),
attributeKey: key,
attributeOldValue: null,
attributeNewValue: selection.getAttribute(key)
};
// Do not fire event if the attribute has been consumed.
if (conversionApi.consumable.test(selection, 'attribute:' + data.attributeKey)) {
this.fire(`attribute:${data.attributeKey}:$text`, data, conversionApi);
if (conversionApi.consumable.test(selection, 'attribute:' + key)) {
const data = {
item: selection,
range: selection.getFirstRange(),
attributeKey: key,
attributeOldValue: null,
attributeNewValue: selection.getAttribute(key)
};
this.fire(`attribute:${key}:$text`, data, conversionApi);
}

@@ -237,0 +246,0 @@ }

@@ -883,3 +883,3 @@ /**

*
* See also {@link module:engine/conversion/downcasthelpers~clearAttributes} which does a clean-up
* See also {@link module:engine/conversion/downcasthelpers~cleanSelection} which does a clean-up
* by merging attributes.

@@ -893,3 +893,3 @@ *

/**
* Function factory that creates a converter which clears artifacts after the previous
* Function factory that creates a converter which cleans artifacts after the previous
* {@link module:engine/model/selection~Selection model selection} conversion. It removes all empty

@@ -913,3 +913,3 @@ * {@link module:engine/view/attributeelement~AttributeElement view attribute elements} and merges sibling attributes at all start and end

* ```ts
* modelDispatcher.on( 'selection', clearAttributes() );
* modelDispatcher.on( 'cleanSelection', cleanSelection() );
* ```

@@ -922,3 +922,3 @@ *

*/
export declare function clearAttributes(): (evt: EventInfo, data: unknown, conversionApi: DowncastConversionApi) => void;
export declare function cleanSelection(): (evt: EventInfo, data: unknown, conversionApi: DowncastConversionApi) => void;
/**

@@ -925,0 +925,0 @@ * Function factory that creates a converter which converts the set/change/remove attribute changes from the model to the view.

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

export { default as TabObserver } from './view/observer/tabobserver';
export { default as FocusObserver } from './view/observer/focusobserver';
export { default as DowncastWriter } from './view/downcastwriter';

@@ -94,0 +95,0 @@ export { default as UpcastWriter } from './view/upcastwriter';

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

export { default as TabObserver } from './view/observer/tabobserver';
export { default as FocusObserver } from './view/observer/focusobserver';
export { default as DowncastWriter } from './view/downcastwriter';

@@ -68,0 +69,0 @@ export { default as UpcastWriter } from './view/upcastwriter';

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

import type Item from './item';
import type RootElement from './rootelement';
import type Operation from './operation/operation';

@@ -196,2 +197,15 @@ /**

/**
* Buffers all the data related to given root like it was all just added to the editor.
*
* Following changes are buffered:
*
* * root is attached,
* * all root content is inserted,
* * all root attributes are added,
* * all markers inside the root are added.
*
* @internal
*/
_bufferRootLoad(root: RootElement): void;
/**
* Saves and handles an insert change.

@@ -198,0 +212,0 @@ */

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

const operation = operationToBuffer;
// Note: an operation that happens inside a non-loaded root will be ignored. If the operation happens partially inside
// a non-loaded root, that part will be ignored (this may happen for move or marker operations).
//
switch (operation.type) {

@@ -183,2 +186,10 @@ case 'insert': {

case 'addRoot': {
const root = operation.affectedSelectable;
if (!root._isLoaded) {
return;
}
// Don't buffer if the root state does not change.
if (root.isAttached() == operation.isAdd) {
return;
}
this._bufferRootStateChange(operation.rootName, operation.isAdd);

@@ -190,2 +201,5 @@ break;

case 'changeRootAttribute': {
if (!operation.root._isLoaded) {
return;
}
const rootName = operation.root.rootName;

@@ -207,17 +221,21 @@ this._bufferRootAttributeChange(rootName, operation.key, operation.oldValue, operation.newValue);

bufferMarkerChange(markerName, oldMarkerData, newMarkerData) {
const buffered = this._changedMarkers.get(markerName);
if (oldMarkerData.range && oldMarkerData.range.root.is('rootElement') && !oldMarkerData.range.root._isLoaded) {
oldMarkerData.range = null;
}
if (newMarkerData.range && newMarkerData.range.root.is('rootElement') && !newMarkerData.range.root._isLoaded) {
newMarkerData.range = null;
}
let buffered = this._changedMarkers.get(markerName);
if (!buffered) {
this._changedMarkers.set(markerName, {
newMarkerData,
oldMarkerData
});
buffered = { newMarkerData, oldMarkerData };
this._changedMarkers.set(markerName, buffered);
}
else {
buffered.newMarkerData = newMarkerData;
if (buffered.oldMarkerData.range == null && newMarkerData.range == null) {
// The marker is going to be removed (`newMarkerData.range == null`) but it did not exist before the first buffered change
// (`buffered.oldMarkerData.range == null`). In this case, do not keep the marker in buffer at all.
this._changedMarkers.delete(markerName);
}
}
if (buffered.oldMarkerData.range == null && newMarkerData.range == null) {
// The marker is going to be removed (`newMarkerData.range == null`) but it did not exist before the first buffered change
// (`buffered.oldMarkerData.range == null`). In this case, do not keep the marker in buffer at all.
this._changedMarkers.delete(markerName);
}
}

@@ -503,3 +521,3 @@ /**

if (diffItem.state !== undefined) {
// Root `state` can only toggle between of the values ('attached' or 'detached') and no value. It cannot be any other way,
// Root `state` can only toggle between one of the values and no value. It cannot be any other way,
// because if the root was originally attached it can only become detached. Then, if it is re-attached in the same batch of

@@ -576,5 +594,40 @@ // changes, it gets back to "no change" (which means no value). Same if the root was originally detached.

/**
* Buffers all the data related to given root like it was all just added to the editor.
*
* Following changes are buffered:
*
* * root is attached,
* * all root content is inserted,
* * all root attributes are added,
* * all markers inside the root are added.
*
* @internal
*/
_bufferRootLoad(root) {
if (!root.isAttached()) {
return;
}
this._bufferRootStateChange(root.rootName, true);
this._markInsert(root, 0, root.maxOffset);
// Buffering root attribute changes makes sense and is actually needed, even though we buffer root state change above.
// Because the root state change is buffered, the root attributes changes are not returned by the differ.
// But, if the root attribute is removed in the same change block, or the root is detached, then the differ results would be wrong.
//
for (const key of root.getAttributeKeys()) {
this._bufferRootAttributeChange(root.rootName, key, null, root.getAttribute(key));
}
for (const marker of this._markerCollection) {
if (marker.getRange().root == root) {
const markerData = marker.getData();
this.bufferMarkerChange(marker.name, { ...markerData, range: null }, markerData);
}
}
}
/**
* Saves and handles an insert change.
*/
_markInsert(parent, offset, howMany) {
if (parent.root.is('rootElement') && !parent.root._isLoaded) {
return;
}
const changeItem = { type: 'insert', offset, howMany, count: this._changeCount++ };

@@ -587,2 +640,5 @@ this._markChange(parent, changeItem);

_markRemove(parent, offset, howMany) {
if (parent.root.is('rootElement') && !parent.root._isLoaded) {
return;
}
const changeItem = { type: 'remove', offset, howMany, count: this._changeCount++ };

@@ -596,2 +652,5 @@ this._markChange(parent, changeItem);

_markAttribute(item) {
if (item.root.is('rootElement') && !item.root._isLoaded) {
return;
}
const changeItem = { type: 'attribute', offset: item.startOffset, howMany: item.offsetSize, count: this._changeCount++ };

@@ -598,0 +657,0 @@ this._markChange(item.parent, changeItem);

@@ -128,6 +128,14 @@ /**

* @param includeDetached Specified whether detached roots should be returned as well.
* @returns Roots names.
*/
getRootNames(includeDetached?: boolean): Array<string>;
/**
* Returns an array with all roots added to the document (except the {@link #graveyard graveyard root}).
*
* Detached roots **are not** returned by this method by default. This is to make sure that all features or algorithms that operate
* on the document data know which roots are still a part of the document and should be processed.
*
* @param includeDetached Specified whether detached roots should be returned as well.
*/
getRoots(includeDetached?: boolean): Array<RootElement>;
/**
* Used to register a post-fixer callback. A post-fixer mechanism guarantees that the features

@@ -134,0 +142,0 @@ * will operate on a correct model state.

@@ -182,8 +182,17 @@ /**

* @param includeDetached Specified whether detached roots should be returned as well.
* @returns Roots names.
*/
getRootNames(includeDetached = false) {
return this.getRoots(includeDetached).map(root => root.rootName);
}
/**
* Returns an array with all roots added to the document (except the {@link #graveyard graveyard root}).
*
* Detached roots **are not** returned by this method by default. This is to make sure that all features or algorithms that operate
* on the document data know which roots are still a part of the document and should be processed.
*
* @param includeDetached Specified whether detached roots should be returned as well.
*/
getRoots(includeDetached = false) {
return Array.from(this.roots)
.filter(root => root.rootName != graveyardName && (includeDetached || root.isAttached()))
.map(root => root.rootName);
.filter(root => root != this.graveyard && (includeDetached || root.isAttached()) && root._isLoaded);
}

@@ -287,8 +296,4 @@ /**

_getDefaultRoot() {
for (const root of this.roots) {
if (root !== this.graveyard) {
return root;
}
}
return this.graveyard;
const roots = this.getRoots();
return roots.length ? roots[0] : this.graveyard;
}

@@ -295,0 +300,0 @@ /**

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

const schema = this._model.schema;
if (position.root.rootName == '$graveyard') {
return null;
}
let attrs = null;

@@ -871,0 +874,0 @@ if (!this.isCollapsed) {

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

* which calls callbacks and returns array of values returned by these callbacks.
*
*/

@@ -775,0 +774,0 @@ private _runPendingChanges;

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

* which calls callbacks and returns array of values returned by these callbacks.
*
*/

@@ -798,0 +797,0 @@ _runPendingChanges() {

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

*/
_validate(): void;
/**
* @inheritDoc
*/
_execute(): void;

@@ -66,0 +62,0 @@ /**

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

import Operation from './operation';
import { CKEditorError } from '@ckeditor/ckeditor5-utils';
/**

@@ -66,25 +65,2 @@ * Operation that creates (or attaches) or detaches a root element.

*/
_validate() {
// Keep in mind that at this point the root will always exist as it was created in the `constructor()`, even for detach operation.
const root = this._document.getRoot(this.rootName);
if (root.isAttached() && this.isAdd) {
/**
* Trying to attach a root that is already attached.
*
* @error root-operation-root-attached
*/
throw new CKEditorError('root-operation-root-attached', this);
}
else if (!root.isAttached() && !this.isAdd) {
/**
* Trying to detach a root that is already detached.
*
* @error root-operation-root-detached
*/
throw new CKEditorError('root-operation-root-detached', this);
}
}
/**
* @inheritDoc
*/
_execute() {

@@ -91,0 +67,0 @@ this._document.getRoot(this.rootName)._isAttached = this.isAdd;

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

/**
* Informs if the root element is loaded (default).
*
* @internal
*/
_isLoaded: boolean;
/**
* Creates root element.

@@ -29,0 +35,0 @@ *

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

this._isAttached = true;
/**
* Informs if the root element is loaded (default).
*
* @internal
*/
this._isLoaded = true;
this._document = document;

@@ -28,0 +34,0 @@ this.rootName = rootName;

@@ -680,2 +680,7 @@ /**

getNearestSelectionRange(position, direction = 'both') {
if (position.root.rootName == '$graveyard') {
// No valid selection range in the graveyard.
// This is important when getting the document selection default range.
return null;
}
// Return collapsed range if provided position is valid.

@@ -682,0 +687,0 @@ if (this.checkChild(position, '$text')) {

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

const { schema, document } = writer.model;
for (const rootName of document.getRootNames()) {
const root = document.getRoot(rootName);
for (const root of document.getRoots()) {
if (root.isEmpty && !schema.checkChild(root, '$text')) {

@@ -21,0 +20,0 @@ // If paragraph element is allowed in the root, create paragraph element.

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

/**
* Placeholder of editable element.
*
* ```ts
* editor.editing.view.document.getRoot( 'main' ).placeholder = 'New placeholder';
* ```
*
* @observable
*/
placeholder?: string;
/**
* Creates an editable element.

@@ -42,0 +52,0 @@ *

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

this.set('isFocused', false);
this.set('placeholder', undefined);
this.bind('isReadOnly').to(document);

@@ -36,0 +37,0 @@ this.bind('isFocused').to(document, 'isFocused', isFocused => isFocused && document.selection.editableElement == this);

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

this.view.hasDomSelection = true;
// Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element).
this.focusObserver.flush();
if (this.selection.isEqual(newViewSelection) && this.domConverter.isDomSelectionCorrect(domSelection)) {

@@ -169,4 +171,2 @@ return;

}
// Mark the latest focus change as complete (we got new selection after the focus so the selection is in the focused element).
this.focusObserver.flush();
if (this.selection.isSimilar(newViewSelection)) {

@@ -173,0 +173,0 @@ // If selection was equal and we are at this point of algorithm, it means that it was incorrect.

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

import type DowncastWriter from './downcastwriter';
import type EditableElement from './editableelement';
import type Element from './element';

@@ -17,3 +18,3 @@ import type View from './view';

*
* To change the placeholder text, simply call this method again with new options.
* To change the placeholder text, change value of the `placeholder` property in the provided `element`.
*

@@ -25,3 +26,2 @@ * To disable the placeholder, use {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} helper.

* @param options.element Element that will gain a placeholder. See `options.isDirectHost` to learn more.
* @param options.text Placeholder text.
* @param options.isDirectHost If set `false`, the placeholder will not be enabled directly

@@ -33,6 +33,5 @@ * in the passed `element` but in one of its children (selected automatically, i.e. a first empty child element).

*/
export declare function enablePlaceholder({ view, element, text, isDirectHost, keepOnFocus }: {
export declare function enablePlaceholder({ view, element, isDirectHost, keepOnFocus }: {
view: View;
element: Element;
text: string;
element: PlaceholderableElement | EditableElement;
isDirectHost?: boolean;

@@ -90,1 +89,10 @@ keepOnFocus?: boolean;

export declare function needsPlaceholder(element: Element, keepOnFocus: boolean): boolean;
/**
* Element that could have a placeholder.
*/
export interface PlaceholderableElement extends Element {
/**
* The text of element's placeholder.
*/
placeholder?: string;
}

@@ -15,3 +15,3 @@ /**

*
* To change the placeholder text, simply call this method again with new options.
* To change the placeholder text, change value of the `placeholder` property in the provided `element`.
*

@@ -23,3 +23,2 @@ * To disable the placeholder, use {@link module:engine/view/placeholder~disablePlaceholder `disablePlaceholder()`} helper.

* @param options.element Element that will gain a placeholder. See `options.isDirectHost` to learn more.
* @param options.text Placeholder text.
* @param options.isDirectHost If set `false`, the placeholder will not be enabled directly

@@ -31,3 +30,3 @@ * in the passed `element` but in one of its children (selected automatically, i.e. a first empty child element).

*/
export function enablePlaceholder({ view, element, text, isDirectHost = true, keepOnFocus = false }) {
export function enablePlaceholder({ view, element, isDirectHost = true, keepOnFocus = false }) {
const doc = view.document;

@@ -45,11 +44,21 @@ // Use a single a single post fixer per—document to update all placeholders.

}
// Store information about the element placeholder under its document.
documentPlaceholders.get(doc).set(element, {
text,
isDirectHost,
keepOnFocus,
hostElement: isDirectHost ? element : null
});
// Update the placeholders right away.
view.change(writer => updateDocumentPlaceholders(doc, writer));
if (element.is('editableElement')) {
element.on('change:placeholder', (evtInfo, evt, text) => {
setPlaceholder(text);
});
}
if (element.placeholder) {
setPlaceholder(element.placeholder);
}
function setPlaceholder(text) {
// Store information about the element placeholder under its document.
documentPlaceholders.get(doc).set(element, {
text,
isDirectHost,
keepOnFocus,
hostElement: isDirectHost ? element : null
});
// Update the placeholders right away.
view.change(writer => updateDocumentPlaceholders(doc, writer));
}
}

@@ -56,0 +65,0 @@ /**

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

import type Item from './item';
import KeyObserver from './observer/keyobserver';
import FakeSelectionObserver from './observer/fakeselectionobserver';
import MutationObserver from './observer/mutationobserver';
import SelectionObserver from './observer/selectionobserver';
import FocusObserver from './observer/focusobserver';
import CompositionObserver from './observer/compositionobserver';
import InputObserver from './observer/inputobserver';
import ArrowKeysObserver from './observer/arrowkeysobserver';
import TabObserver from './observer/tabobserver';
type IfTrue<T> = T extends true ? true : never;

@@ -172,10 +181,4 @@ type DomRange = globalThis.Range;

addObserver(ObserverConstructor: ObserverConstructor): Observer;
getObserver<T extends ObserverConstructor>(ObserverConstructor: T): T extends AlwaysRegisteredObservers ? InstanceType<T> : InstanceType<T> | undefined;
/**
* Returns observer of the given type or `undefined` if such observer has not been added yet.
*
* @param ObserverConstructor The constructor of an observer to get.
* @returns Observer instance or undefined.
*/
getObserver<T extends ObserverConstructor>(ObserverConstructor: T): InstanceType<T> | undefined;
/**
* Disables all added observers.

@@ -482,2 +485,6 @@ */

};
/**
* Observers that are always registered.
*/
export type AlwaysRegisteredObservers = typeof MutationObserver | typeof FocusObserver | typeof SelectionObserver | typeof KeyObserver | typeof FakeSelectionObserver | typeof CompositionObserver | typeof ArrowKeysObserver | typeof InputObserver | typeof TabObserver;
export {};

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

// Add default observers.
// Make sure that this list matches AlwaysRegisteredObservers type.
this.addObserver(MutationObserver);

@@ -109,0 +110,0 @@ this.addObserver(FocusObserver);

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

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc