@ckeditor/ckeditor5-utils
Advanced tools
Comparing version 35.3.2 to 35.4.0
{ | ||
"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` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
252240
5770