Socket
Socket
Sign inDemoInstall

@ckeditor/ckeditor5-utils

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-utils - npm Package Compare versions

Comparing version 35.3.2 to 35.4.0

10

package.json
{
"name": "@ckeditor/ckeditor5-utils",
"version": "35.3.2",
"version": "35.4.0",
"description": "Miscellaneous utilities used by CKEditor 5.",

@@ -17,6 +17,6 @@ "keywords": [

"devDependencies": {
"@ckeditor/ckeditor5-build-classic": "^35.3.2",
"@ckeditor/ckeditor5-editor-classic": "^35.3.2",
"@ckeditor/ckeditor5-core": "^35.3.2",
"@ckeditor/ckeditor5-engine": "^35.3.2",
"@ckeditor/ckeditor5-build-classic": "^35.4.0",
"@ckeditor/ckeditor5-editor-classic": "^35.4.0",
"@ckeditor/ckeditor5-core": "^35.4.0",
"@ckeditor/ckeditor5-engine": "^35.4.0",
"@types/lodash-es": "^4.17.6",

@@ -23,0 +23,0 @@ "typescript": "^4.8.4"

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

* Traverses both structures to find out whether there is a reference that is shared between both structures.
*
* @param {Object|Array} obj1
* @param {Object|Array} obj2
* @returns {Boolean}
*/

@@ -30,5 +26,7 @@ export default function areConnectedThroughProperties(obj1, obj2) {

}
// Traverses JS structure and stores all sub-nodes, including the head node.
// It walks into each iterable structures with the `try catch` block to omit errors that might be thrown during
// tree walking. All primitives, functions and built-ins are skipped.
/**
* Traverses JS structure and stores all sub-nodes, including the head node.
* It walks into each iterable structures with the `try catch` block to omit errors that might be thrown during
* tree walking. All primitives, functions and built-ins are skipped.
*/
function getSubNodes(head) {

@@ -35,0 +33,0 @@ const nodes = [head];

@@ -27,15 +27,15 @@ /**

*
* /**
* * Error thrown when a plugin cannot be loaded due to JavaScript errors, lack of plugins with a given name, etc.
* *
* * @error plugin-load
* * @param pluginName The name of the plugin that could not be loaded.
* * @param moduleName The name of the module which tried to load this plugin.
* * /
* throw new CKEditorError( 'plugin-load', {
* pluginName: 'foo',
* moduleName: 'bar'
* } );
*
* @extends Error
* ```ts
* /**
* * Error thrown when a plugin cannot be loaded due to JavaScript errors, lack of plugins with a given name, etc.
* *
* * @error plugin-load
* * @param pluginName The name of the plugin that could not be loaded.
* * @param moduleName The name of the module which tried to load this plugin.
* *\/
* throw new CKEditorError( 'plugin-load', {
* pluginName: 'foo',
* moduleName: 'bar'
* } );
* ```
*/

@@ -46,5 +46,5 @@ export default class CKEditorError extends Error {

*
* @param {String} errorName The error id in an `error-name` format. A link to this error documentation page will be added
* @param errorName The error id in an `error-name` format. A link to this error documentation page will be added
* to the thrown error's `message`.
* @param {Object|null} context A context of the error by which the {@link module:watchdog/watchdog~Watchdog watchdog}
* @param context A context of the error by which the {@link module:watchdog/watchdog~Watchdog watchdog}
* is able to determine which editor crashed. It should be an editor instance or a property connected to it. It can be also

@@ -54,3 +54,3 @@ * a `null` value if the editor should not be restarted in case of the error (e.g. during the editor initialization).

* to check if the object works as the context.
* @param {Object} [data] Additional data describing the error. A stringified version of this object
* @param data Additional data describing the error. A stringified version of this object
* will be appended to the error message, so the data are quickly visible in the console. The original

@@ -61,17 +61,4 @@ * data object will also be later available under the {@link #data} property.

super(getErrorMessage(errorName, data));
/**
* @type {String}
*/
this.name = 'CKEditorError';
/**
* A context of the error by which the Watchdog is able to determine which editor crashed.
*
* @type {Object|null}
*/
this.context = context;
/**
* The additional error data passed to the constructor. Undefined if none was passed.
*
* @type {Object|undefined}
*/
this.data = data;

@@ -81,3 +68,2 @@ }

* Checks if the error is of the `CKEditorError` type.
* @returns {Boolean}
*/

@@ -92,5 +78,4 @@ is(type) {

*
* @static
* @param {Error} err The error to rethrow.
* @param {Object} context An object connected through properties with the editor instance. This context will be used
* @param err The error to rethrow.
* @param context An object connected through properties with the editor instance. This context will be used
* by the watchdog to verify which editor should be restarted.

@@ -122,10 +107,12 @@ */

*
* /**
* * There was a problem processing the configuration of the toolbar. The item with the given
* * name does not exist, so it was omitted when rendering the toolbar.
* *
* * @error toolbarview-item-unavailable
* * @param {String} name The name of the component.
* * /
* logWarning( 'toolbarview-item-unavailable', { name } );
* ```ts
* /**
* * There was a problem processing the configuration of the toolbar. The item with the given
* * name does not exist, so it was omitted when rendering the toolbar.
* *
* * @error toolbarview-item-unavailable
* * @param {String} name The name of the component.
* *\/
* logWarning( 'toolbarview-item-unavailable', { name } );
* ```
*

@@ -135,4 +122,4 @@ * See also {@link module:utils/ckeditorerror~CKEditorError} for an explanation when to throw an error and when to log

*
* @param {String} errorName The error name to be logged.
* @param {Object} [data] Additional data to be logged.
* @param errorName The error name to be logged.
* @param data Additional data to be logged.
*/

@@ -146,10 +133,12 @@ export function logWarning(errorName, data) {

*
* /**
* * There was a problem processing the configuration of the toolbar. The item with the given
* * name does not exist, so it was omitted when rendering the toolbar.
* *
* * @error toolbarview-item-unavailable
* * @param {String} name The name of the component.
* * /
* logError( 'toolbarview-item-unavailable', { name } );
* ```ts
* /**
* * There was a problem processing the configuration of the toolbar. The item with the given
* * name does not exist, so it was omitted when rendering the toolbar.
* *
* * @error toolbarview-item-unavailable
* * @param {String} name The name of the component.
* *\/
* logError( 'toolbarview-item-unavailable', { name } );
* ```
*

@@ -160,4 +149,4 @@ * **Note**: In most cases logging a warning using {@link module:utils/ckeditorerror~logWarning} is enough.

*
* @param {String} errorName The error name to be logged.
* @param {Object} [data] Additional data to be logged.
* @param errorName The error name to be logged.
* @param data Additional data to be logged.
*/

@@ -167,16 +156,11 @@ export function logError(errorName, data) {

}
// Returns formatted link to documentation message.
//
// @private
// @param {String} errorName
// @returns {string}
/**
* Returns formatted link to documentation message.
*/
function getLinkToDocumentationMessage(errorName) {
return `\nRead more: ${DOCUMENTATION_URL}#error-${errorName}`;
}
// Returns formatted error message.
//
// @private
// @param {String} errorName
// @param {Object} [data]
// @returns {string}
/**
* Returns formatted error message.
*/
function getErrorMessage(errorName, data) {

@@ -197,8 +181,5 @@ const processedObjects = new WeakSet();

}
// Returns formatted console error arguments.
//
// @private
// @param {String} errorName
// @param {Object} [data]
// @returns {Array}
/**
* Returns formatted console error arguments.
*/
function formatConsoleArguments(errorName, data) {

@@ -205,0 +186,0 @@ const documentationMessage = getLinkToDocumentationMessage(errorName);

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

*/
import { Emitter } from './emittermixin';
import EmitterMixin from './emittermixin';
import CKEditorError from './ckeditorerror';

@@ -23,41 +23,5 @@ import uid from './uid';

*
* @mixes module:utils/emittermixin~EmitterMixin
* @typeParam T The type of the collection element.
*/
export default class Collection extends Emitter {
/**
* Creates a new Collection instance.
*
* You can provide an iterable of initial items the collection will be created with:
*
* const collection = new Collection( [ { id: 'John' }, { id: 'Mike' } ] );
*
* console.log( collection.get( 0 ) ); // -> { id: 'John' }
* console.log( collection.get( 1 ) ); // -> { id: 'Mike' }
* console.log( collection.get( 'Mike' ) ); // -> { id: 'Mike' }
*
* Or you can first create a collection and then add new items using the {@link #add} method:
*
* const collection = new Collection();
*
* collection.add( { id: 'John' } );
* console.log( collection.get( 0 ) ); // -> { id: 'John' }
*
* Whatever option you choose, you can always pass a configuration object as the last argument
* of the constructor:
*
* const emptyCollection = new Collection( { idProperty: 'name' } );
* emptyCollection.add( { name: 'John' } );
* console.log( collection.get( 'John' ) ); // -> { name: 'John' }
*
* const nonEmptyCollection = new Collection( [ { name: 'John' } ], { idProperty: 'name' } );
* nonEmptyCollection.add( { name: 'George' } );
* console.log( collection.get( 'George' ) ); // -> { name: 'George' }
* console.log( collection.get( 'John' ) ); // -> { name: 'John' }
*
* @param {Iterable.<Object>|Object} [initialItemsOrOptions] The initial items of the collection or
* the options object.
* @param {Object} [options={}] The options object, when the first argument is an array of initial items.
* @param {String} [options.idProperty='id'] The name of the property which is used to identify an item.
* Items that do not have such a property will be assigned one when added to the collection.
*/
export default class Collection extends EmitterMixin() {
constructor(initialItemsOrOptions = {}, options = {}) {

@@ -85,4 +49,2 @@ super();

* The number of items available in the collection.
*
* @member {Number} #length
*/

@@ -94,4 +56,2 @@ get length() {

* Returns the first item from the collection or null when collection is empty.
*
* @returns {Object|null} The first item or `null` if collection is empty.
*/

@@ -103,4 +63,2 @@ get first() {

* Returns the last item from the collection or null when collection is empty.
*
* @returns {Object|null} The last item or `null` if collection is empty.
*/

@@ -115,5 +73,4 @@ get last() {

*
* @chainable
* @param {Object} item
* @param {Number} [index] The position of the item in the collection. The item
* @param item
* @param index The position of the item in the collection. The item
* is pushed to the collection when `index` not specified.

@@ -131,5 +88,4 @@ * @fires add

*
* @chainable
* @param {Iterable.<Object>} items
* @param {Number} [index] The position of the insertion. Items will be appended if no `index` is specified.
* @param items
* @param index The position of the insertion. Items will be appended if no `index` is specified.
* @fires add

@@ -170,4 +126,4 @@ * @fires change

*
* @param {String|Number} idOrIndex The item ID or index in the collection.
* @returns {Object|null} The requested item or `null` if such item does not exist.
* @param idOrIndex The item ID or index in the collection.
* @returns The requested item or `null` if such item does not exist.
*/

@@ -195,4 +151,4 @@ get(idOrIndex) {

*
* @param {Object|String} itemOrId The item or its ID in the collection.
* @returns {Boolean} `true` if the collection contains the item, `false` otherwise.
* @param itemOrId The item or its ID in the collection.
* @returns `true` if the collection contains the item, `false` otherwise.
*/

@@ -213,4 +169,4 @@ has(itemOrId) {

*
* @param {Object|String} itemOrId The item or its ID in the collection.
* @returns {Number} The index of a given item.
* @param itemOrId The item or its ID in the collection.
* @returns The index of a given item.
*/

@@ -230,4 +186,4 @@ getIndex(itemOrId) {

*
* @param {Object|Number|String} subject The item to remove, its ID or index in the collection.
* @returns {Object} The removed item.
* @param subject The item to remove, its ID or index in the collection.
* @returns The removed item.
* @fires remove

@@ -248,7 +204,6 @@ * @fires change

*
* @param {Function} callback
* @param {Object} callback.item
* @param {Number} callback.index
* @param {Object} [ctx] Context in which the `callback` will be called.
* @returns {Array} The result of mapping.
* @typeParam U The result type of the callback.
* @param callback
* @param ctx Context in which the `callback` will be called.
* @returns The result of mapping.
*/

@@ -261,7 +216,5 @@ map(callback, ctx) {

*
* @param {Function} callback
* @param {Object} callback.item
* @param {Number} callback.index
* @param {Object} [ctx] Context in which the `callback` will be called.
* @returns {Object|undefined} The item for which `callback` returned a true value.
* @param callback
* @param ctx Context in which the `callback` will be called.
* @returns The item for which `callback` returned a true value.
*/

@@ -274,7 +227,5 @@ find(callback, ctx) {

*
* @param {Function} callback
* @param {Object} callback.item
* @param {Number} callback.index
* @param {Object} [ctx] Context in which the `callback` will be called.
* @returns {Array} The array with matching items.
* @param callback
* @param ctx Context in which the `callback` will be called.
* @returns The array with matching items.
*/

@@ -311,92 +262,107 @@ filter(callback, ctx) {

*
* class FactoryClass {
* constructor( data ) {
* this.label = data.label;
* }
* }
* ```ts
* class FactoryClass {
* public label: string;
*
* const source = new Collection( { idProperty: 'label' } );
* const target = new Collection();
* constructor( data: { label: string } ) {
* this.label = data.label;
* }
* }
*
* target.bindTo( source ).as( FactoryClass );
* const source = new Collection<{ label: string }>( { idProperty: 'label' } );
* const target = new Collection<FactoryClass>();
*
* source.add( { label: 'foo' } );
* source.add( { label: 'bar' } );
* target.bindTo( source ).as( FactoryClass );
*
* console.log( target.length ); // 2
* console.log( target.get( 1 ).label ); // 'bar'
* source.add( { label: 'foo' } );
* source.add( { label: 'bar' } );
*
* source.remove( 0 );
* console.log( target.length ); // 1
* console.log( target.get( 0 ).label ); // 'bar'
* console.log( target.length ); // 2
* console.log( target.get( 1 ).label ); // 'bar'
*
* source.remove( 0 );
* console.log( target.length ); // 1
* console.log( target.get( 0 ).label ); // 'bar'
* ```
*
* or the factory driven by a custom callback:
*
* class FooClass {
* constructor( data ) {
* this.label = data.label;
* }
* }
* ```ts
* class FooClass {
* public label: string;
*
* class BarClass {
* constructor( data ) {
* this.label = data.label;
* }
* }
* constructor( data: { label: string } ) {
* this.label = data.label;
* }
* }
*
* const source = new Collection( { idProperty: 'label' } );
* const target = new Collection();
* class BarClass {
* public label: string;
*
* target.bindTo( source ).using( ( item ) => {
* if ( item.label == 'foo' ) {
* return new FooClass( item );
* } else {
* return new BarClass( item );
* }
* } );
* constructor( data: { label: string } ) {
* this.label = data.label;
* }
* }
*
* source.add( { label: 'foo' } );
* source.add( { label: 'bar' } );
* const source = new Collection<{ label: string }>( { idProperty: 'label' } );
* const target = new Collection<FooClass | BarClass>();
*
* console.log( target.length ); // 2
* console.log( target.get( 0 ) instanceof FooClass ); // true
* console.log( target.get( 1 ) instanceof BarClass ); // true
* target.bindTo( source ).using( ( item ) => {
* if ( item.label == 'foo' ) {
* return new FooClass( item );
* } else {
* return new BarClass( item );
* }
* } );
*
* source.add( { label: 'foo' } );
* source.add( { label: 'bar' } );
*
* console.log( target.length ); // 2
* console.log( target.get( 0 ) instanceof FooClass ); // true
* console.log( target.get( 1 ) instanceof BarClass ); // true
* ```
*
* or the factory out of property name:
*
* const source = new Collection( { idProperty: 'label' } );
* const target = new Collection();
* ```ts
* const source = new Collection<{ nested: { value: string } }>();
* const target = new Collection<{ value: string }>();
*
* target.bindTo( source ).using( 'label' );
* target.bindTo( source ).using( 'nested' );
*
* source.add( { label: { value: 'foo' } } );
* source.add( { label: { value: 'bar' } } );
* source.add( { nested: { value: 'foo' } } );
* source.add( { nested: { value: 'bar' } } );
*
* console.log( target.length ); // 2
* console.log( target.get( 0 ).value ); // 'foo'
* console.log( target.get( 1 ).value ); // 'bar'
* console.log( target.length ); // 2
* console.log( target.get( 0 ).value ); // 'foo'
* console.log( target.get( 1 ).value ); // 'bar'
* ```
*
* It's possible to skip specified items by returning falsy value:
* It's possible to skip specified items by returning null value:
*
* const source = new Collection();
* const target = new Collection();
* ```ts
* const source = new Collection<{ hidden: boolean }>();
* const target = new Collection<{ hidden: boolean }>();
*
* target.bindTo( source ).using( item => {
* if ( item.hidden ) {
* return null;
* }
* target.bindTo( source ).using( item => {
* if ( item.hidden ) {
* return null;
* }
*
* return item;
* } );
* return item;
* } );
*
* source.add( { hidden: true } );
* source.add( { hidden: false } );
* source.add( { hidden: true } );
* source.add( { hidden: false } );
*
* console.log( source.length ); // 2
* console.log( target.length ); // 1
* console.log( source.length ); // 2
* console.log( target.length ); // 1
* ```
*
* **Note**: {@link #clear} can be used to break the binding.
*
* @param {module:utils/collection~Collection} externalCollection A collection to be bound.
* @returns {module:utils/collection~CollectionBindToChain} The binding chain object.
* @typeParam S The type of `externalCollection` element.
* @param externalCollection A collection to be bound.
* @returns The binding chain object.
*/

@@ -430,4 +396,3 @@ bindTo(externalCollection) {

*
* @private
* @param {Function} factory A function which produces collection items.
* @param factory A function which produces collection items.
*/

@@ -437,4 +402,2 @@ _setUpBindToBinding(factory) {

// Adds the item to the collection once a change has been done to the external collection.
//
// @private
const addItem = (evt, externalItem, index) => {

@@ -543,5 +506,3 @@ const isExternalBoundToThis = externalCollection._bindToCollection == this;

*
* @private
* @param {Object} item Item to be added.
* @returns {String}
* @param item Item to be added.
*/

@@ -580,5 +541,4 @@ _getItemIdBeforeAdding(item) {

*
* @private
* @param {Object|Number|String} subject The item to remove, its id or index in the collection.
* @returns {Array} Returns an array with the removed item and its index.
* @param subject The item to remove, its id or index in the collection.
* @returns Returns an array with the removed item and its index.
* @fires remove

@@ -630,4 +590,2 @@ */

* Iterable interface.
*
* @returns {Iterator.<*>}
*/

@@ -634,0 +592,0 @@ [Symbol.iterator]() {

@@ -14,11 +14,13 @@ /**

*
* compareArrays( [ 0, 2 ], [ 0, 2 ] ); // 'same'
* compareArrays( [ 0, 2 ], [ 0, 2, 1 ] ); // 'prefix'
* compareArrays( [ 0, 2 ], [ 0 ] ); // 'extension'
* compareArrays( [ 0, 2 ], [ 1, 2 ] ); // 0
* compareArrays( [ 0, 2 ], [ 0, 1 ] ); // 1
* ```ts
* compareArrays( [ 0, 2 ], [ 0, 2 ] ); // 'same'
* compareArrays( [ 0, 2 ], [ 0, 2, 1 ] ); // 'prefix'
* compareArrays( [ 0, 2 ], [ 0 ] ); // 'extension'
* compareArrays( [ 0, 2 ], [ 1, 2 ] ); // 0
* compareArrays( [ 0, 2 ], [ 0, 1 ] ); // 1
* ```
*
* @param {Array} a Array that is compared.
* @param {Array} b Array to compare with.
* @returns {module:utils/comparearrays~ArrayRelation|Number} How array `a` is related to `b`.
* @param a Array that is compared.
* @param b Array to compare with.
* @returns How array `a` is related to `b`.
*/

@@ -25,0 +27,0 @@ export default function compareArrays(a, b) {

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

* Handles a configuration dictionary.
*
* @typeParam Cfg A type of the configuration dictionary.
*/

@@ -17,12 +19,6 @@ export default class Config {

*
* @param {Object} [configurations] The initial configurations to be set. Usually, provided by the user.
* @param {Object} [defaultConfigurations] The default configurations. Usually, provided by the system.
* @param configurations The initial configurations to be set. Usually, provided by the user.
* @param defaultConfigurations The default configurations. Usually, provided by the system.
*/
constructor(configurations, defaultConfigurations) {
/**
* Store for the whole configuration.
*
* @private
* @member {Object}
*/
this._config = {};

@@ -40,53 +36,5 @@ // Set default configuration.

}
/**
* Set configuration values.
*
* It accepts both a name/value pair or an object, which properties and values will be used to set
* configurations.
*
* It also accepts setting a "deep configuration" by using dots in the name. For example, `'resize.width'` sets
* the value for the `width` configuration in the `resize` subset.
*
* config.set( 'width', 500 );
* config.set( 'toolbar.collapsed', true );
*
* // Equivalent to:
* config.set( {
* width: 500
* toolbar: {
* collapsed: true
* }
* } );
*
* Passing an object as the value will amend the configuration, not replace it.
*
* config.set( 'toolbar', {
* collapsed: true,
* } );
*
* config.set( 'toolbar', {
* color: 'red',
* } );
*
* config.get( 'toolbar.collapsed' ); // true
* config.get( 'toolbar.color' ); // 'red'
*
* @param {String|Object} name The configuration name or an object from which take properties as
* configuration entries. Configuration names are case-sensitive.
* @param {*} value The configuration value. Used if a name is passed.
*/
set(name, value) {
this._setToTarget(this._config, name, value);
}
/**
* Does exactly the same as {@link #set} with one exception – passed configuration extends
* existing one, but does not overwrite already defined values.
*
* This method is supposed to be called by plugin developers to setup plugin's configurations. It would be
* rarely used for other needs.
*
* @param {String|Object} name The configuration name or an object from which take properties as
* configuration entries. Configuration names are case-sensitive.
* @param {*} value The configuration value. Used if a name is passed.
*/
define(name, value) {

@@ -99,10 +47,14 @@ const isDefine = true;

*
* config.get( 'name' );
* ```ts
* config.get( 'name' );
* ```
*
* Deep configurations can be retrieved by separating each part with a dot.
*
* config.get( 'toolbar.collapsed' );
* ```ts
* config.get( 'toolbar.collapsed' );
* ```
*
* @param {String} name The configuration name. Configuration names are case-sensitive.
* @returns {*} The configuration value or `undefined` if the configuration entry was not found.
* @param name The configuration name. Configuration names are case-sensitive.
* @returns The configuration value or `undefined` if the configuration entry was not found.
*/

@@ -114,4 +66,2 @@ get(name) {

* Iterates over all top level configuration names.
*
* @returns {Iterable.<String>}
*/

@@ -126,8 +76,7 @@ *names() {

*
* @private
* @param {Object} target Nested config object.
* @param {String|Object} name The configuration name or an object from which take properties as
* @param target Nested config object.
* @param name The configuration name or an object from which take properties as
* configuration entries. Configuration names are case-sensitive.
* @param {*} value The configuration value. Used if a name is passed.
* @param {Boolean} [isDefine=false] Define if passed configuration should overwrite existing one.
* @param value The configuration value. Used if a name is passed.
* @param isDefine Define if passed configuration should overwrite existing one.
*/

@@ -173,6 +122,5 @@ _setToTarget(target, name, value, isDefine = false) {

*
* @private
* @param {Object} source level of nested object.
* @param {String} name The configuration name. Configuration names are case-sensitive.
* @returns {*} The configuration value or `undefined` if the configuration entry was not found.
* @param source level of nested object.
* @param name The configuration name. Configuration names are case-sensitive.
* @returns The configuration value or `undefined` if the configuration entry was not found.
*/

@@ -199,6 +147,5 @@ _getFromSource(source, name) {

*
* @private
* @param {Object} target Nested config object.
* @param {Object} configuration Configuration data set
* @param {Boolean} [isDefine] Defines if passed configuration is default configuration or not.
* @param target Nested config object.
* @param configuration Configuration data set
* @param isDefine Defines if passed configuration is default configuration or not.
*/

@@ -211,15 +158,14 @@ _setObjectToTarget(target, configuration, isDefine) {

}
// Clones configuration object or value.
// @param {*} source Source configuration
// @returns {*} Cloned configuration value.
/**
* Clones configuration object or value.
*/
function cloneConfig(source) {
return cloneDeepWith(source, leaveDOMReferences);
}
// A customized function for cloneDeepWith.
// It will leave references to DOM Elements instead of cloning them.
//
// @param {*} value
// @returns {Element|undefined}
/**
* A customized function for cloneDeepWith.
* It will leave references to DOM Elements instead of cloning them.
*/
function leaveDOMReferences(value) {
return isElement(value) ? value : undefined;
}

@@ -11,6 +11,8 @@ /**

*
* count( [ 1, 2, 3, 4, 5 ] ); // 5;
* ```ts
* count( [ 1, 2, 3, 4, 5 ] ); // 5;
* ```
*
* @param {Iterable.<*>} iterable Any iterable.
* @returns {Number} Number of items returned by that iterable.
* @param iterable Any iterable.
* @returns Number of items returned by that iterable.
*/

@@ -17,0 +19,0 @@ export default function count(iterable) {

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

*
* diff( 'aba', 'acca' ); // [ 'equal', 'insert', 'insert', 'delete', 'equal' ]
* ```ts
* diff( 'aba', 'acca' ); // [ 'equal', 'insert', 'insert', 'delete', 'equal' ]
* ```
*

@@ -23,6 +25,6 @@ * This function is based on the "O(NP) Sequence Comparison Algorithm" by Sun Wu, Udi Manber, Gene Myers, Webb Miller.

*
* @param {Array|String} a Input array or string.
* @param {Array|String} b Output array or string.
* @param {Function} [cmp] Optional function used to compare array values, by default === is used.
* @returns {Array.<module:utils/diff~DiffResult>} Array of changes.
* @param a Input array or string.
* @param b Output array or string.
* @param cmp Optional function used to compare array values, by default === is used.
* @returns Array of changes.
*/

@@ -29,0 +31,0 @@ export default function diff(a, b, cmp) {

@@ -12,19 +12,22 @@ /**

*
* const input = Array.from( 'abc' );
* const output = Array.from( 'xaby' );
* const changes = diffToChanges( diff( input, output ), output );
* ```ts
* const input = Array.from( 'abc' );
* const output = Array.from( 'xaby' );
* const changes = diffToChanges( diff( input, output ), output );
*
* changes.forEach( change => {
* if ( change.type == 'insert' ) {
* input.splice( change.index, 0, ...change.values );
* } else if ( change.type == 'delete' ) {
* input.splice( change.index, change.howMany );
* }
* } );
* changes.forEach( change => {
* if ( change.type == 'insert' ) {
* input.splice( change.index, 0, ...change.values );
* } else if ( change.type == 'delete' ) {
* input.splice( change.index, change.howMany );
* }
* } );
*
* input.join( '' ) == output.join( '' ); // -> true
* input.join( '' ) == output.join( '' ); // -> true
* ```
*
* @param {Array.<module:utils/diff~DiffResult>} diff Result of {@link module:utils/diff~diff}.
* @param {String|Array} output The string or array which was passed as diff's output.
* @returns {Array.<module:utils/difftochanges~Change>} Set of changes (insert or delete) which need to be applied to the input
* @typeParam T The type of output array element.
* @param diff Result of {@link module:utils/diff~diff}.
* @param output The string or array which was passed as diff's output.
* @returns Set of changes (insert or delete) which need to be applied to the input
* in order to transform it into the output.

@@ -31,0 +34,0 @@ */

@@ -13,13 +13,15 @@ /**

*
* createElement( document, 'p' ); // <p>
* createElement( document, 'p', { class: 'foo' } ); // <p class="foo">
* createElement( document, 'p', null, 'foo' ); // <p>foo</p>
* createElement( document, 'p', null, [ 'foo', createElement( document, 'img' ) ] ); // <p>foo<img></p>
* ```ts
* createElement( document, 'p' ); // <p>
* createElement( document, 'p', { class: 'foo' } ); // <p class="foo">
* createElement( document, 'p', null, 'foo' ); // <p>foo</p>
* createElement( document, 'p', null, [ 'foo', createElement( document, 'img' ) ] ); // <p>foo<img></p>
* ```
*
* @param {Document} doc Document used to create element.
* @param {String} name Name of the element.
* @param {Object} [attributes] Object keys will become attributes keys and object values will became attributes values.
* @param {Node|String|Iterable.<Node|String>} [children] Child or any iterable of children. Strings will be automatically turned
* @param doc Document used to create element.
* @param name Name of the element.
* @param attributes Object keys will become attributes keys and object values will became attributes values.
* @param children Child or any iterable of children. Strings will be automatically turned
* into Text nodes.
* @returns {Element} Created element.
* @returns Created element.
*/

@@ -26,0 +28,0 @@ export default function createElement(doc, name, attributes = {}, children = []) {

@@ -5,33 +5,14 @@ /**

*/
/* eslint-disable new-cap */
/**
* @module utils/dom/emittermixin
*/
import { _getEmitterListenedTo, _setEmitterId, Emitter as BaseEmitter } from '../emittermixin';
import EmitterMixin, { _getEmitterListenedTo, _setEmitterId } from '../emittermixin';
import uid from '../uid';
import isNode from './isnode';
import isWindow from './iswindow';
/**
* Mixin that injects the DOM events API into its host. It provides the API
* compatible with {@link module:utils/emittermixin~EmitterMixin}.
*
* DOM emitter mixin is by default available in the {@link module:ui/view~View} class,
* but it can also be mixed into any other class:
*
* import mix from '../utils/mix.js';
* import DomEmitterMixin from '../utils/dom/emittermixin.js';
* import { Emitter } from '../utils/emittermixin.js';
*
* class SomeView extends DomEmitterMixin( Emitter ) {}
*
* const view = new SomeView();
* view.listenTo( domElement, ( evt, domEvt ) => {
* console.log( evt, domEvt );
* } );
*
* @mixin EmitterMixin
* @mixes module:utils/emittermixin~EmitterMixin
* @implements module:utils/dom/emittermixin~Emitter
*/
const defaultEmitterClass = DomEmitterMixin(EmitterMixin());
export default function DomEmitterMixin(base) {
if (!base) {
return defaultEmitterClass;
}
class Mixin extends base {

@@ -50,3 +31,3 @@ listenTo(emitter, event, callback, options = {}) {

// Execute parent class method with Emitter (or ProxyEmitter) instance.
BaseEmitter.prototype.listenTo.call(this, emitter, event, callback, options);
super.listenTo(emitter, event, callback, options);
}

@@ -64,3 +45,3 @@ }

// Execute parent class method with Emitter (or ProxyEmitter) instance.
BaseEmitter.prototype.stopListening.call(this, emitter, event, callback);
super.stopListening(emitter, event, callback);
}

@@ -71,10 +52,9 @@ }

*
* @private
* @param {Node|Window} node DOM Node of the ProxyEmitter.
* @param {Object} [options] Additional options.
* @param {Boolean} [options.useCapture=false] Indicates that events of this type will be dispatched to the registered
* @param node DOM Node of the ProxyEmitter.
* @param options Additional options.
* @param options.useCapture Indicates that events of this type will be dispatched to the registered
* listener before being dispatched to any EventTarget beneath it in the DOM tree.
* @param {Boolean} [options.usePassive=false] Indicates that the function specified by listener will never call preventDefault()
* @param options.usePassive Indicates that the function specified by listener will never call preventDefault()
* and prevents blocking browser's main thread by this event handler.
* @returns {module:utils/dom/emittermixin~ProxyEmitter|null} ProxyEmitter instance bound to the DOM Node.
* @returns ProxyEmitter instance bound to the DOM Node.
*/

@@ -87,5 +67,3 @@ _getProxyEmitter(node, options) {

*
* @private
* @param {Node|Window} node DOM Node of the ProxyEmitter.
* @returns {Array.<module:utils/dom/emittermixin~ProxyEmitter>}
* @param node DOM Node of the ProxyEmitter.
*/

@@ -103,3 +81,2 @@ _getAllProxyEmitters(node) {

}
export const Emitter = DomEmitterMixin(BaseEmitter);
// Backward compatibility with `mix`

@@ -112,7 +89,7 @@ ([

]).forEach(key => {
DomEmitterMixin[key] = Emitter.prototype[key];
DomEmitterMixin[key] = defaultEmitterClass.prototype[key];
});
/**
* Creates a ProxyEmitter instance. Such an instance is a bridge between a DOM Node firing events
* and any Host listening to them. It is backwards compatible with {@link module:utils/emittermixin~EmitterMixin#on}.
* and any Host listening to them. It is backwards compatible with {@link module:utils/emittermixin~Emitter#on}.
* There is a separate instance for each combination of modes (useCapture & usePassive). The mode is concatenated with

@@ -142,14 +119,10 @@ * UID stored in HTMLElement to give each instance unique identifier.

* fire( click, DOM Event )
*
* @mixes module:utils/emittermixin~EmitterMixin
* @implements module:utils/dom/emittermixin~Emitter
* @private
*/
class ProxyEmitter extends BaseEmitter {
class ProxyEmitter extends EmitterMixin() {
/**
* @param {Node|Window} node DOM Node that fires events.
* @param {Object} [options] Additional options.
* @param {Boolean} [options.useCapture=false] Indicates that events of this type will be dispatched to the registered
* @param node DOM Node that fires events.
* @param options Additional options.
* @param options.useCapture Indicates that events of this type will be dispatched to the registered
* listener before being dispatched to any EventTarget beneath it in the DOM tree.
* @param {Boolean} [options.usePassive=false] Indicates that the function specified by listener will never call preventDefault()
* @param options.usePassive Indicates that the function specified by listener will never call preventDefault()
* and prevents blocking browser's main thread by this event handler.

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

* **Note**: This is automatically called by the
* {@link module:utils/emittermixin~EmitterMixin#listenTo `EmitterMixin#listenTo()`}.
* {@link module:utils/emittermixin~Emitter#listenTo `Emitter#listenTo()`}.
*
* @method module:utils/dom/emittermixin~ProxyEmitter#attach
* @param {String} event The name of the event.
* @param event The name of the event.
*/

@@ -199,6 +171,5 @@ attach(event) {

* **Note**: This is automatically called by the
* {@link module:utils/emittermixin~EmitterMixin#stopListening `EmitterMixin#stopListening()`}.
* {@link module:utils/emittermixin~Emitter#stopListening `Emitter#stopListening()`}.
*
* @method module:utils/dom/emittermixin~ProxyEmitter#detach
* @param {String} event The name of the event.
* @param event The name of the event.
*/

@@ -217,14 +188,10 @@ detach(event) {

*
* @protected
* @method module:utils/dom/emittermixin~ProxyEmitter#_addEventListener
* @param {String} event The name of the event.
* @param {Function} callback The function to be called on event.
* @param {Object} [options={}] Additional options.
* @param {module:utils/priorities~PriorityString} [options.priority='normal'] The priority of this event callback. The higher
* the priority value the sooner the callback will be fired. Events having the same priority are called in the
* order they were added.
* @internal
* @param event The name of the event.
* @param callback The function to be called on event.
* @param options Additional options.
*/
_addEventListener(event, callback, options) {
this.attach(event);
BaseEmitter.prototype._addEventListener.call(this, event, callback, options);
EmitterMixin().prototype._addEventListener.call(this, event, callback, options);
}

@@ -234,9 +201,8 @@ /**

*
* @protected
* @method module:utils/dom/emittermixin~ProxyEmitter#_removeEventListener
* @param {String} event The name of the event.
* @param {Function} callback The function to stop being called.
* @internal
* @param event The name of the event.
* @param callback The function to stop being called.
*/
_removeEventListener(event, callback) {
BaseEmitter.prototype._removeEventListener.call(this, event, callback);
EmitterMixin().prototype._removeEventListener.call(this, event, callback);
this.detach(event);

@@ -249,6 +215,4 @@ }

*
* @private
* @method module:utils/dom/emittermixin~ProxyEmitter#_createDomListener
* @param {String} event The name of the event.
* @returns {Function} The DOM listener callback.
* @param event The name of the event.
* @returns The DOM listener callback.
*/

@@ -269,18 +233,13 @@ _createDomListener(event) {

}
// Gets an unique DOM Node identifier. The identifier will be set if not defined.
//
// @private
// @param {Node} node
// @returns {String} UID for given DOM Node.
/**
* Gets an unique DOM Node identifier. The identifier will be set if not defined.
*
* @returns UID for given DOM Node.
*/
function getNodeUID(node) {
return node['data-ck-expando'] || (node['data-ck-expando'] = uid());
}
// Gets id of the ProxyEmitter for the given node.
//
// Combines DOM Node identifier and additional options.
//
// @private
// @param {Node} node
// @param {Object} options Additional options.
// @returns {String} ProxyEmitter id.
/**
* Gets id of the ProxyEmitter for the given node.
*/
function getProxyEmitterId(node, options) {

@@ -287,0 +246,0 @@ let id = getNodeUID(node);

@@ -15,4 +15,4 @@ /**

*
* @param {Node} node DOM node.
* @returns {Array.<Node|DocumentFragment>} Array of given `node` parents.
* @param node DOM node.
* @returns Array of given `node` parents.
*/

@@ -19,0 +19,0 @@ export default function getAncestors(node) {

@@ -11,4 +11,4 @@ /**

*
* @param {HTMLElement} element An element which has CSS borders.
* @returns {module:utils/dom/getborderwidths~BorderWidths} An object containing `top`, `left`, `right` and `bottom` properties
* @param element An element which has CSS borders.
* @returns An object containing `top`, `left`, `right` and `bottom` properties
* with numerical values of the `border-[top,left,right,bottom]-width` CSS styles.

@@ -15,0 +15,0 @@ */

@@ -12,5 +12,5 @@ /**

*
* @param {Node} nodeA First node.
* @param {Node} nodeB Second node.
* @returns {Node|DocumentFragment|Document|null} Lowest common ancestor of both nodes or `null` if nodes do not have a common ancestor.
* @param nodeA First node.
* @param nodeB Second node.
* @returns Lowest common ancestor of both nodes or `null` if nodes do not have a common ancestor.
*/

@@ -17,0 +17,0 @@ export default function getCommonAncestor(nodeA, nodeB) {

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

*
* @param {HTMLElement} el The element from which the data will be retrieved.
* @returns {String} The data string.
* @param el The element from which the data will be retrieved.
* @returns The data string.
*/

@@ -16,0 +16,0 @@ export default function getDataFromElement(el) {

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

*
* @param {HTMLElement} [element] The native DOM element to be checked.
* @returns {HTMLElement|null}
* @param element The native DOM element to be checked.
*/

@@ -16,0 +15,0 @@ export default function getPositionedAncestor(element) {

@@ -5,7 +5,3 @@ /**

*/
/* globals window, document */
/**
* @module utils/dom/global
*/
/**
* A helper (module) giving an access to the global DOM objects such as `window` and

@@ -15,10 +11,12 @@ * `document`. Accessing these objects using this helper allows easy and bulletproof

*
* import global from 'ckeditor5/utils/dom/global.js';
* ```ts
* import { global } from 'ckeditor5/utils';
*
* // This stub will work for any code using global module.
* testUtils.sinon.stub( global, 'window', {
* innerWidth: 10000
* } );
* // This stub will work for any code using global module.
* testUtils.sinon.stub( global, 'window', {
* innerWidth: 10000
* } );
*
* console.log( global.window.innerWidth );
* console.log( global.window.innerWidth );
* ```
*/

@@ -25,0 +23,0 @@ let global;

@@ -11,4 +11,4 @@ /**

*
* @param {Node} node Node which index is tested.
* @returns {Number} Index of the node in the parent element. Returns 0 if node has no parent.
* @param node Node which index is tested.
* @returns Index of the node in the parent element. Returns 0 if node has no parent.
*/

@@ -15,0 +15,0 @@ export default function indexOf(node) {

@@ -11,5 +11,5 @@ /**

*
* @param {Element} parentElement Parent element.
* @param {Number} index Insertions index.
* @param {Node} nodeToInsert Node to insert.
* @param parentElement Parent element.
* @param index Insertions index.
* @param nodeToInsert Node to insert.
*/

@@ -16,0 +16,0 @@ export default function insertAt(parentElement, index, nodeToInsert) {

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

* Checks whether the object is a native DOM Comment node.
*
* @param {*} obj
* @returns {Boolean}
*/

@@ -16,0 +13,0 @@ export default function isComment(obj) {

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

* Checks if the object is a native DOM Node.
*
* @param {*} obj
* @returns {Boolean}
*/

@@ -15,0 +12,0 @@ export default function isNode(obj) {

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

* Checks if the object is a native DOM Range.
*
* @param {*} obj
* @returns {Boolean}
*/

@@ -15,0 +12,0 @@ export default function isRange(obj) {

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

* Checks if the object is a native DOM Text node.
*
* @param {*} obj
* @returns {Boolean}
*/

@@ -15,0 +12,0 @@ export default function isText(obj) {

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

* To check that, use {@link module:utils/dom/rect~Rect} instead.
*
* @param {HTMLElement|null|undefined} element
* @returns {Boolean}
*/

@@ -22,0 +19,0 @@ export default function isVisible(element) {

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

* Checks if the object is a native DOM Window.
*
* @param {*} obj
* @returns {Boolean}
*/

@@ -15,0 +12,0 @@ export default function isWindow(obj) {

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

import { isFunction } from 'lodash-es';
// @if CK_DEBUG_POSITION // import { RectDrawer } from '@ckeditor/ckeditor5-minimap/src/utils';
// @if CK_DEBUG_POSITION // const { RectDrawer } = require( '@ckeditor/ckeditor5-minimap/src/utils' );
/**

@@ -20,60 +20,61 @@ * Calculates the `position: absolute` coordinates of a given element so it can be positioned with respect to the

*
* // The element which is to be positioned.
* const element = document.body.querySelector( '#toolbar' );
* ```ts
* // The element which is to be positioned.
* const element = document.body.querySelector( '#toolbar' );
*
* // A target to which the element is positioned relatively.
* const target = document.body.querySelector( '#container' );
* // A target to which the element is positioned relatively.
* const target = document.body.querySelector( '#container' );
*
* // Finding the optimal coordinates for the positioning.
* const { left, top, name } = getOptimalPosition( {
* element: element,
* target: target,
* // Finding the optimal coordinates for the positioning.
* const { left, top, name } = getOptimalPosition( {
* element: element,
* target: target,
*
* // The algorithm will chose among these positions to meet the requirements such
* // as "limiter" element or "fitInViewport", set below. The positions are considered
* // in the order of the array.
* positions: [
* //
* // [ Target ]
* // +-----------------+
* // | Element |
* // +-----------------+
* //
* targetRect => ( {
* top: targetRect.bottom,
* left: targetRect.left,
* name: 'mySouthEastPosition'
* } ),
* // The algorithm will chose among these positions to meet the requirements such
* // as "limiter" element or "fitInViewport", set below. The positions are considered
* // in the order of the array.
* positions: [
* //
* // [ Target ]
* // +-----------------+
* // | Element |
* // +-----------------+
* //
* targetRect => ( {
* top: targetRect.bottom,
* left: targetRect.left,
* name: 'mySouthEastPosition'
* } ),
*
* //
* // +-----------------+
* // | Element |
* // +-----------------+
* // [ Target ]
* //
* ( targetRect, elementRect ) => ( {
* top: targetRect.top - elementRect.height,
* left: targetRect.left,
* name: 'myNorthEastPosition'
* } )
* ],
* //
* // +-----------------+
* // | Element |
* // +-----------------+
* // [ Target ]
* //
* ( targetRect, elementRect ) => ( {
* top: targetRect.top - elementRect.height,
* left: targetRect.left,
* name: 'myNorthEastPosition'
* } )
* ],
*
* // Find a position such guarantees the element remains within visible boundaries of <body>.
* limiter: document.body,
* // Find a position such guarantees the element remains within visible boundaries of <body>.
* limiter: document.body,
*
* // Find a position such guarantees the element remains within visible boundaries of the browser viewport.
* fitInViewport: true
* } );
* // Find a position such guarantees the element remains within visible boundaries of the browser viewport.
* fitInViewport: true
* } );
*
* // The best position which fits into document.body and the viewport. May be useful
* // to set proper class on the `element`.
* console.log( name ); // -> "myNorthEastPosition"
* // The best position which fits into document.body and the viewport. May be useful
* // to set proper class on the `element`.
* console.log( name ); // -> "myNorthEastPosition"
*
* // Using the absolute coordinates which has been found to position the element
* // as in the diagram depicting the "myNorthEastPosition" position.
* element.style.top = top;
* element.style.left = left;
* // Using the absolute coordinates which has been found to position the element
* // as in the diagram depicting the "myNorthEastPosition" position.
* element.style.top = top;
* element.style.left = left;
* ```
*
* @param {module:utils/dom/position~Options} options The input data and configuration of the helper.
* @returns {module:utils/dom/position~Position}
* @param options The input data and configuration of the helper.
*/

@@ -118,7 +119,5 @@ export function getOptimalPosition({ element, target, positions, limiter, fitInViewport, viewportOffsetConfig }) {

}
// Returns a viewport `Rect` shrunk by the viewport offset config from all sides.
//
// @private
// @param {Object} An object containing viewportOffset config.
// @returns {module:utils/dom/rect~Rect} A shrunken rect of the viewport.
/**
* Returns a viewport `Rect` shrunk by the viewport offset config from all sides.
*/
function getConstrainedViewportRect(viewportOffsetConfig) {

@@ -133,17 +132,6 @@ viewportOffsetConfig = Object.assign({ top: 0, bottom: 0, left: 0, right: 0 }, viewportOffsetConfig);

}
// For a given array of positioning functions, returns such that provides the best
// fit of the `elementRect` into the `limiterRect` and `viewportRect`.
//
// @private
//
// @param {module:utils/dom/position~Options#positions} positions Functions returning
// {@link module:utils/dom/position~Position}to be checked, in the order of preference.
// @param {Object} options
// @param {module:utils/dom/rect~Rect} options.elementRect The positioned element rect.
// @param {module:utils/dom/rect~Rect} options.targetRect The target element rect.
// @param {module:utils/dom/rect~Rect} options.viewportRect The viewport rect.
// @param {module:utils/dom/rect~Rect} [options.limiterRect] The limiter rect.
// @param {HTMLElement|null} [options.positionedElementAncestor] Nearest element ancestor element which CSS position is not "static".
//
// @returns {module:utils/dom/position~Position|null} An array containing the name of the position and it's rect.
/**
* For a given array of positioning functions, returns such that provides the best
* fit of the `elementRect` into the `limiterRect` and `viewportRect`.
*/
function getBestPosition(positions, options) {

@@ -176,13 +164,10 @@ const { elementRect } = options;

}
// For a given absolute Rect coordinates object and a positioned element ancestor, it updates its
// coordinates that make up for the position and the scroll of the ancestor.
//
// This is necessary because while Rects (and DOMRects) are relative to the browser's viewport, their coordinates
// are used in real–life to position elements with `position: absolute`, which are scoped by any positioned
// (and scrollable) ancestors.
//
// @private
//
// @param {module:utils/dom/rect~Rect} rect A rect with absolute rect coordinates.
// @param {HTMLElement} positionedElementAncestor An ancestor element that should be considered.
/**
* For a given absolute Rect coordinates object and a positioned element ancestor, it updates its
* coordinates that make up for the position and the scroll of the ancestor.
*
* This is necessary because while Rects (and DOMRects) are relative to the browser's viewport, their coordinates
* are used in real–life to position elements with `position: absolute`, which are scoped by any positioned
* (and scrollable) ancestors.
*/
function shiftRectToCompensatePositionedAncestor(rect, positionedElementAncestor) {

@@ -215,8 +200,6 @@ const ancestorPosition = getRectForAbsolutePositioning(new Rect(positionedElementAncestor));

}
// DOMRect (also Rect) works in a scroll–independent geometry but `position: absolute` doesn't.
// This function converts Rect to `position: absolute` coordinates.
//
// @private
// @param {module:utils/dom/rect~Rect} rect A rect to be converted.
// @returns {module:utils/dom/rect~Rect} Object containing `left` and `top` properties, in absolute coordinates.
/**
* DOMRect (also Rect) works in a scroll–independent geometry but `position: absolute` doesn't.
* This function converts Rect to `position: absolute` coordinates.
*/
function getRectForAbsolutePositioning(rect) {

@@ -226,20 +209,22 @@ const { scrollX, scrollY } = global.window;

}
// A position class which instances are created and used by the {@link module:utils/dom/position~getOptimalPosition} helper.
//
// {@link module:utils/dom/position~Position#top} and {@link module:utils/dom/position~Position#left} properties of the position instance
// translate directly to the `top` and `left` properties in CSS "`position: absolute` coordinate system". If set on the positioned element
// in DOM, they will make it display it in the right place in the viewport.
// @private
// @implements {Position}
/**
* A position class which instances are created and used by the {@link module:utils/dom/position~getOptimalPosition} helper.
*
* {@link module:utils/dom/position~Position#top} and {@link module:utils/dom/position~Position#left} properties of the position instance
* translate directly to the `top` and `left` properties in CSS "`position: absolute` coordinate system". If set on the positioned element
* in DOM, they will make it display it in the right place in the viewport.
*/
class PositionObject {
// Creates an instance of the {@link module:utils/dom/position~PositionObject} class.
//
// @param {module:utils/dom/position~PositioningFunction} positioningFunction function The function that defines the expected
// coordinates the positioned element should move to.
// @param {Object} [options] options object.
// @param {module:utils/dom/rect~Rect} options.elementRect The positioned element rect.
// @param {module:utils/dom/rect~Rect} options.targetRect The target element rect.
// @param {module:utils/dom/rect~Rect|null} options.viewportRect The viewport rect.
// @param {module:utils/dom/rect~Rect} [options.limiterRect] The limiter rect.
// @param {HTMLElement|null} [options.positionedElementAncestor] Nearest element ancestor element which CSS position is not "static".
/**
* Creates an instance of the {@link module:utils/dom/position~PositionObject} class.
*
* @param positioningFunction function The function that defines the expected
* coordinates the positioned element should move to.
* @param options options object.
* @param options.elementRect The positioned element rect.
* @param options.targetRect The target element rect.
* @param options.viewportRect The viewport rect.
* @param options.limiterRect The limiter rect.
* @param options.positionedElementAncestor Nearest element ancestor element which CSS position is not "static".
*/
constructor(positioningFunction, options) {

@@ -257,22 +242,19 @@ const positioningFunctionOutput = positioningFunction(options.targetRect, options.elementRect, options.viewportRect);

}
// The left value in pixels in the CSS `position: absolute` coordinate system.
// Set it on the positioned element in DOM to move it to the position.
//
// @readonly
// @type {Number}
/**
* The left value in pixels in the CSS `position: absolute` coordinate system.
* Set it on the positioned element in DOM to move it to the position.
*/
get left() {
return this._absoluteRect.left;
}
// The top value in pixels in the CSS `position: absolute` coordinate system.
// Set it on the positioned element in DOM to move it to the position.
//
// @readonly
// @type {Number}
/**
* The top value in pixels in the CSS `position: absolute` coordinate system.
* Set it on the positioned element in DOM to move it to the position.
*/
get top() {
return this._absoluteRect.top;
}
// An intersection area between positioned element and limiter within viewport constraints.
//
// @readonly
// @type {Number}
/**
* An intersection area between positioned element and limiter within viewport constraints.
*/
get limiterIntersectionArea() {

@@ -297,6 +279,5 @@ const limiterRect = this._options.limiterRect;

}
// An intersection area between positioned element and viewport.
//
// @readonly
// @type {Number}
/**
* An intersection area between positioned element and viewport.
*/
get viewportIntersectionArea() {

@@ -309,8 +290,6 @@ const viewportRect = this._options.viewportRect;

}
// An already positioned element rect. A clone of the element rect passed to the constructor
// but placed in the viewport according to the positioning function.
//
// @private
// @readonly
// @type {module:utils/dom/rect~Rect}
/**
* An already positioned element rect. A clone of the element rect passed to the constructor
* but placed in the viewport according to the positioning function.
*/
get _rect() {

@@ -323,7 +302,5 @@ if (this._cachedRect) {

}
// An already absolutely positioned element rect. See ({@link #_rect}).
//
// @private
// @readonly
// @type {module:utils/dom/rect~Rect}
/**
* An already absolutely positioned element rect. See ({@link #_rect}).
*/
get _absoluteRect() {

@@ -330,0 +307,0 @@ if (this._cachedAbsoluteRect) {

@@ -22,19 +22,21 @@ /**

*
* // Rect of an HTMLElement.
* const rectA = new Rect( document.body );
* ```ts
* // Rect of an HTMLElement.
* const rectA = new Rect( document.body );
*
* // Rect of a DOM Range.
* const rectB = new Rect( document.getSelection().getRangeAt( 0 ) );
* // Rect of a DOM Range.
* const rectB = new Rect( document.getSelection().getRangeAt( 0 ) );
*
* // Rect of a window (web browser viewport).
* const rectC = new Rect( window );
* // Rect of a window (web browser viewport).
* const rectC = new Rect( window );
*
* // Rect out of an object.
* const rectD = new Rect( { top: 0, right: 10, bottom: 10, left: 0, width: 10, height: 10 } );
* // Rect out of an object.
* const rectD = new Rect( { top: 0, right: 10, bottom: 10, left: 0, width: 10, height: 10 } );
*
* // Rect out of another Rect instance.
* const rectE = new Rect( rectD );
* // Rect out of another Rect instance.
* const rectE = new Rect( rectD );
*
* // Rect out of a ClientRect.
* const rectF = new Rect( document.body.getClientRects().item( 0 ) );
* // Rect out of a ClientRect.
* const rectF = new Rect( document.body.getClientRects().item( 0 ) );
* ```
*

@@ -45,3 +47,3 @@ * **Note**: By default a rect of an HTML element includes its CSS borders and scrollbars (if any)

*
* @param {module:utils/dom/rect~RectSource} source A source object to create the rect.
* @param source A source object to create the rect.
*/

@@ -93,3 +95,3 @@ constructor(source) {

*
* @returns {module:utils/dom/rect~Rect} A cloned rect.
* @returns A cloned rect.
*/

@@ -102,5 +104,5 @@ clone() {

*
* @param {Number} x Desired horizontal location.
* @param {Number} y Desired vertical location.
* @returns {module:utils/dom/rect~Rect} A rect which has been moved.
* @param x Desired horizontal location.
* @param y Desired vertical location.
* @returns A rect which has been moved.
*/

@@ -117,5 +119,5 @@ moveTo(x, y) {

*
* @param {Number} x A horizontal offset.
* @param {Number} y A vertical offset
* @returns {module:utils/dom/rect~Rect} A rect which has been moved.
* @param x A horizontal offset.
* @param y A vertical offset
* @returns A rect which has been moved.
*/

@@ -131,5 +133,2 @@ moveBy(x, y) {

* Returns a new rect a a result of intersection with another rect.
*
* @param {module:utils/dom/rect~Rect} anotherRect
* @returns {module:utils/dom/rect~Rect|null}
*/

@@ -157,4 +156,3 @@ getIntersection(anotherRect) {

*
* @param {module:utils/dom/rect~Rect} anotherRect
* @returns {Number} Area of intersection.
* @returns Area of intersection.
*/

@@ -172,4 +170,2 @@ getIntersectionArea(anotherRect) {

* Returns the area of the rect.
*
* @returns {Number}
*/

@@ -187,3 +183,3 @@ getArea() {

*
* @returns {module:utils/dom/rect~Rect|null} A visible rect instance or `null`, if there's none.
* @returns A visible rect instance or `null`, if there's none.
*/

@@ -220,4 +216,4 @@ getVisible() {

*
* @param {module:utils/dom/rect~Rect} anotherRect A rect instance to compare with.
* @returns {Boolean} `true` when Rects are equal. `false` otherwise.
* @param anotherRect A rect instance to compare with.
* @returns `true` when Rects are equal. `false` otherwise.
*/

@@ -235,4 +231,4 @@ isEqual(anotherRect) {

*
* @param {module:utils/dom/rect~Rect} anotherRect
* @returns {Boolean} `true` if contains, `false` otherwise.
* @param anotherRect
* @returns `true` if contains, `false` otherwise.
*/

@@ -249,3 +245,3 @@ contains(anotherRect) {

*
* @returns {module:utils/dom/rect~Rect} A rect which has been updated.
* @returns A rect which has been updated.
*/

@@ -286,4 +282,4 @@ excludeScrollbarsAndBorders() {

*
* @param {Range} range A native DOM range.
* @returns {Array.<module:utils/dom/rect~Rect>} DOM Range rects.
* @param range A native DOM range.
* @returns DOM Range rects.
*/

@@ -318,4 +314,4 @@ static getDomRangeRects(range) {

*
* @param {Iterable.<module:utils/dom/rect~Rect>} rects A list of rectangles that should be contained in the result rectangle.
* @returns {module:utils/dom/rect~Rect|null} Bounding rectangle or `null` if no `rects` were given.
* @param rects A list of rectangles that should be contained in the result rectangle.
* @returns Bounding rectangle or `null` if no `rects` were given.
*/

@@ -347,7 +343,5 @@ static getBoundingRect(rects) {

}
// Acquires all the rect properties from the passed source.
//
// @private
// @param {module:utils/dom/rect~Rect} rect
// @param {module:utils/dom/rect~RectLike} source
/**
* Acquires all the rect properties from the passed source.
*/
function copyRectProperties(rect, source) {

@@ -358,7 +352,5 @@ for (const p of rectProperties) {

}
// Checks if provided object is a <body> HTML element.
//
// @private
// @param {*} value
// @returns {Boolean}
/**
* Checks if provided object is a <body> HTML element.
*/
function isBody(value) {

@@ -370,7 +362,5 @@ if (!isDomElement(value)) {

}
// Checks if provided object "looks like" a DOM Element and has API required by `Rect` class.
//
// @private
// @param {*} value
// @returns {Boolean}
/**
* Checks if provided object "looks like" a DOM Element and has API required by `Rect` class.
*/
function isDomElement(value) {

@@ -377,0 +367,0 @@ // Note: earlier we used `isElement()` from lodash library, however that function is less performant because

@@ -11,3 +11,3 @@ /**

*
* @param {Node} node Node to remove.
* @param node Node to remove.
*/

@@ -14,0 +14,0 @@ export default function remove(node) {

@@ -12,9 +12,11 @@ /**

*
* const editableElement = editor.editing.view.getDomRoot();
* ```ts
* const editableElement = editor.editing.view.getDomRoot();
*
* const observer = new ResizeObserver( editableElement, entry => {
* console.log( 'The editable element has been resized in DOM.' );
* console.log( entry.target ); // -> editableElement
* console.log( entry.contentRect.width ); // -> e.g. '423px'
* } );
* const observer = new ResizeObserver( editableElement, entry => {
* console.log( 'The editable element has been resized in DOM.' );
* console.log( entry.target ); // -> editableElement
* console.log( entry.contentRect.width ); // -> e.g. '423px'
* } );
* ```
*

@@ -28,5 +30,5 @@ * It uses the [native DOM resize observer](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver)

*
* @param {Element} element A DOM element that is to be observed for resizing. Note that
* @param element A DOM element that is to be observed for resizing. Note that
* the element must be visible (i.e. not detached from DOM) for the observer to work.
* @param {Function} callback A function called when the observed element was resized. It passes
* @param callback A function called when the observed element was resized. It passes
* the [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry)

@@ -54,7 +56,2 @@ * object with information about the resize event.

* Registers a new resize callback for the DOM element.
*
* @private
* @static
* @param {Element} element
* @param {Function} callback
*/

@@ -75,7 +72,2 @@ static _addElementCallback(element, callback) {

* for the element, it removes the element from the native observer.
*
* @private
* @static
* @param {Element} element
* @param {Function} callback
*/

@@ -101,7 +93,2 @@ static _deleteElementCallback(element, callback) {

* Returns are registered resize callbacks for the DOM element.
*
* @private
* @static
* @param {Element} element
* @returns {Set.<Function>|null|undefined}
*/

@@ -116,5 +103,2 @@ static _getElementCallbacks(element) {

* Creates the single native observer shared across all `ResizeObserver` instances.
*
* @private
* @static
*/

@@ -136,7 +120,2 @@ static _createObserver() {

* The single native observer instance shared across all {@link module:utils/dom/resizeobserver~ResizeObserver} instances.
*
* @static
* @private
* @readonly
* @property {Object|null}
*/

@@ -147,7 +126,3 @@ ResizeObserver._observerInstance = null;

* {@link module:utils/dom/resizeobserver~ResizeObserver} instances.
*
* @static
* @private
* @property {Map.<Element,Set>|null}
*/
ResizeObserver._elementCallbacks = null;

@@ -16,5 +16,5 @@ /**

*
* @param {Object} options
* @param {HTMLElement|Range} options.target A target, which supposed to become visible to the user.
* @param {Number} [options.viewportOffset] An offset from the edge of the viewport (in pixels)
* @param options
* @param options.target A target, which supposed to become visible to the user.
* @param options.viewportOffset An offset from the edge of the viewport (in pixels)
* the `target` will be moved by when the viewport is scrolled. It enhances the user experience

@@ -80,3 +80,3 @@ * by keeping the `target` some distance from the edge of the viewport and thus making it easier to

*
* @param {HTMLElement|Range} target A target, which supposed to become visible to the user.
* @param target A target, which supposed to become visible to the user.
*/

@@ -89,43 +89,52 @@ export function scrollAncestorsToShowTarget(target) {

}
// Makes a given rect visible within its parent window.
//
// Note: Avoid the situation where the caret is still in the viewport, but totally
// at the edge of it. In such situation, if it moved beyond the viewport in the next
// action e.g. after paste, the scrolling would move it to the viewportOffset level
// and it all would look like the caret visually moved up/down:
//
// 1.
// | foo[]
// | <--- N px of space below the caret
// +---------------------------------...
//
// 2. *paste*
// 3.
// |
// |
// +-foo-----------------------------...
// bar[] <--- caret below viewport, scrolling...
//
// 4. *scrolling*
// 5.
// |
// | foo
// | bar[] <--- caret precisely at the edge
// +---------------------------------...
//
// To prevent this, this method checks the rects moved by the viewportOffset to cover
// the upper/lower edge of the viewport. It makes sure if the action repeats, there's
// no twitching – it's a purely visual improvement:
//
// 5. (after fix)
// |
// | foo
// | bar[]
// | <--- N px of space below the caret
// +---------------------------------...
//
// @private
// @param {Window} window A window which is scrolled to reveal the rect.
// @param {module:utils/dom/rect~Rect} rect A rect which is to be revealed.
// @param {Number} viewportOffset See scrollViewportToShowTarget.
/**
* Makes a given rect visible within its parent window.
*
* Note: Avoid the situation where the caret is still in the viewport, but totally
* at the edge of it. In such situation, if it moved beyond the viewport in the next
* action e.g. after paste, the scrolling would move it to the viewportOffset level
* and it all would look like the caret visually moved up/down:
*
* 1.
* ```
* | foo[]
* | <--- N px of space below the caret
* +---------------------------------...
* ```
*
* 2. *paste*
* 3.
* ```
* |
* |
* +-foo-----------------------------...
* bar[] <--- caret below viewport, scrolling...
* ```
*
* 4. *scrolling*
* 5.
* ```
* |
* | foo
* | bar[] <--- caret precisely at the edge
* +---------------------------------...
* ```
*
* To prevent this, this method checks the rects moved by the viewportOffset to cover
* the upper/lower edge of the viewport. It makes sure if the action repeats, there's
* no twitching – it's a purely visual improvement:
*
* 5. (after fix)
* ```
* |
* | foo
* | bar[]
* | <--- N px of space below the caret
* +---------------------------------...
* ```
*
* @param window A window which is scrolled to reveal the rect.
* @param rect A rect which is to be revealed.
* @param viewportOffset See scrollViewportToShowTarget.
*/
function scrollWindowToShowRect(window, rect, viewportOffset) {

@@ -155,7 +164,8 @@ const targetShiftedDownRect = rect.clone().moveBy(0, viewportOffset);

}
// Recursively scrolls element ancestors to visually reveal a rect.
//
// @private
// @param {HTMLElement} A parent The first ancestors to start scrolling.
// @param {Function} getRect A function which returns the Rect, which is to be revealed.
/**
* Recursively scrolls element ancestors to visually reveal a rect.
*
* @param parent A parent The first ancestors to start scrolling.
* @param getRect A function which returns the Rect, which is to be revealed.
*/
function scrollAncestorsToShowRect(parent, getRect) {

@@ -184,43 +194,29 @@ const parentWindow = getWindow(parent);

}
// Determines if a given `Rect` extends beyond the bottom edge of the second `Rect`.
//
// @private
// @param {module:utils/dom/rect~Rect} firstRect
// @param {module:utils/dom/rect~Rect} secondRect
// @returns {Boolean}
/**
* Determines if a given `Rect` extends beyond the bottom edge of the second `Rect`.
*/
function isBelow(firstRect, secondRect) {
return firstRect.bottom > secondRect.bottom;
}
// Determines if a given `Rect` extends beyond the top edge of the second `Rect`.
//
// @private
// @param {module:utils/dom/rect~Rect} firstRect
// @param {module:utils/dom/rect~Rect} secondRect
// @returns {Boolean}
/**
* Determines if a given `Rect` extends beyond the top edge of the second `Rect`.
*/
function isAbove(firstRect, secondRect) {
return firstRect.top < secondRect.top;
}
// Determines if a given `Rect` extends beyond the left edge of the second `Rect`.
//
// @private
// @param {module:utils/dom/rect~Rect} firstRect
// @param {module:utils/dom/rect~Rect} secondRect
// @returns {Boolean}
/**
* Determines if a given `Rect` extends beyond the left edge of the second `Rect`.
*/
function isLeftOf(firstRect, secondRect) {
return firstRect.left < secondRect.left;
}
// Determines if a given `Rect` extends beyond the right edge of the second `Rect`.
//
// @private
// @param {module:utils/dom/rect~Rect} firstRect
// @param {module:utils/dom/rect~Rect} secondRect
// @returns {Boolean}
/**
* Determines if a given `Rect` extends beyond the right edge of the second `Rect`.
*/
function isRightOf(firstRect, secondRect) {
return firstRect.right > secondRect.right;
}
// Returns the closest window of an element or range.
//
// @private
// @param {HTMLElement|Range} elementOrRange
// @returns {Window}
/**
* Returns the closest window of an element or range.
*/
function getWindow(elementOrRange) {

@@ -234,7 +230,5 @@ if (isRange(elementOrRange)) {

}
// Returns the closest parent of an element or DOM range.
//
// @private
// @param {HTMLElement|Range} elementOrRange
// @returns {HTMLelement}
/**
* Returns the closest parent of an element or DOM range.
*/
function getParentElement(elementOrRange) {

@@ -253,9 +247,9 @@ if (isRange(elementOrRange)) {

}
// Returns the rect of an element or range residing in an iframe.
// The result rect is relative to the geometry of the passed window instance.
//
// @private
// @param {HTMLElement|Range} target Element or range which rect should be returned.
// @param {Window} relativeWindow A window the rect should be relative to.
// @returns {module:utils/dom/rect~Rect}
/**
* Returns the rect of an element or range residing in an iframe.
* The result rect is relative to the geometry of the passed window instance.
*
* @param target Element or range which rect should be returned.
* @param relativeWindow A window the rect should be relative to.
*/
function getRectRelativeToWindow(target, relativeWindow) {

@@ -262,0 +256,0 @@ const targetWindow = getWindow(target);

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

*
* @param {HTMLElement} el The element in which the data will be set.
* @param {String} data The data string.
* @param el The element in which the data will be set.
* @param data The data string.
*/

@@ -16,0 +16,0 @@ export default function setDataInElement(el, data) {

@@ -12,15 +12,6 @@ /**

*
* @param {String} unit An unit like "px" or "em".
* @returns {module:utils/dom/tounit~helper}
* @param unit An unit like "px" or "em".
*/
export default function toUnit(unit) {
/**
* A function, which adds a pre–defined trailing `unit`
* to the passed `value`.
*
* @function helper
* @param {String|Number} value A value to be given the unit.
* @returns {String} A value with the trailing unit.
*/
return value => value + unit;
}

@@ -21,4 +21,4 @@ /**

*
* @param {HTMLElement} element The element to replace.
* @param {HTMLElement} [newElement] The replacement element. If not passed, then the `element` will just be hidden.
* @param element The element to replace.
* @param newElement The replacement element. If not passed, then the `element` will just be hidden.
*/

@@ -25,0 +25,0 @@ replace(element, newElement) {

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

*/
/* eslint-disable new-cap */
import EventInfo from './eventinfo';

@@ -20,14 +19,7 @@ import uid from './uid';

const _delegations = Symbol('delegations');
/**
* Mixin that injects the {@link ~Emitter events API} into its host.
*
* Read more about the concept of emitters in the:
* * {@glink framework/guides/architecture/core-editor-architecture#event-system-and-observables Event system and observables}
* section of the {@glink framework/guides/architecture/core-editor-architecture Core editor architecture} guide.
* * {@glink framework/guides/deep-dive/event-system Event system} deep dive guide.
*
* @mixin EmitterMixin
* @implements module:utils/emittermixin~Emitter
*/
const defaultEmitterClass = EmitterMixin(Object);
export default function EmitterMixin(base) {
if (!base) {
return defaultEmitterClass;
}
class Mixin extends base {

@@ -255,3 +247,2 @@ on(event, callback, options) {

}
export const Emitter = EmitterMixin(Object);
// Backward compatibility with `mix`

@@ -263,3 +254,3 @@ ([

]).forEach(key => {
EmitterMixin[key] = Emitter.prototype[key];
EmitterMixin[key] = defaultEmitterClass.prototype[key];
});

@@ -271,6 +262,4 @@ /**

* @internal
* @protected
* @param {module:utils/emittermixin~Emitter} listeningEmitter An emitter that listens.
* @param {String} listenedToEmitterId Unique emitter id of emitter listened to.
* @returns {module:utils/emittermixin~Emitter|null}
* @param listeningEmitter An emitter that listens.
* @param listenedToEmitterId Unique emitter id of emitter listened to.
*/

@@ -290,5 +279,4 @@ export function _getEmitterListenedTo(listeningEmitter, listenedToEmitterId) {

* @internal
* @protected
* @param {module:utils/emittermixin~Emitter} emitter An emitter for which id will be set.
* @param {String} [id] Unique id to set. If not passed, random unique id will be set.
* @param emitter An emitter for which id will be set.
* @param id Unique id to set. If not passed, random unique id will be set.
*/

@@ -304,5 +292,3 @@ export function _setEmitterId(emitter, id) {

* @internal
* @protected
* @param {module:utils/emittermixin~Emitter} emitter An emitter which id will be returned.
* @returns {String|undefined}
* @param emitter An emitter which id will be returned.
*/

@@ -312,5 +298,7 @@ export function _getEmitterId(emitter) {

}
// Gets the internal `_events` property of the given object.
// `_events` property store all lists with callbacks for registered event names.
// If there were no events registered on the object, empty `_events` object is created.
/**
* Gets the internal `_events` property of the given object.
* `_events` property store all lists with callbacks for registered event names.
* If there were no events registered on the object, empty `_events` object is created.
*/
function getEvents(source) {

@@ -324,3 +312,5 @@ if (!source._events) {

}
// Creates event node for generic-specific events relation architecture.
/**
* Creates event node for generic-specific events relation architecture.
*/
function makeEventNode() {

@@ -332,7 +322,9 @@ return {

}
// Creates an architecture for generic-specific events relation.
// If needed, creates all events for given eventName, i.e. if the first registered event
// is foo:bar:abc, it will create foo:bar:abc, foo:bar and foo event and tie them together.
// It also copies callbacks from more generic events to more specific events when
// specific events are created.
/**
* Creates an architecture for generic-specific events relation.
* If needed, creates all events for given eventName, i.e. if the first registered event
* is foo:bar:abc, it will create foo:bar:abc, foo:bar and foo event and tie them together.
* It also copies callbacks from more generic events to more specific events when
* specific events are created.
*/
function createEventNamespace(source, eventName) {

@@ -388,5 +380,7 @@ const events = getEvents(source);

}
// Gets an array containing callbacks list for a given event and it's more specific events.
// I.e. if given event is foo:bar and there is also foo:bar:abc event registered, this will
// return callback list of foo:bar and foo:bar:abc (but not foo).
/**
* Gets an array containing callbacks list for a given event and it's more specific events.
* I.e. if given event is foo:bar and there is also foo:bar:abc event registered, this will
* return callback list of foo:bar and foo:bar:abc (but not foo).
*/
function getCallbacksListsForNamespace(source, eventName) {

@@ -404,5 +398,7 @@ const eventNode = getEvents(source)[eventName];

}
// Get the list of callbacks for a given event, but only if there any callbacks have been registered.
// If there are no callbacks registered for given event, it checks if this is a specific event and looks
// for callbacks for it's more generic version.
/**
* Get the list of callbacks for a given event, but only if there any callbacks have been registered.
* If there are no callbacks registered for given event, it checks if this is a specific event and looks
* for callbacks for it's more generic version.
*/
function getCallbacksForEvent(source, eventName) {

@@ -424,9 +420,9 @@ let event;

}
// Fires delegated events for given map of destinations.
//
// @private
// * @param {Map.<utils.Emitter>} destinations A map containing
// `[ {@link module:utils/emittermixin~Emitter}, "event name" ]` pair destinations.
// * @param {utils.EventInfo} eventInfo The original event info object.
// * @param {Array.<*>} fireArgs Arguments the original event was fired with.
/**
* Fires delegated events for given map of destinations.
*
* @param destinations A map containing `[ {@link module:utils/emittermixin~Emitter}, "event name" ]` pair destinations.
* @param eventInfo The original event info object.
* @param fireArgs Arguments the original event was fired with.
*/
function fireDelegatedEvents(destinations, eventInfo, fireArgs) {

@@ -445,3 +441,5 @@ for (let [emitter, name] of destinations) {

}
// Helper for registering event callback on the emitter.
/**
* Helper for registering event callback on the emitter.
*/
function addEventListener(listener, emitter, event, callback, options) {

@@ -457,3 +455,5 @@ if (emitter._addEventListener) {

}
// Helper for removing event callback from the emitter.
/**
* Helper for removing event callback from the emitter.
*/
function removeEventListener(listener, emitter, event, callback) {

@@ -460,0 +460,0 @@ if (emitter._removeEventListener) {

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

* If navigator API is not available it will return an empty string.
*
* @returns {String}
*/

@@ -28,69 +26,12 @@ export function getUserAgent() {

* A namespace containing environment and browser information.
*
* @namespace
*/
const env = {
/**
* Indicates that the application is running on Macintosh.
*
* @static
* @type {Boolean}
*/
isMac: isMac(userAgent),
/**
* Indicates that the application is running on Windows.
*
* @static
* @type {Boolean}
*/
isWindows: isWindows(userAgent),
/**
* Indicates that the application is running in Firefox (Gecko).
*
* @static
* @type {Boolean}
*/
isGecko: isGecko(userAgent),
/**
* Indicates that the application is running in Safari.
*
* @static
* @type {Boolean}
*/
isSafari: isSafari(userAgent),
/**
* Indicates the the application is running in iOS.
*
* @static
* @type {Boolean}
*/
isiOS: isiOS(userAgent),
/**
* Indicates that the application is running on Android mobile device.
*
* @static
* @type {Boolean}
*/
isAndroid: isAndroid(userAgent),
/**
* Indicates that the application is running in a browser using the Blink engine.
*
* @static
* @type {Boolean}
*/
isBlink: isBlink(userAgent),
/**
* Environment features information.
*
* @memberOf module:utils/env~env
* @namespace
*/
features: {
/**
* Indicates that the environment supports ES2018 Unicode property escapes — like `\p{P}` or `\p{L}`.
* More information about unicode properties might be found
* [in Unicode Standard Annex #44](https://www.unicode.org/reports/tr44/#GC_Values_Table).
*
* @type {Boolean}
*/
isRegExpUnicodePropertySupported: isRegExpUnicodePropertySupported()

@@ -103,4 +44,4 @@ }

*
* @param {String} userAgent **Lowercase** `navigator.userAgent` string.
* @returns {Boolean} Whether User Agent is running on Macintosh or not.
* @param userAgent **Lowercase** `navigator.userAgent` string.
* @returns Whether User Agent is running on Macintosh or not.
*/

@@ -113,4 +54,4 @@ export function isMac(userAgent) {

*
* @param {String} userAgent **Lowercase** `navigator.userAgent` string.
* @returns {Boolean} Whether User Agent is running on Windows or not.
* @param userAgent **Lowercase** `navigator.userAgent` string.
* @returns Whether User Agent is running on Windows or not.
*/

@@ -123,4 +64,4 @@ export function isWindows(userAgent) {

*
* @param {String} userAgent **Lowercase** `navigator.userAgent` string.
* @returns {Boolean} Whether User Agent is Firefox or not.
* @param userAgent **Lowercase** `navigator.userAgent` string.
* @returns Whether User Agent is Firefox or not.
*/

@@ -133,4 +74,4 @@ export function isGecko(userAgent) {

*
* @param {String} userAgent **Lowercase** `navigator.userAgent` string.
* @returns {Boolean} Whether User Agent is Safari or not.
* @param userAgent **Lowercase** `navigator.userAgent` string.
* @returns Whether User Agent is Safari or not.
*/

@@ -143,4 +84,4 @@ export function isSafari(userAgent) {

*
* @param {String} userAgent **Lowercase** `navigator.userAgent` string.
* @returns {Boolean} Whether User Agent is running in iOS or not.
* @param userAgent **Lowercase** `navigator.userAgent` string.
* @returns Whether User Agent is running in iOS or not.
*/

@@ -154,4 +95,4 @@ export function isiOS(userAgent) {

*
* @param {String} userAgent **Lowercase** `navigator.userAgent` string.
* @returns {Boolean} Whether User Agent is Safari or not.
* @param userAgent **Lowercase** `navigator.userAgent` string.
* @returns Whether User Agent is Safari or not.
*/

@@ -164,4 +105,4 @@ export function isAndroid(userAgent) {

*
* @param {String} userAgent **Lowercase** `navigator.userAgent` string.
* @returns {Boolean} Whether User Agent is Blink engine or not.
* @param userAgent **Lowercase** `navigator.userAgent` string.
* @returns Whether User Agent is Blink engine or not.
*/

@@ -177,4 +118,2 @@ export function isBlink(userAgent) {

* [in Unicode Standard Annex #44](https://www.unicode.org/reports/tr44/#GC_Values_Table).
*
* @returns {Boolean}
*/

@@ -181,0 +120,0 @@ export function isRegExpUnicodePropertySupported() {

@@ -15,4 +15,4 @@ /**

/**
* @param {Object} source The emitter.
* @param {String} name The event name.
* @param source The emitter.
* @param name The event name.
*/

@@ -19,0 +19,0 @@ constructor(source, name) {

@@ -6,18 +6,23 @@ /**

/**
* @module utils/fastdiff
*/
/**
* Finds positions of the first and last change in the given string/array and generates a set of changes:
*
* fastDiff( '12a', '12xyza' );
* // [ { index: 2, type: 'insert', values: [ 'x', 'y', 'z' ] } ]
* ```ts
* fastDiff( '12a', '12xyza' );
* // [ { index: 2, type: 'insert', values: [ 'x', 'y', 'z' ] } ]
*
* fastDiff( '12a', '12aa' );
* // [ { index: 3, type: 'insert', values: [ 'a' ] } ]
* fastDiff( '12a', '12aa' );
* // [ { index: 3, type: 'insert', values: [ 'a' ] } ]
*
* fastDiff( '12xyza', '12a' );
* // [ { index: 2, type: 'delete', howMany: 3 } ]
* fastDiff( '12xyza', '12a' );
* // [ { index: 2, type: 'delete', howMany: 3 } ]
*
* fastDiff( [ '1', '2', 'a', 'a' ], [ '1', '2', 'a' ] );
* // [ { index: 3, type: 'delete', howMany: 1 } ]
* fastDiff( [ '1', '2', 'a', 'a' ], [ '1', '2', 'a' ] );
* // [ { index: 3, type: 'delete', howMany: 1 } ]
*
* fastDiff( [ '1', '2', 'a', 'b', 'c', '3' ], [ '2', 'a', 'b' ] );
* // [ { index: 0, type: 'insert', values: [ '2', 'a', 'b' ] }, { index: 3, type: 'delete', howMany: 6 } ]
* fastDiff( [ '1', '2', 'a', 'b', 'c', '3' ], [ '2', 'a', 'b' ] );
* // [ { index: 0, type: 'insert', values: [ '2', 'a', 'b' ] }, { index: 3, type: 'delete', howMany: 6 } ]
* ```
*

@@ -27,38 +32,44 @@ * Passed arrays can contain any type of data, however to compare them correctly custom comparator function

*
* fastDiff( [ { value: 1 }, { value: 2 } ], [ { value: 1 }, { value: 3 } ], ( a, b ) => {
* return a.value === b.value;
* } );
* // [ { index: 1, type: 'insert', values: [ { value: 3 } ] }, { index: 2, type: 'delete', howMany: 1 } ]
* ```ts
* fastDiff( [ { value: 1 }, { value: 2 } ], [ { value: 1 }, { value: 3 } ], ( a, b ) => {
* return a.value === b.value;
* } );
* // [ { index: 1, type: 'insert', values: [ { value: 3 } ] }, { index: 2, type: 'delete', howMany: 1 } ]
* ```
*
* The resulted set of changes can be applied to the input in order to transform it into the output, for example:
*
* let input = '12abc3';
* const output = '2ab';
* const changes = fastDiff( input, output );
* ```ts
* let input = '12abc3';
* const output = '2ab';
* const changes = fastDiff( input, output );
*
* changes.forEach( change => {
* if ( change.type == 'insert' ) {
* input = input.substring( 0, change.index ) + change.values.join( '' ) + input.substring( change.index );
* } else if ( change.type == 'delete' ) {
* input = input.substring( 0, change.index ) + input.substring( change.index + change.howMany );
* }
* } );
* changes.forEach( change => {
* if ( change.type == 'insert' ) {
* input = input.substring( 0, change.index ) + change.values.join( '' ) + input.substring( change.index );
* } else if ( change.type == 'delete' ) {
* input = input.substring( 0, change.index ) + input.substring( change.index + change.howMany );
* }
* } );
*
* // input equals output now
* // input equals output now
* ```
*
* or in case of arrays:
*
* let input = [ '1', '2', 'a', 'b', 'c', '3' ];
* const output = [ '2', 'a', 'b' ];
* const changes = fastDiff( input, output );
* ```ts
* let input = [ '1', '2', 'a', 'b', 'c', '3' ];
* const output = [ '2', 'a', 'b' ];
* const changes = fastDiff( input, output );
*
* changes.forEach( change => {
* if ( change.type == 'insert' ) {
* input = input.slice( 0, change.index ).concat( change.values, input.slice( change.index ) );
* } else if ( change.type == 'delete' ) {
* input = input.slice( 0, change.index ).concat( input.slice( change.index + change.howMany ) );
* }
* } );
* changes.forEach( change => {
* if ( change.type == 'insert' ) {
* input = input.slice( 0, change.index ).concat( change.values, input.slice( change.index ) );
* } else if ( change.type == 'delete' ) {
* input = input.slice( 0, change.index ).concat( input.slice( change.index + change.howMany ) );
* }
* } );
*
* // input equals output now
* // input equals output now
* ```
*

@@ -68,4 +79,6 @@ * By passing `true` as the fourth parameter (`atomicChanges`) the output of this function will become compatible with

*
* fastDiff( '12a', '12xyza' );
* // [ 'equal', 'equal', 'insert', 'insert', 'insert', 'equal' ]
* ```ts
* fastDiff( '12a', '12xyza', undefined, true );
* // [ 'equal', 'equal', 'insert', 'insert', 'insert', 'equal' ]
* ```
*

@@ -76,22 +89,27 @@ * The default output format of this function is compatible with the output format of

*
* const a = '1234';
* const b = '12xyz34';
* ```ts
* const a = '1234';
* const b = '12xyz34';
*
* // Both calls will return the same results (grouped changes format).
* fastDiff( a, b );
* diffToChanges( diff( a, b ) );
* // Both calls will return the same results (grouped changes format).
* fastDiff( a, b );
* diffToChanges( diff( a, b ) );
*
* // Again, both calls will return the same results (atomic changes format).
* fastDiff( a, b, null, true );
* diff( a, b );
* // Again, both calls will return the same results (atomic changes format).
* fastDiff( a, b, undefined, true );
* diff( a, b );
* ```
*
*
* @param {Array|String} a Input array or string.
* @param {Array|String} b Input array or string.
* @param {Function} [cmp] Optional function used to compare array values, by default `===` (strict equal operator) is used.
* @param {Boolean} [atomicChanges=false] Whether an array of `inset|delete|equal` operations should
* @typeParam T The type of array elements.
* @typeParam AtomicChanges The type of `atomicChanges` parameter (selects the result type).
* @param a Input array or string.
* @param b Input array or string.
* @param cmp Optional function used to compare array values, by default `===` (strict equal operator) is used.
* @param atomicChanges Whether an array of `inset|delete|equal` operations should
* be returned instead of changes set. This makes this function compatible with {@link module:utils/diff~diff `diff()`}.
* @returns {Array} Array of changes.
* Defaults to `false`.
* @returns Array of changes. The elements are either {@link module:utils/diff~DiffResult} or {@link module:utils/difftochanges~Change},
* depending on `atomicChanges` parameter.
*/
export default function fastDiff(a, b, cmp, atomicChanges = false) {
export default function fastDiff(a, b, cmp, atomicChanges) {
// Set the comparator function.

@@ -112,20 +130,19 @@ cmp = cmp || function (a, b) {

// Transform into changes array.
return atomicChanges ? changeIndexesToAtomicChanges(changeIndexes, arrayB.length) : changeIndexesToChanges(arrayB, changeIndexes);
const result = atomicChanges ?
changeIndexesToAtomicChanges(changeIndexes, arrayB.length) :
changeIndexesToChanges(arrayB, changeIndexes);
return result;
}
// Finds position of the first and last change in the given arrays. For example:
//
// const indexes = findChangeBoundaryIndexes( [ '1', '2', '3', '4' ], [ '1', '3', '4', '2', '4' ] );
// console.log( indexes ); // { firstIndex: 1, lastIndexOld: 3, lastIndexNew: 4 }
//
// The above indexes means that in the first array the modified part is `1[23]4` and in the second array it is `1[342]4`.
// Based on such indexes, array with `insert`/`delete` operations which allows transforming first value into the second one
// can be generated.
//
// @param {Array} arr1
// @param {Array} arr2
// @param {Function} cmp Comparator function.
// @returns {Object}
// @returns {Number} return.firstIndex Index of the first change in both values (always the same for both).
// @returns {Number} result.lastIndexOld Index of the last common value in `arr1`.
// @returns {Number} result.lastIndexNew Index of the last common value in `arr2`.
/**
* Finds position of the first and last change in the given arrays. For example:
*
* ```ts
* const indexes = findChangeBoundaryIndexes( [ '1', '2', '3', '4' ], [ '1', '3', '4', '2', '4' ] );
* console.log( indexes ); // { firstIndex: 1, lastIndexOld: 3, lastIndexNew: 4 }
* ```
*
* The above indexes means that in the first array the modified part is `1[23]4` and in the second array it is `1[342]4`.
* Based on such indexes, array with `insert`/`delete` operations which allows transforming first value into the second one
* can be generated.
*/
function findChangeBoundaryIndexes(arr1, arr2, cmp) {

@@ -158,8 +175,5 @@ // Find the first difference between passed values.

}
// Returns a first index on which given arrays differ. If both arrays are the same, -1 is returned.
//
// @param {Array} arr1
// @param {Array} arr2
// @param {Function} cmp Comparator function.
// @returns {Number}
/**
* Returns a first index on which given arrays differ. If both arrays are the same, -1 is returned.
*/
function findFirstDifferenceIndex(arr1, arr2, cmp) {

@@ -173,17 +187,20 @@ for (let i = 0; i < Math.max(arr1.length, arr2.length); i++) {

}
// Returns a copy of the given array with `howMany` elements removed starting from the beginning and in reversed order.
//
// @param {Array} arr Array to be processed.
// @param {Number} howMany How many elements from array beginning to remove.
// @returns {Array} Shortened and reversed array.
/**
* Returns a copy of the given array with `howMany` elements removed starting from the beginning and in reversed order.
*
* @param arr Array to be processed.
* @param howMany How many elements from array beginning to remove.
* @returns Shortened and reversed array.
*/
function cutAndReverse(arr, howMany) {
return arr.slice(howMany).reverse();
}
// Generates changes array based on change indexes from `findChangeBoundaryIndexes` function. This function will
// generate array with 0 (no changes), 1 (deletion or insertion) or 2 records (insertion and deletion).
//
// @param {Array} newArray New array for which change indexes were calculated.
// @param {Object} changeIndexes Change indexes object from `findChangeBoundaryIndexes` function.
// @returns {Array.<module:utils/difftochanges~Change>} Array of changes compatible with
// {@link module:utils/difftochanges~diffToChanges} format.
/**
* Generates changes array based on change indexes from `findChangeBoundaryIndexes` function. This function will
* generate array with 0 (no changes), 1 (deletion or insertion) or 2 records (insertion and deletion).
*
* @param newArray New array for which change indexes were calculated.
* @param changeIndexes Change indexes object from `findChangeBoundaryIndexes` function.
* @returns Array of changes compatible with {@link module:utils/difftochanges~diffToChanges} format.
*/
function changeIndexesToChanges(newArray, changeIndexes) {

@@ -211,7 +228,9 @@ const result = [];

}
// Generates array with set `equal|insert|delete` operations based on change indexes from `findChangeBoundaryIndexes` function.
//
// @param {Object} changeIndexes Change indexes object from `findChangeBoundaryIndexes` function.
// @param {Number} newLength Length of the new array on which `findChangeBoundaryIndexes` calculated change indexes.
// @returns {Array.<module:utils/diff~DiffResult>} Array of changes compatible with {@link module:utils/diff~diff} format.
/**
* Generates array with set `equal|insert|delete` operations based on change indexes from `findChangeBoundaryIndexes` function.
*
* @param changeIndexes Change indexes object from `findChangeBoundaryIndexes` function.
* @param newLength Length of the new array on which `findChangeBoundaryIndexes` calculated change indexes.
* @returns Array of changes compatible with {@link module:utils/diff~diff} format.
*/
function changeIndexesToAtomicChanges(changeIndexes, newLength) {

@@ -218,0 +237,0 @@ const { firstIndex, lastIndexOld, lastIndexNew } = changeIndexes;

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

* Returns first item of the given `iterator`.
*
* @param {Iterator.<*>} iterator
* @returns {*}
*/

@@ -15,0 +12,0 @@ export default function first(iterator) {

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

/* global setTimeout, clearTimeout */
/* eslint-disable new-cap */
/**

@@ -12,3 +11,3 @@ * @module utils/focustracker

import DomEmitterMixin from './dom/emittermixin';
import { Observable } from './observablemixin';
import ObservableMixin from './observablemixin';
import CKEditorError from './ckeditorerror';

@@ -26,18 +25,19 @@ /**

* Check out the {@glink framework/guides/deep-dive/ui/focus-tracking "Deep dive into focus tracking" guide} to learn more.
*
* @mixes module:utils/dom/emittermixin~EmitterMixin
* @mixes module:utils/observablemixin~ObservableMixin
*/
export default class FocusTracker extends DomEmitterMixin(Observable) {
export default class FocusTracker extends DomEmitterMixin(ObservableMixin()) {
constructor() {
super();
/**
* List of registered elements.
*/
this._elements = new Set();
/**
* Event loop timeout.
*/
this._nextEventLoopTimeout = null;
this.set('isFocused', false);
this.set('focusedElement', null);
this._elements = new Set();
this._nextEventLoopTimeout = null;
}
/**
* Starts tracking the specified element.
*
* @param {Element} element
*/

@@ -59,4 +59,2 @@ add(element) {

* Stops tracking the specified element and stops listening on this element.
*
* @param {Element} element
*/

@@ -82,5 +80,2 @@ remove(element) {

* Stores currently focused element and set {#isFocused} as `true`.
*
* @private
* @param {Element} element Element which has been focused.
*/

@@ -95,5 +90,2 @@ _focus(element) {

* This method uses `setTimeout` to change order of fires `blur` and `focus` events.
*
* @private
* @fires blur
*/

@@ -100,0 +92,0 @@ _blur() {

@@ -10,11 +10,19 @@ /**

export { default as diff } from './diff';
export { default as fastDiff } from './fastdiff';
export { default as mix } from './mix';
export { default as EmitterMixin } from './emittermixin';
export { default as EventInfo } from './eventinfo';
export { default as ObservableMixin } from './observablemixin';
export { default as CKEditorError, logError, logWarning } from './ckeditorerror';
export { default as ElementReplacer } from './elementreplacer';
export { default as count } from './count';
export { default as compareArrays } from './comparearrays';
export { default as createElement } from './dom/createelement';
export { default as Config } from './config';
export { default as isIterable } from './isiterable';
export { default as DomEmitterMixin } from './dom/emittermixin';
export { default as global } from './dom/global';
export { default as getAncestors } from './dom/getancestors';
export { default as getDataFromElement } from './dom/getdatafromelement';
export { default as isText } from './dom/istext';
export { default as Rect } from './dom/rect';

@@ -24,3 +32,10 @@ export { default as ResizeObserver } from './dom/resizeobserver';

export { default as toUnit } from './dom/tounit';
export { default as indexOf } from './dom/indexof';
export { default as insertAt } from './dom/insertat';
export { default as isComment } from './dom/iscomment';
export { default as isNode } from './dom/isnode';
export { default as isRange } from './dom/isrange';
export { default as isVisible } from './dom/isvisible';
export { getOptimalPosition } from './dom/position';
export { default as remove } from './dom/remove';
export * from './dom/scroll';

@@ -38,3 +53,5 @@ export * from './keyboard';

export { default as insertToPriorityArray } from './inserttopriorityarray';
export { default as spliceArray } from './splicearray';
export { default as uid } from './uid';
export * from './unicode';
export { default as version } from './version';

@@ -9,4 +9,4 @@ /**

*
* @param {Array.<module:utils/inserttopriorityarray~ObjectWithPriority>} objects Array of objects with priority to insert object to.
* @param {module:utils/inserttopriorityarray~ObjectWithPriority} objectToInsert Object with `priority` property.
* @param objects Array of objects with priority to insert object to.
* @param objectToInsert Object with `priority` property.
*/

@@ -13,0 +13,0 @@ export default function insertToPriorityArray(objects, objectToInsert) {

@@ -11,4 +11,4 @@ /**

*
* @param {*} value The value to check.
* @returns {Boolean} True if value implements iterator interface.
* @param value The value to check.
* @returns True if value implements iterator interface.
*/

@@ -15,0 +15,0 @@ export default function isIterable(value) {

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

*
* @param {String|module:utils/keyboard~KeystrokeInfo} A key name (see {@link module:utils/keyboard~keyCodes})
* or a keystroke data object.
* @returns {Number} Key or keystroke code.
* @param key A key name (see {@link module:utils/keyboard~keyCodes}) or a keystroke data object.
* @returns Key or keystroke code.
*/

@@ -85,4 +84,4 @@ export function getCode(key) {

*
* @param {String|Array.<Number|String>} keystroke The keystroke definition.
* @returns {Number} Keystroke code.
* @param keystroke The keystroke definition.
* @returns Keystroke code.
*/

@@ -101,4 +100,4 @@ export function parseKeystroke(keystroke) {

*
* @param {String} keystroke The keystroke text.
* @returns {String} The keystroke text specific for the environment.
* @param keystroke The keystroke text.
* @returns The keystroke text specific for the environment.
*/

@@ -121,4 +120,3 @@ export function getEnvKeystrokeText(keystroke) {

*
* @param {Number} keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.
* @returns {Boolean}
* @param keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.
*/

@@ -138,6 +136,6 @@ export function isArrowKeyCode(keyCode) {

*
* @param {Number} keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.
* @param {module:utils/language~LanguageDirection} contentLanguageDirection The content language direction, corresponding to
* @param keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.
* @param contentLanguageDirection The content language direction, corresponding to
* {@link module:utils/locale~Locale#contentLanguageDirection}.
* @returns {module:utils/keyboard~ArrowKeyCodeDirection|undefined} Localized arrow direction or `undefined` for non-arrow key codes.
* @returns Localized arrow direction or `undefined` for non-arrow key codes.
*/

@@ -157,8 +155,10 @@ export function getLocalizedArrowKeyCodeDirection(keyCode, contentLanguageDirection) {

}
// Converts a key name to the key code with mapping based on the env.
//
// See: {@link module:utils/keyboard~getCode}.
//
// @param {String} key The key name (see {@link module:utils/keyboard~keyCodes}).
// @returns {Number} Key code.
/**
* Converts a key name to the key code with mapping based on the env.
*
* See: {@link module:utils/keyboard~getCode}.
*
* @param key The key name (see {@link module:utils/keyboard~keyCodes}).
* @returns Key code.
*/
function getEnvKeyCode(key) {

@@ -179,6 +179,5 @@ // Don't remap modifier key for forced modifiers.

*
* @param {Number} keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.
* @param {module:utils/language~LanguageDirection} contentLanguageDirection The content language direction, corresponding to
* @param keyCode A key code as in {@link module:utils/keyboard~KeystrokeInfo#keyCode}.
* @param contentLanguageDirection The content language direction, corresponding to
* {@link module:utils/locale~Locale#contentLanguageDirection}.
* @returns {Boolean}
*/

@@ -185,0 +184,0 @@ export function isForwardArrowKeyCode(keyCode, contentLanguageDirection) {

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

*/
import { Emitter as DomEmitter } from './dom/emittermixin';
import DomEmitterMixin from './dom/emittermixin';
import { getCode, parseKeystroke } from './keyboard';

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

*
* editor.keystrokes.set( 'Ctrl+A', ( keyEvtData, cancel ) => {
* console.log( 'Ctrl+A has been pressed' );
* cancel();
* } );
* ```ts
* editor.keystrokes.set( 'Ctrl+A', ( keyEvtData, cancel ) => {
* console.log( 'Ctrl+A has been pressed' );
* cancel();
* } );
* ```
*

@@ -26,15 +28,17 @@ * However, this utility class can be used in various part of the UI. For instance, a certain {@link module:ui/view~View}

*
* class MyView extends View {
* constructor() {
* this.keystrokes = new KeystrokeHandler();
* ```ts
* class MyView extends View {
* constructor() {
* this.keystrokes = new KeystrokeHandler();
*
* this.keystrokes.set( 'tab', handleTabKey );
* }
* this.keystrokes.set( 'tab', handleTabKey );
* }
*
* render() {
* super.render();
* render() {
* super.render();
*
* this.keystrokes.listenTo( this.element );
* }
* }
* this.keystrokes.listenTo( this.element );
* }
* }
* ```
*

@@ -49,8 +53,6 @@ * That keystroke handler will listen to `keydown` events fired in this view's main element.

constructor() {
this._listener = new DomEmitter();
this._listener = new (DomEmitterMixin())();
}
/**
* Starts listening for `keydown` events from a given emitter.
*
* @param {module:utils/emittermixin~Emitter|HTMLElement|Window} emitter
*/

@@ -74,9 +76,9 @@ listenTo(emitter) {

*
* @param {String|Array.<String|Number>} keystroke Keystroke defined in a format accepted by
* @param keystroke Keystroke defined in a format accepted by
* the {@link module:utils/keyboard~parseKeystroke} function.
* @param {Function} callback A function called with the
* @param callback A function called with the
* {@link module:engine/view/observer/keyobserver~KeyEventData key event data} object and
* a helper function to call both `preventDefault()` and `stopPropagation()` on the underlying event.
* @param {Object} [options={}] Additional options.
* @param {module:utils/priorities~PriorityString} [options.priority='normal'] The priority of the keystroke
* @param options Additional options.
* @param options.priority The priority of the keystroke
* callback. The higher the priority value the sooner the callback will be executed. Keystrokes having the same priority

@@ -107,4 +109,4 @@ * are called in the order they were added.

*
* @param {module:engine/view/observer/keyobserver~KeyEventData} keyEvtData Key event data.
* @returns {Boolean} Whether the keystroke was handled.
* @param keyEvtData Key event data.
* @returns Whether the keystroke was handled.
*/

@@ -111,0 +113,0 @@ press(keyEvtData) {

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

*
* @param {String} languageCode The ISO 639-1 or ISO 639-2 language code.
* @returns {module:utils/language~LanguageDirection}
* @param languageCode The ISO 639-1 or ISO 639-2 language code.
*/

@@ -19,0 +18,0 @@ export function getLanguageDirection(languageCode) {

@@ -20,12 +20,12 @@ /**

*
* @param {Object} [options] Locale configuration.
* @param {String} [options.uiLanguage='en'] The editor UI language code in the
* @param options Locale configuration.
* @param options.uiLanguage The editor UI language code in the
* [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. See {@link #uiLanguage}.
* @param {String} [options.contentLanguage] The editor content language code in the
* @param options.contentLanguage The editor content language code in the
* [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) format. If not specified, the same as `options.language`.
* See {@link #contentLanguage}.
*/
constructor(options = {}) {
this.uiLanguage = options.uiLanguage || 'en';
this.contentLanguage = options.contentLanguage || this.uiLanguage;
constructor({ uiLanguage = 'en', contentLanguage } = {}) {
this.uiLanguage = uiLanguage;
this.contentLanguage = contentLanguage || this.uiLanguage;
this.uiLanguageDirection = getLanguageDirection(this.uiLanguage);

@@ -42,3 +42,2 @@ this.contentLanguageDirection = getLanguageDirection(this.contentLanguage);

* @deprecated
* @member {String}
*/

@@ -48,3 +47,4 @@ get language() {

* The {@link module:utils/locale~Locale#language `Locale#language`} property was deprecated and will
* be removed in the near future. Please use the {@link #uiLanguage} and {@link #contentLanguage} properties instead.
* be removed in the near future. Please use the {@link module:utils/locale~Locale#uiLanguage `Locale#uiLanguage`} and
* {@link module:utils/locale~Locale#contentLanguage `Locale#contentLanguage`} properties instead.
*

@@ -60,7 +60,2 @@ * @error locale-deprecated-language-property

* An unbound version of the {@link #t} method.
*
* @private
* @param {String|module:utils/translation-service~Message} message
* @param {Number|String|Array.<Number|String>} [values]
* @returns {String}
*/

@@ -78,3 +73,5 @@ _t(message, values = []) {

}
// Fills the `%0, %1, ...` string placeholders with values.
/**
* Fills the `%0, %1, ...` string placeholders with values.
*/
function interpolateString(string, values) {

@@ -81,0 +78,0 @@ return string.replace(/%(\d+)/g, (match, index) => {

@@ -11,5 +11,5 @@ /**

*
* @param {Map} mapA The first map to compare.
* @param {Map} mapB The second map to compare.
* @returns {Boolean} `true` if given maps are equal, `false` otherwise.
* @param mapA The first map to compare.
* @param mapB The second map to compare.
* @returns `true` if given maps are equal, `false` otherwise.
*/

@@ -16,0 +16,0 @@ export default function mapsEqual(mapA, mapB) {

@@ -12,21 +12,23 @@ /**

*
* class Editor {
* ...
* }
* ```
* class Editor {
* ...
* }
*
* const SomeMixin = {
* a() {
* return 'a';
* }
* };
* const SomeMixin = {
* a() {
* return 'a';
* }
* };
*
* mix( Editor, SomeMixin, ... );
* mix( Editor, SomeMixin, ... );
*
* new Editor().a(); // -> 'a'
* new Editor().a(); // -> 'a'
* ```
*
* Note: Properties which already exist in the base class will not be overriden.
*
* @depreciated Use mixin pattern, see: https://www.typescriptlang.org/docs/handbook/mixins.html.
* @param {Function} [baseClass] Class which prototype will be extended.
* @param {Object} [...mixins] Objects from which to get properties.
* @deprecated Use mixin pattern, see: https://www.typescriptlang.org/docs/handbook/mixins.html.
* @param baseClass Class which prototype will be extended.
* @param mixins Objects from which to get properties.
*/

@@ -33,0 +35,0 @@ export default function mix(baseClass, ...mixins) {

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

* guide to learn differences between these interfaces.
*
* @param {Number} index
* @param {Iterable.<*>} iterable
* @returns {*}
*/

@@ -21,0 +17,0 @@ export default function nth(index, iterable) {

@@ -11,9 +11,11 @@ /**

*
* const map = objectToMap( { 'foo': 1, 'bar': 2 } );
* map.get( 'foo' ); // 1
* ```ts
* const map = objectToMap( { 'foo': 1, 'bar': 2 } );
* map.get( 'foo' ); // 1
* ```
*
* **Note**: For mixed data (`Object` or `Iterable`) there's a dedicated {@link module:utils/tomap~toMap} function.
*
* @param {Object|null} obj Object to transform.
* @returns {Map} Map created from object.
* @param obj Object to transform.
* @returns Map created from object.
*/

@@ -20,0 +22,0 @@ export default function objectToMap(obj) {

@@ -5,7 +5,7 @@ /**

*/
/* eslint-disable @typescript-eslint/unified-signatures, new-cap */
/* eslint-disable @typescript-eslint/unified-signatures */
/**
* @module utils/observablemixin
*/
import { Emitter } from './emittermixin';
import EmitterMixin from './emittermixin';
import CKEditorError from './ckeditorerror';

@@ -18,16 +18,7 @@ import { isObject } from 'lodash-es';

const decoratedOriginal = Symbol('decoratedOriginal');
/**
* A mixin that injects the "observable properties" and data binding functionality described in the
* {@link ~Observable} interface.
*
* Read more about the concept of observables in the:
* * {@glink framework/guides/architecture/core-editor-architecture#event-system-and-observables Event system and observables}
* section of the {@glink framework/guides/architecture/core-editor-architecture Core editor architecture} guide,
* * {@glink framework/guides/deep-dive/observables Observables deep dive} guide.
*
* @mixin ObservableMixin
* @mixes module:utils/emittermixin~EmitterMixin
* @implements module:utils/observablemixin~Observable
*/
const defaultObservableClass = ObservableMixin(EmitterMixin());
export default function ObservableMixin(base) {
if (!base) {
return defaultObservableClass;
}
class Mixin extends base {

@@ -48,11 +39,13 @@ set(name, value) {

*
* This error is thrown when trying to {@link ~Observable#set set} a property with
* This error is thrown when trying to {@link module:utils/observablemixin~Observable#set set} a property with
* a name of an already existing property. For example:
*
* let observable = new Model();
* observable.property = 1;
* observable.set( 'property', 2 ); // throws
* ```ts
* let observable = new Model();
* observable.property = 1;
* observable.set( 'property', 2 ); // throws
*
* observable.set( 'property', 1 );
* observable.set( 'property', 2 ); // ok, because this is an existing property.
* observable.set( 'property', 1 );
* observable.set( 'property', 2 ); // ok, because this is an existing property.
* ```
*

@@ -118,6 +111,2 @@ * @error observable-set-cannot-override

const bindings = new Map();
// @typedef {Object} Binding
// @property {Array} property Property which is bound.
// @property {Array} to Array of observable–property components of the binding (`{ observable: ..., property: .. }`).
// @property {Array} callback A function which processes `to` components.
bindProperties.forEach(a => {

@@ -128,11 +117,2 @@ const binding = { property: a, to: [] };

});
// @typedef {Object} BindChain
// @property {Function} to See {@link ~ObservableMixin#_bindTo}.
// @property {Function} toMany See {@link ~ObservableMixin#_bindToMany}.
// @property {module:utils/observablemixin~Observable} _observable The observable which initializes the binding.
// @property {Array} _bindProperties Array of `_observable` properties to be bound.
// @property {Array} _to Array of `to()` observable–properties (`{ observable: toObservable, properties: ...toProperties }`).
// @property {Map} _bindings Stores bindings to be kept in
// {@link ~ObservableMixin#_boundProperties}/{@link ~ObservableMixin#_boundObservables}
// initiated in this binding chain.
return {

@@ -230,3 +210,3 @@ to: bindTo,

}
Emitter.prototype.stopListening.call(this, emitter, event, callback);
super.stopListening(emitter, event, callback);
}

@@ -236,3 +216,2 @@ }

}
export const Observable = ObservableMixin(Emitter);
// Backward compatibility with `mix`

@@ -245,8 +224,5 @@ ([

]).forEach(key => {
ObservableMixin[key] = Observable.prototype[key];
ObservableMixin[key] = defaultObservableClass.prototype[key];
});
// Init symbol properties needed for the observable mechanism to work.
//
// @private
// @param {module:utils/observablemixin~ObservableMixin} observable
function initObservable(observable) {

@@ -258,5 +234,2 @@ // Do nothing if already inited.

// The internal hash containing the observable's state.
//
// @private
// @type {Map}
Object.defineProperty(observable, observablePropertiesSymbol, {

@@ -266,5 +239,5 @@ value: new Map()

// Map containing bindings to external observables. It shares the binding objects
// (`{ observable: A, property: 'a', to: ... }`) with {@link module:utils/observablemixin~ObservableMixin#_boundProperties} and
// (`{ observable: A, property: 'a', to: ... }`) with {@link module:utils/observablemixin~Observable#_boundProperties} and
// it is used to observe external observables to update own properties accordingly.
// See {@link module:utils/observablemixin~ObservableMixin#bind}.
// See {@link module:utils/observablemixin~Observable#bind}.
//

@@ -309,4 +282,2 @@ // A.bind( 'a', 'b', 'c' ).to( B, 'x', 'y', 'x' );

//
// @private
// @type {Map}
Object.defineProperty(observable, boundObservablesSymbol, {

@@ -317,7 +288,7 @@ value: new Map()

// the binding objects (`{ observable: A, property: 'a', to: ... }`) with
// {@link module:utils/observablemixin~ObservableMixin#_boundObservables}. This data structure is
// a reverse of {@link module:utils/observablemixin~ObservableMixin#_boundObservables} and it is helpful for
// {@link module:utils/observablemixin~ObservableMixin#unbind}.
// {@link module:utils/observablemixin~Observable#_boundObservables}. This data structure is
// a reverse of {@link module:utils/observablemixin~Observable#_boundObservables} and it is helpful for
// {@link module:utils/observablemixin~Observable#unbind}.
//
// See {@link module:utils/observablemixin~ObservableMixin#bind}.
// See {@link module:utils/observablemixin~Observable#bind}.
//

@@ -342,5 +313,2 @@ // A.bind( 'a', 'b', 'c' ).to( B, 'x', 'y', 'x' );

// } )
//
// @private
// @type {Map}
Object.defineProperty(observable, boundPropertiesSymbol, {

@@ -350,6 +318,7 @@ value: new Map()

}
// A chaining for {@link module:utils/observablemixin~ObservableMixin#bind} providing `.to()` interface.
//
// @private
// @param {...[Observable|String|Function]} args Arguments of the `.to( args )` binding.
/**
* A chaining for {@link module:utils/observablemixin~Observable#bind} providing `.to()` interface.
*
* @param args Arguments of the `.to( args )` binding.
*/
function bindTo(...args) {

@@ -406,8 +375,5 @@ const parsedArgs = parseBindToArgs(...args);

}
// Binds to an attribute in a set of iterable observables.
//
// @private
// @param {Array.<Observable>} observables
// @param {String} attribute
// @param {Function} callback
/**
* Binds to an attribute in a set of iterable observables.
*/
function bindToMany(observables, attribute, callback) {

@@ -428,8 +394,6 @@ if (this._bindings.size > 1) {

}
// Returns an array of binding components for
// {@link Observable#bind} from a set of iterable observables.
//
// @param {Array.<Observable>} observables
// @param {String} attribute
// @returns {Array.<String|Observable>}
/**
* Returns an array of binding components for
* {@link Observable#bind} from a set of iterable observables.
*/
function getBindingTargets(observables, attribute) {

@@ -440,28 +404,29 @@ const observableAndAttributePairs = observables.map(observable => [observable, attribute]);

}
// Check if all entries of the array are of `String` type.
//
// @private
// @param {Array} arr An array to be checked.
// @returns {Boolean}
/**
* Check if all entries of the array are of `String` type.
*/
function isStringArray(arr) {
return arr.every(a => typeof a == 'string');
}
// Parses and validates {@link Observable#bind}`.to( args )` arguments and returns
// an object with a parsed structure. For example
//
// A.bind( 'x' ).to( B, 'a', C, 'b', call );
//
// becomes
//
// {
// to: [
// { observable: B, properties: [ 'a' ] },
// { observable: C, properties: [ 'b' ] },
// ],
// callback: call
// }
//
// @private
// @param {...*} args Arguments of {@link Observable#bind}`.to( args )`.
// @returns {Object}
/**
* Parses and validates {@link Observable#bind}`.to( args )` arguments and returns
* an object with a parsed structure. For example
*
* ```ts
* A.bind( 'x' ).to( B, 'a', C, 'b', call );
* ```
*
* becomes
*
* ```ts
* {
* to: [
* { observable: B, properties: [ 'a' ] },
* { observable: C, properties: [ 'b' ] },
* ],
* callback: call
* }
*
* @param args Arguments of {@link Observable#bind}`.to( args )`.
*/
function parseBindToArgs(...args) {

@@ -496,8 +461,9 @@ // Eliminate A.bind( 'x' ).to()

}
// Synchronizes {@link module:utils/observablemixin#_boundObservables} with {@link Binding}.
//
// @private
// @param {Binding} binding A binding to store in {@link Observable#_boundObservables}.
// @param {Observable} toObservable A observable, which is a new component of `binding`.
// @param {String} toPropertyName A name of `toObservable`'s property, a new component of the `binding`.
/**
* Synchronizes {@link module:utils/observable#_boundObservables} with {@link Binding}.
*
* @param binding A binding to store in {@link Observable#_boundObservables}.
* @param toObservable A observable, which is a new component of `binding`.
* @param toPropertyName A name of `toObservable`'s property, a new component of the `binding`.
*/
function updateBoundObservables(observable, binding, toObservable, toPropertyName) {

@@ -516,40 +482,49 @@ const boundObservables = observable[boundObservablesSymbol];

}
// Synchronizes {@link Observable#_boundProperties} and {@link Observable#_boundObservables}
// with {@link BindChain}.
//
// Assuming the following binding being created
//
// A.bind( 'a', 'b' ).to( B, 'x', 'y' );
//
// the following bindings were initialized by {@link Observable#bind} in {@link BindChain#_bindings}:
//
// {
// a: { observable: A, property: 'a', to: [] },
// b: { observable: A, property: 'b', to: [] },
// }
//
// Iterate over all bindings in this chain and fill their `to` properties with
// corresponding to( ... ) arguments (components of the binding), so
//
// {
// a: { observable: A, property: 'a', to: [ B, 'x' ] },
// b: { observable: A, property: 'b', to: [ B, 'y' ] },
// }
//
// Then update the structure of {@link Observable#_boundObservables} with updated
// binding, so it becomes:
//
// Map( {
// B: {
// x: Set( [
// { observable: A, property: 'a', to: [ [ B, 'x' ] ] }
// ] ),
// y: Set( [
// { observable: A, property: 'b', to: [ [ B, 'y' ] ] },
// ] )
// }
// } )
//
// @private
// @param {BindChain} chain The binding initialized by {@link Observable#bind}.
/**
* Synchronizes {@link Observable#_boundProperties} and {@link Observable#_boundObservables}
* with {@link BindChain}.
*
* Assuming the following binding being created
*
* ```ts
* A.bind( 'a', 'b' ).to( B, 'x', 'y' );
* ```
*
* the following bindings were initialized by {@link Observable#bind} in {@link BindChain#_bindings}:
*
* ```ts
* {
* a: { observable: A, property: 'a', to: [] },
* b: { observable: A, property: 'b', to: [] },
* }
* ```
*
* Iterate over all bindings in this chain and fill their `to` properties with
* corresponding to( ... ) arguments (components of the binding), so
*
* ```ts
* {
* a: { observable: A, property: 'a', to: [ B, 'x' ] },
* b: { observable: A, property: 'b', to: [ B, 'y' ] },
* }
* ```
*
* Then update the structure of {@link Observable#_boundObservables} with updated
* binding, so it becomes:
*
* ```ts
* Map( {
* B: {
* x: Set( [
* { observable: A, property: 'a', to: [ [ B, 'x' ] ] }
* ] ),
* y: Set( [
* { observable: A, property: 'b', to: [ [ B, 'y' ] ] },
* ] )
* }
* } )
* ```
*
* @param chain The binding initialized by {@link Observable#bind}.
*/
function updateBindToBound(chain) {

@@ -568,8 +543,9 @@ let toProperty;

}
// Updates an property of a {@link Observable} with a value
// determined by an entry in {@link Observable#_boundProperties}.
//
// @private
// @param {Observable} observable A observable which property is to be updated.
// @param {String} propertyName An property to be updated.
/**
* Updates an property of a {@link Observable} with a value
* determined by an entry in {@link Observable#_boundProperties}.
*
* @param observable A observable which property is to be updated.
* @param propertyName An property to be updated.
*/
function updateBoundObservableProperty(observable, propertyName) {

@@ -598,9 +574,9 @@ const boundProperties = observable[boundPropertiesSymbol];

}
// Starts listening to changes in {@link BindChain._to} observables to update
// {@link BindChain._observable} {@link BindChain._bindProperties}. Also sets the
// initial state of {@link BindChain._observable}.
//
// @private
// @param {Observable} observable
// @param {BindChain} chain The chain initialized by {@link Observable#bind}.
/**
* Starts listening to changes in {@link BindChain._to} observables to update
* {@link BindChain._observable} {@link BindChain._bindProperties}. Also sets the
* initial state of {@link BindChain._observable}.
*
* @param chain The chain initialized by {@link Observable#bind}.
*/
function attachBindToListeners(observable, toBindings) {

@@ -607,0 +583,0 @@ toBindings.forEach(to => {

@@ -7,13 +7,4 @@ /**

* Provides group of constants to use instead of hardcoding numeric priority values.
*
* @namespace
*/
const priorities = {
/**
* Converts a string with priority name to it's numeric value. If `Number` is given, it just returns it.
*
* @static
* @param {module:utils/priorities~PriorityString} [priority] Priority to convert.
* @returns {Number} Converted priority.
*/
get(priority = 'normal') {

@@ -20,0 +11,0 @@ if (typeof priority != 'number') {

@@ -15,15 +15,16 @@ /**

*
* spliceArray( [ 1, 2 ], [ 3, 4 ], 0, 0 ); // [ 3, 4, 1, 2 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 1 ); // [ 1, 3, 4 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 0 ); // [ 1, 3, 4, 2 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 2, 0 ); // [ 1, 2, 3, 4 ]
* spliceArray( [ 1, 2 ], [], 0, 1 ); // [ 2 ]
* ```ts
* spliceArray( [ 1, 2 ], [ 3, 4 ], 0, 0 ); // [ 3, 4, 1, 2 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 1 ); // [ 1, 3, 4 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 0 ); // [ 1, 3, 4, 2 ]
* spliceArray( [ 1, 2 ], [ 3, 4 ], 2, 0 ); // [ 1, 2, 3, 4 ]
* spliceArray( [ 1, 2 ], [], 0, 1 ); // [ 2 ]
* ```
*
* @private
* @param {Array} target Array to be spliced.
* @param {Array} source Array of elements to be inserted to target.
* @param {Number} start Index at which nodes should be inserted/removed.
* @param {Number} count Number of items.
* @param target Array to be spliced.
* @param source Array of elements to be inserted to target.
* @param start Index at which nodes should be inserted/removed.
* @param count Number of items.
*
* @returns {Array} New spliced array.
* @returns New spliced array.
*/

@@ -30,0 +31,0 @@ export default function spliceArray(target, source, start, count) {

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

*
* @returns {Function} The spy function.
* @returns The spy function.
*/

@@ -18,0 +18,0 @@ function spy() {

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

*
* map = toMap( { 'foo': 1, 'bar': 2 } );
* map = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
* map = toMap( anotherMap );
* ```ts
* map = toMap( { 'foo': 1, 'bar': 2 } );
* map = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
* map = toMap( anotherMap );
* ```
*
* @param {Object|Iterable|null} data Object or iterable to transform.
* @returns {Map} Map created from data.
* @param data Object or iterable to transform.
* @returns Map created from data.
*/

@@ -21,0 +23,0 @@ export default function toMap(data) {

@@ -25,12 +25,16 @@ /**

*
* add( 'pl', {
* 'Cancel': 'Anuluj',
* 'IMAGE': 'obraz', // Note that the `IMAGE` comes from the message ID, while the string can be `image`.
* } );
* ```ts
* add( 'pl', {
* 'Cancel': 'Anuluj',
* 'IMAGE': 'obraz', // Note that the `IMAGE` comes from the message ID, while the string can be `image`.
* } );
* ```
*
* If the message is supposed to support various plural forms, make sure to provide an array with the singular form and all plural forms:
*
* add( 'pl', {
* 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
* } );
* ```ts
* add( 'pl', {
* 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
* } );
* ```
*

@@ -42,22 +46,26 @@ * You should also specify the third argument (the `getPluralForm()` function) that will be used to determine the plural form if no

*
* add( 'en', {
* // ... Translations.
* }, n => n !== 1 );
* add( 'pl', {
* // ... Translations.
* }, n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
* ```ts
* add( 'en', {
* // ... Translations.
* }, n => n !== 1 );
* add( 'pl', {
* // ... Translations.
* }, n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
* ```
*
* All translations extend the global `window.CKEDITOR_TRANSLATIONS` object. An example of this object can be found below:
*
* {
* pl: {
* dictionary: {
* 'Cancel': 'Anuluj',
* 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
* },
* // A function that returns the plural form index.
* getPluralForm: n => n !==1
* }
* // Other languages.
* }
* ```ts
* {
* pl: {
* dictionary: {
* 'Cancel': 'Anuluj',
* 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
* },
* // A function that returns the plural form index.
* getPluralForm: n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
* }
* // Other languages.
* }
* ```
*

@@ -68,25 +76,27 @@ * If you cannot import this function from this module (e.g. because you use a CKEditor 5 build), you can

*
* function addTranslations( language, translations, getPluralForm ) {
* if ( !global.window.CKEDITOR_TRANSLATIONS ) {
* global.window.CKEDITOR_TRANSLATIONS = {};
* }
* ```ts
* function addTranslations( language, translations, getPluralForm ) {
* if ( !global.window.CKEDITOR_TRANSLATIONS ) {
* global.window.CKEDITOR_TRANSLATIONS = {};
* }
* if ( !global.window.CKEDITOR_TRANSLATIONS[ language ] ) {
* global.window.CKEDITOR_TRANSLATIONS[ language ] = {};
* }
* if ( !global.window.CKEDITOR_TRANSLATIONS[ language ] ) {
* global.window.CKEDITOR_TRANSLATIONS[ language ] = {};
* }
*
* const languageTranslations = global.window.CKEDITOR_TRANSLATIONS[ language ];
* const languageTranslations = global.window.CKEDITOR_TRANSLATIONS[ language ];
*
* languageTranslations.dictionary = languageTranslations.dictionary || {};
* languageTranslations.getPluralForm = getPluralForm || languageTranslations.getPluralForm;
* languageTranslations.dictionary = languageTranslations.dictionary || {};
* languageTranslations.getPluralForm = getPluralForm || languageTranslations.getPluralForm;
*
* // Extend the dictionary for the given language.
* Object.assign( languageTranslations.dictionary, translations );
* }
* // Extend the dictionary for the given language.
* Object.assign( languageTranslations.dictionary, translations );
* }
* ```
*
* @param {String} language Target language.
* @param {Object.<String,*>} translations An object with translations which will be added to the dictionary.
* @param language Target language.
* @param translations An object with translations which will be added to the dictionary.
* For each message ID the value should be either a translation or an array of translations if the message
* should support plural forms.
* @param {Function} [getPluralForm] A function that returns the plural form index (a number).
* @param getPluralForm A function that returns the plural form index (a number).
*/

@@ -113,3 +123,5 @@ export function add(language, translations, getPluralForm) {

*
* translate( 'pl', { string: 'Cancel' } ); // 'Cancel'
* ```ts
* translate( 'pl', { string: 'Cancel' } ); // 'Cancel'
* ```
*

@@ -119,4 +131,6 @@ * The third optional argument is the number of elements, based on which the single form or one of the plural forms

*
* translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 1 ); // 'Add a space'
* translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 3 ); // 'Add %0 spaces'
* ```ts
* translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 1 ); // 'Add a space'
* translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 3 ); // 'Add %0 spaces'
* ```
*

@@ -126,10 +140,12 @@ * The message should provide an ID using the `id` property when the message strings are not unique and their

*
* translate( 'en', { string: 'image', id: 'ADD_IMAGE' } );
* translate( 'en', { string: 'image', id: 'AN_IMAGE' } );
* ```ts
* translate( 'en', { string: 'image', id: 'ADD_IMAGE' } );
* translate( 'en', { string: 'image', id: 'AN_IMAGE' } );
* ```
*
* @protected
* @param {String} language Target language.
* @param {module:utils/translation-service~Message} message A message that will be translated.
* @param {Number} [quantity] The number of elements for which a plural form should be picked from the target language dictionary.
* @returns {String} Translated sentence.
* @internal
* @param language Target language.
* @param message A message that will be translated.
* @param quantity The number of elements for which a plural form should be picked from the target language dictionary.
* @returns Translated sentence.
*/

@@ -174,3 +190,3 @@ export function _translate(language, message, quantity = 1) {

*
* @protected
* @internal
*/

@@ -180,3 +196,5 @@ export function _clear() {

}
// Checks whether the dictionary exists and translation in that dictionary exists.
/**
* Checks whether the dictionary exists and translation in that dictionary exists.
*/
function hasTranslation(language, messageId) {

@@ -183,0 +201,0 @@ return (!!global.window.CKEDITOR_TRANSLATIONS[language] &&

@@ -8,4 +8,6 @@ /**

*/
// A hash table of hex numbers to avoid using toString() in uid() which is costly.
// [ '00', '01', '02', ..., 'fe', 'ff' ]
/**
* A hash table of hex numbers to avoid using toString() in uid() which is costly.
* [ '00', '01', '02', ..., 'fe', 'ff' ]
*/
const HEX_NUMBERS = new Array(256).fill('')

@@ -21,3 +23,3 @@ .map((_, index) => ('0' + (index).toString(16)).slice(-2));

*
* @returns {String} An unique id string.
* @returns An unique id string.
*/

@@ -24,0 +26,0 @@ export default function uid() {

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

*
* @param {String} character Character to check.
* @returns {Boolean}
* @param character Character to check.
*/

@@ -27,4 +26,3 @@ export function isCombiningMark(character) {

*
* @param {String} character Character to check.
* @returns {Boolean}
* @param character Character to check.
*/

@@ -40,4 +38,3 @@ export function isHighSurrogateHalf(character) {

*
* @param {String} character Character to check.
* @returns {Boolean}
* @param character Character to check.
*/

@@ -50,5 +47,4 @@ export function isLowSurrogateHalf(character) {

*
* @param {String} string String to check.
* @param {Number} offset Offset to check.
* @returns {Boolean}
* @param string String to check.
* @param offset Offset to check.
*/

@@ -61,5 +57,4 @@ export function isInsideSurrogatePair(string, offset) {

*
* @param {String} string String to check.
* @param {Number} offset Offset to check.
* @returns {Boolean}
* @param string String to check.
* @param offset Offset to check.
*/

@@ -73,5 +68,4 @@ export function isInsideCombinedSymbol(string, offset) {

*
* @param {String} string String to check.
* @param {Number} offset Offset to check.
* @returns {Boolean}
* @param string String to check.
* @param offset Offset to check.
*/

@@ -78,0 +72,0 @@ export function isInsideEmojiSequence(string, offset) {

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

import CKEditorError from './ckeditorerror';
const version = '35.3.2';
const version = '35.4.0';
export default version;

@@ -29,4 +29,6 @@ /* istanbul ignore next */

*
* import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
* import Highlight from '@ckeditor/ckeditor5-highlight/src/highlight';
* ```ts
* import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
* import Highlight from '@ckeditor/ckeditor5-highlight/src/highlight';
* ```
*

@@ -59,19 +61,21 @@ * Then your project loads some CKEditor 5 packages twice. How does it happen?

*
* import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
* import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
* import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
* import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
* import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
* ```ts
* import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
* import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
* import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
* import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
* import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
*
* ClassicEditor
* .create( document.querySelector( '#editor' ), {
* plugins: [ Essentials, Paragraph, Bold, Italic ],
* toolbar: [ 'bold', 'italic' ]
* } )
* .then( editor => {
* console.log( 'Editor was initialized', editor );
* } )
* .catch( error => {
* console.error( error.stack );
* } );
* ClassicEditor
* .create( document.querySelector( '#editor' ), {
* plugins: [ Essentials, Paragraph, Bold, Italic ],
* toolbar: [ 'bold', 'italic' ]
* } )
* .then( editor => {
* console.log( 'Editor was initialized', editor );
* } )
* .catch( error => {
* console.error( error.stack );
* } );
* ```
*

@@ -81,7 +85,9 @@ * However, you might have mistakenly imported a build instead of the source `ClassicEditor`. In this case

*
* import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
* import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
* import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
* import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
* import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
* ```ts
* import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
* import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
* import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
* import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
* import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
* ```
*

@@ -124,3 +130,3 @@ * This creates the same situation as in the previous section because you use a build together with source plugins.

* whether you use packages coming from the same CKEditor 5 version. You can read more about versioning in the
* {@glink support/versioning-policy Versioning policy} guide.
* {@glink updating/versioning-policy Versioning policy} guide.
*

@@ -127,0 +133,0 @@ * # Packages were duplicated in `node_modules`

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