@ckeditor/ckeditor5-utils 34.2.0 → 35.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +324 -0
  2. package/LICENSE.md +1 -1
  3. package/package.json +19 -8
  4. package/src/areconnectedthroughproperties.js +54 -71
  5. package/src/ckeditorerror.js +92 -114
  6. package/src/collection.js +594 -762
  7. package/src/comparearrays.js +22 -28
  8. package/src/config.js +193 -223
  9. package/src/count.js +8 -12
  10. package/src/diff.js +85 -110
  11. package/src/difftochanges.js +47 -57
  12. package/src/dom/createelement.js +17 -25
  13. package/src/dom/emittermixin.js +202 -263
  14. package/src/dom/getancestors.js +9 -13
  15. package/src/dom/getborderwidths.js +10 -13
  16. package/src/dom/getcommonancestor.js +9 -15
  17. package/src/dom/getdatafromelement.js +5 -9
  18. package/src/dom/getpositionedancestor.js +9 -14
  19. package/src/dom/global.js +15 -4
  20. package/src/dom/indexof.js +7 -11
  21. package/src/dom/insertat.js +2 -4
  22. package/src/dom/iscomment.js +2 -5
  23. package/src/dom/isnode.js +10 -12
  24. package/src/dom/isrange.js +2 -4
  25. package/src/dom/istext.js +2 -4
  26. package/src/dom/isvisible.js +2 -4
  27. package/src/dom/iswindow.js +11 -16
  28. package/src/dom/position.js +220 -410
  29. package/src/dom/rect.js +335 -414
  30. package/src/dom/remove.js +5 -8
  31. package/src/dom/resizeobserver.js +109 -342
  32. package/src/dom/scroll.js +151 -183
  33. package/src/dom/setdatainelement.js +5 -9
  34. package/src/dom/tounit.js +10 -12
  35. package/src/elementreplacer.js +30 -44
  36. package/src/emittermixin.js +368 -634
  37. package/src/env.js +109 -116
  38. package/src/eventinfo.js +12 -65
  39. package/src/fastdiff.js +96 -128
  40. package/src/first.js +8 -12
  41. package/src/focustracker.js +77 -133
  42. package/src/index.js +0 -9
  43. package/src/inserttopriorityarray.js +9 -30
  44. package/src/isiterable.js +2 -4
  45. package/src/keyboard.js +117 -196
  46. package/src/keystrokehandler.js +72 -88
  47. package/src/language.js +9 -15
  48. package/src/locale.js +61 -158
  49. package/src/mapsequal.js +12 -17
  50. package/src/mix.js +17 -16
  51. package/src/nth.js +8 -11
  52. package/src/objecttomap.js +7 -11
  53. package/src/observablemixin.js +474 -778
  54. package/src/priorities.js +20 -32
  55. package/src/spy.js +3 -6
  56. package/src/toarray.js +2 -13
  57. package/src/tomap.js +8 -10
  58. package/src/translation-service.js +57 -93
  59. package/src/uid.js +34 -38
  60. package/src/unicode.js +28 -43
  61. package/src/version.js +134 -143
@@ -2,11 +2,9 @@
2
2
  * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  /**
7
6
  * @module utils/comparearrays
8
7
  */
9
-
10
8
  /**
11
9
  * Compares how given arrays relate to each other. One array can be: same as another array, prefix of another array
12
10
  * or completely different. If arrays are different, first index at which they differ is returned. Otherwise,
@@ -21,31 +19,27 @@
21
19
  *
22
20
  * @param {Array} a Array that is compared.
23
21
  * @param {Array} b Array to compare with.
24
- * @returns {module:utils/comparearrays~ArrayRelation} How array `a` is related to `b`.
22
+ * @returns {module:utils/comparearrays~ArrayRelation|Number} How array `a` is related to `b`.
25
23
  */
26
- export default function compareArrays( a, b ) {
27
- const minLen = Math.min( a.length, b.length );
28
-
29
- for ( let i = 0; i < minLen; i++ ) {
30
- if ( a[ i ] != b[ i ] ) {
31
- // The arrays are different.
32
- return i;
33
- }
34
- }
35
-
36
- // Both arrays were same at all points.
37
- if ( a.length == b.length ) {
38
- // If their length is also same, they are the same.
39
- return 'same';
40
- } else if ( a.length < b.length ) {
41
- // Compared array is shorter so it is a prefix of the other array.
42
- return 'prefix';
43
- } else {
44
- // Compared array is longer so it is an extension of the other array.
45
- return 'extension';
46
- }
24
+ export default function compareArrays(a, b) {
25
+ const minLen = Math.min(a.length, b.length);
26
+ for (let i = 0; i < minLen; i++) {
27
+ if (a[i] != b[i]) {
28
+ // The arrays are different.
29
+ return i;
30
+ }
31
+ }
32
+ // Both arrays were same at all points.
33
+ if (a.length == b.length) {
34
+ // If their length is also same, they are the same.
35
+ return 'same';
36
+ }
37
+ else if (a.length < b.length) {
38
+ // Compared array is shorter so it is a prefix of the other array.
39
+ return 'prefix';
40
+ }
41
+ else {
42
+ // Compared array is longer so it is an extension of the other array.
43
+ return 'extension';
44
+ }
47
45
  }
48
-
49
- /**
50
- * @typedef {'extension'|'same'|'prefix'} module:utils/comparearrays~ArrayRelation
51
- */
package/src/config.js CHANGED
@@ -2,245 +2,215 @@
2
2
  * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  /**
7
6
  * @module utils/config
8
7
  */
9
-
10
8
  import { isPlainObject, isElement, cloneDeepWith } from 'lodash-es';
11
-
12
9
  /**
13
10
  * Handles a configuration dictionary.
14
11
  */
15
12
  export default class Config {
16
- /**
17
- * Creates an instance of the {@link ~Config} class.
18
- *
19
- * @param {Object} [configurations] The initial configurations to be set. Usually, provided by the user.
20
- * @param {Object} [defaultConfigurations] The default configurations. Usually, provided by the system.
21
- */
22
- constructor( configurations, defaultConfigurations ) {
23
- /**
24
- * Store for the whole configuration.
25
- *
26
- * @private
27
- * @member {Object}
28
- */
29
- this._config = {};
30
-
31
- // Set default configuration.
32
- if ( defaultConfigurations ) {
33
- // Clone the configuration to make sure that the properties will not be shared
34
- // between editors and make the watchdog feature work correctly.
35
- this.define( cloneConfig( defaultConfigurations ) );
36
- }
37
-
38
- // Set initial configuration.
39
- if ( configurations ) {
40
- this._setObjectToTarget( this._config, configurations );
41
- }
42
- }
43
-
44
- /**
45
- * Set configuration values.
46
- *
47
- * It accepts both a name/value pair or an object, which properties and values will be used to set
48
- * configurations.
49
- *
50
- * It also accepts setting a "deep configuration" by using dots in the name. For example, `'resize.width'` sets
51
- * the value for the `width` configuration in the `resize` subset.
52
- *
53
- * config.set( 'width', 500 );
54
- * config.set( 'toolbar.collapsed', true );
55
- *
56
- * // Equivalent to:
57
- * config.set( {
58
- * width: 500
59
- * toolbar: {
60
- * collapsed: true
61
- * }
62
- * } );
63
- *
64
- * Passing an object as the value will amend the configuration, not replace it.
65
- *
66
- * config.set( 'toolbar', {
67
- * collapsed: true,
68
- * } );
69
- *
70
- * config.set( 'toolbar', {
71
- * color: 'red',
72
- * } );
73
- *
74
- * config.get( 'toolbar.collapsed' ); // true
75
- * config.get( 'toolbar.color' ); // 'red'
76
- *
77
- * @param {String|Object} name The configuration name or an object from which take properties as
78
- * configuration entries. Configuration names are case-sensitive.
79
- * @param {*} value The configuration value. Used if a name is passed.
80
- */
81
- set( name, value ) {
82
- this._setToTarget( this._config, name, value );
83
- }
84
-
85
- /**
86
- * Does exactly the same as {@link #set} with one exception – passed configuration extends
87
- * existing one, but does not overwrite already defined values.
88
- *
89
- * This method is supposed to be called by plugin developers to setup plugin's configurations. It would be
90
- * rarely used for other needs.
91
- *
92
- * @param {String|Object} name The configuration name or an object from which take properties as
93
- * configuration entries. Configuration names are case-sensitive.
94
- * @param {*} value The configuration value. Used if a name is passed.
95
- */
96
- define( name, value ) {
97
- const isDefine = true;
98
-
99
- this._setToTarget( this._config, name, value, isDefine );
100
- }
101
-
102
- /**
103
- * Gets the value for a configuration entry.
104
- *
105
- * config.get( 'name' );
106
- *
107
- * Deep configurations can be retrieved by separating each part with a dot.
108
- *
109
- * config.get( 'toolbar.collapsed' );
110
- *
111
- * @param {String} name The configuration name. Configuration names are case-sensitive.
112
- * @returns {*} The configuration value or `undefined` if the configuration entry was not found.
113
- */
114
- get( name ) {
115
- return this._getFromSource( this._config, name );
116
- }
117
-
118
- /**
119
- * Iterates over all top level configuration names.
120
- *
121
- * @returns {Iterable.<String>}
122
- */
123
- * names() {
124
- for ( const name of Object.keys( this._config ) ) {
125
- yield name;
126
- }
127
- }
128
-
129
- /**
130
- * Saves passed configuration to the specified target (nested object).
131
- *
132
- * @private
133
- * @param {Object} target Nested config object.
134
- * @param {String|Object} name The configuration name or an object from which take properties as
135
- * configuration entries. Configuration names are case-sensitive.
136
- * @param {*} value The configuration value. Used if a name is passed.
137
- * @param {Boolean} [isDefine=false] Define if passed configuration should overwrite existing one.
138
- */
139
- _setToTarget( target, name, value, isDefine = false ) {
140
- // In case of an object, iterate through it and call `_setToTarget` again for each property.
141
- if ( isPlainObject( name ) ) {
142
- this._setObjectToTarget( target, name, isDefine );
143
-
144
- return;
145
- }
146
-
147
- // The configuration name should be split into parts if it has dots. E.g. `resize.width` -> [`resize`, `width`].
148
- const parts = name.split( '.' );
149
-
150
- // Take the name of the configuration out of the parts. E.g. `resize.width` -> `width`.
151
- name = parts.pop();
152
-
153
- // Iterate over parts to check if currently stored configuration has proper structure.
154
- for ( const part of parts ) {
155
- // If there is no object for specified part then create one.
156
- if ( !isPlainObject( target[ part ] ) ) {
157
- target[ part ] = {};
158
- }
159
-
160
- // Nested object becomes a target.
161
- target = target[ part ];
162
- }
163
-
164
- // In case of value is an object.
165
- if ( isPlainObject( value ) ) {
166
- // We take care of proper config structure.
167
- if ( !isPlainObject( target[ name ] ) ) {
168
- target[ name ] = {};
169
- }
170
-
171
- target = target[ name ];
172
-
173
- // And iterate through this object calling `_setToTarget` again for each property.
174
- this._setObjectToTarget( target, value, isDefine );
175
-
176
- return;
177
- }
178
-
179
- // Do nothing if we are defining configuration for non empty name.
180
- if ( isDefine && typeof target[ name ] != 'undefined' ) {
181
- return;
182
- }
183
-
184
- target[ name ] = value;
185
- }
186
-
187
- /**
188
- * Get specified configuration from specified source (nested object).
189
- *
190
- * @private
191
- * @param {Object} source level of nested object.
192
- * @param {String} name The configuration name. Configuration names are case-sensitive.
193
- * @returns {*} The configuration value or `undefined` if the configuration entry was not found.
194
- */
195
- _getFromSource( source, name ) {
196
- // The configuration name should be split into parts if it has dots. E.g. `resize.width` -> [`resize`, `width`].
197
- const parts = name.split( '.' );
198
-
199
- // Take the name of the configuration out of the parts. E.g. `resize.width` -> `width`.
200
- name = parts.pop();
201
-
202
- // Iterate over parts to check if currently stored configuration has proper structure.
203
- for ( const part of parts ) {
204
- if ( !isPlainObject( source[ part ] ) ) {
205
- source = null;
206
- break;
207
- }
208
-
209
- // Nested object becomes a source.
210
- source = source[ part ];
211
- }
212
-
213
- // Always returns undefined for non existing configuration.
214
- return source ? cloneConfig( source[ name ] ) : undefined;
215
- }
216
-
217
- /**
218
- * Iterates through passed object and calls {@link #_setToTarget} method with object key and value for each property.
219
- *
220
- * @private
221
- * @param {Object} target Nested config object.
222
- * @param {Object} configuration Configuration data set
223
- * @param {Boolean} [isDefine] Defines if passed configuration is default configuration or not.
224
- */
225
- _setObjectToTarget( target, configuration, isDefine ) {
226
- Object.keys( configuration ).forEach( key => {
227
- this._setToTarget( target, key, configuration[ key ], isDefine );
228
- } );
229
- }
13
+ /**
14
+ * Creates an instance of the {@link ~Config} class.
15
+ *
16
+ * @param {Object} [configurations] The initial configurations to be set. Usually, provided by the user.
17
+ * @param {Object} [defaultConfigurations] The default configurations. Usually, provided by the system.
18
+ */
19
+ constructor(configurations, defaultConfigurations) {
20
+ /**
21
+ * Store for the whole configuration.
22
+ *
23
+ * @private
24
+ * @member {Object}
25
+ */
26
+ this._config = {};
27
+ // Set default configuration.
28
+ if (defaultConfigurations) {
29
+ // Clone the configuration to make sure that the properties will not be shared
30
+ // between editors and make the watchdog feature work correctly.
31
+ this.define(cloneConfig(defaultConfigurations));
32
+ }
33
+ // Set initial configuration.
34
+ if (configurations) {
35
+ this._setObjectToTarget(this._config, configurations);
36
+ }
37
+ }
38
+ /**
39
+ * Set configuration values.
40
+ *
41
+ * It accepts both a name/value pair or an object, which properties and values will be used to set
42
+ * configurations.
43
+ *
44
+ * It also accepts setting a "deep configuration" by using dots in the name. For example, `'resize.width'` sets
45
+ * the value for the `width` configuration in the `resize` subset.
46
+ *
47
+ * config.set( 'width', 500 );
48
+ * config.set( 'toolbar.collapsed', true );
49
+ *
50
+ * // Equivalent to:
51
+ * config.set( {
52
+ * width: 500
53
+ * toolbar: {
54
+ * collapsed: true
55
+ * }
56
+ * } );
57
+ *
58
+ * Passing an object as the value will amend the configuration, not replace it.
59
+ *
60
+ * config.set( 'toolbar', {
61
+ * collapsed: true,
62
+ * } );
63
+ *
64
+ * config.set( 'toolbar', {
65
+ * color: 'red',
66
+ * } );
67
+ *
68
+ * config.get( 'toolbar.collapsed' ); // true
69
+ * config.get( 'toolbar.color' ); // 'red'
70
+ *
71
+ * @param {String|Object} name The configuration name or an object from which take properties as
72
+ * configuration entries. Configuration names are case-sensitive.
73
+ * @param {*} value The configuration value. Used if a name is passed.
74
+ */
75
+ set(name, value) {
76
+ this._setToTarget(this._config, name, value);
77
+ }
78
+ /**
79
+ * Does exactly the same as {@link #set} with one exception – passed configuration extends
80
+ * existing one, but does not overwrite already defined values.
81
+ *
82
+ * This method is supposed to be called by plugin developers to setup plugin's configurations. It would be
83
+ * rarely used for other needs.
84
+ *
85
+ * @param {String|Object} name The configuration name or an object from which take properties as
86
+ * configuration entries. Configuration names are case-sensitive.
87
+ * @param {*} value The configuration value. Used if a name is passed.
88
+ */
89
+ define(name, value) {
90
+ const isDefine = true;
91
+ this._setToTarget(this._config, name, value, isDefine);
92
+ }
93
+ /**
94
+ * Gets the value for a configuration entry.
95
+ *
96
+ * config.get( 'name' );
97
+ *
98
+ * Deep configurations can be retrieved by separating each part with a dot.
99
+ *
100
+ * config.get( 'toolbar.collapsed' );
101
+ *
102
+ * @param {String} name The configuration name. Configuration names are case-sensitive.
103
+ * @returns {*} The configuration value or `undefined` if the configuration entry was not found.
104
+ */
105
+ get(name) {
106
+ return this._getFromSource(this._config, name);
107
+ }
108
+ /**
109
+ * Iterates over all top level configuration names.
110
+ *
111
+ * @returns {Iterable.<String>}
112
+ */
113
+ *names() {
114
+ for (const name of Object.keys(this._config)) {
115
+ yield name;
116
+ }
117
+ }
118
+ /**
119
+ * Saves passed configuration to the specified target (nested object).
120
+ *
121
+ * @private
122
+ * @param {Object} target Nested config object.
123
+ * @param {String|Object} name The configuration name or an object from which take properties as
124
+ * configuration entries. Configuration names are case-sensitive.
125
+ * @param {*} value The configuration value. Used if a name is passed.
126
+ * @param {Boolean} [isDefine=false] Define if passed configuration should overwrite existing one.
127
+ */
128
+ _setToTarget(target, name, value, isDefine = false) {
129
+ // In case of an object, iterate through it and call `_setToTarget` again for each property.
130
+ if (isPlainObject(name)) {
131
+ this._setObjectToTarget(target, name, isDefine);
132
+ return;
133
+ }
134
+ // The configuration name should be split into parts if it has dots. E.g. `resize.width` -> [`resize`, `width`].
135
+ const parts = name.split('.');
136
+ // Take the name of the configuration out of the parts. E.g. `resize.width` -> `width`.
137
+ name = parts.pop();
138
+ // Iterate over parts to check if currently stored configuration has proper structure.
139
+ for (const part of parts) {
140
+ // If there is no object for specified part then create one.
141
+ if (!isPlainObject(target[part])) {
142
+ target[part] = {};
143
+ }
144
+ // Nested object becomes a target.
145
+ target = target[part];
146
+ }
147
+ // In case of value is an object.
148
+ if (isPlainObject(value)) {
149
+ // We take care of proper config structure.
150
+ if (!isPlainObject(target[name])) {
151
+ target[name] = {};
152
+ }
153
+ target = target[name];
154
+ // And iterate through this object calling `_setToTarget` again for each property.
155
+ this._setObjectToTarget(target, value, isDefine);
156
+ return;
157
+ }
158
+ // Do nothing if we are defining configuration for non empty name.
159
+ if (isDefine && typeof target[name] != 'undefined') {
160
+ return;
161
+ }
162
+ target[name] = value;
163
+ }
164
+ /**
165
+ * Get specified configuration from specified source (nested object).
166
+ *
167
+ * @private
168
+ * @param {Object} source level of nested object.
169
+ * @param {String} name The configuration name. Configuration names are case-sensitive.
170
+ * @returns {*} The configuration value or `undefined` if the configuration entry was not found.
171
+ */
172
+ _getFromSource(source, name) {
173
+ // The configuration name should be split into parts if it has dots. E.g. `resize.width` -> [`resize`, `width`].
174
+ const parts = name.split('.');
175
+ // Take the name of the configuration out of the parts. E.g. `resize.width` -> `width`.
176
+ name = parts.pop();
177
+ // Iterate over parts to check if currently stored configuration has proper structure.
178
+ for (const part of parts) {
179
+ if (!isPlainObject(source[part])) {
180
+ source = null;
181
+ break;
182
+ }
183
+ // Nested object becomes a source.
184
+ source = source[part];
185
+ }
186
+ // Always returns undefined for non existing configuration.
187
+ return source ? cloneConfig(source[name]) : undefined;
188
+ }
189
+ /**
190
+ * Iterates through passed object and calls {@link #_setToTarget} method with object key and value for each property.
191
+ *
192
+ * @private
193
+ * @param {Object} target Nested config object.
194
+ * @param {Object} configuration Configuration data set
195
+ * @param {Boolean} [isDefine] Defines if passed configuration is default configuration or not.
196
+ */
197
+ _setObjectToTarget(target, configuration, isDefine) {
198
+ Object.keys(configuration).forEach(key => {
199
+ this._setToTarget(target, key, configuration[key], isDefine);
200
+ });
201
+ }
230
202
  }
231
-
232
203
  // Clones configuration object or value.
233
204
  // @param {*} source Source configuration
234
205
  // @returns {*} Cloned configuration value.
235
- function cloneConfig( source ) {
236
- return cloneDeepWith( source, leaveDOMReferences );
206
+ function cloneConfig(source) {
207
+ return cloneDeepWith(source, leaveDOMReferences);
237
208
  }
238
-
239
209
  // A customized function for cloneDeepWith.
240
210
  // It will leave references to DOM Elements instead of cloning them.
241
211
  //
242
212
  // @param {*} value
243
213
  // @returns {Element|undefined}
244
- function leaveDOMReferences( value ) {
245
- return isElement( value ) ? value : undefined;
214
+ function leaveDOMReferences(value) {
215
+ return isElement(value) ? value : undefined;
246
216
  }
package/src/count.js CHANGED
@@ -2,25 +2,21 @@
2
2
  * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  /**
7
6
  * @module utils/count
8
7
  */
9
-
10
8
  /**
11
9
  * Returns the number of items return by the iterator.
12
10
  *
13
11
  * count( [ 1, 2, 3, 4, 5 ] ); // 5;
14
12
  *
15
- * @param {Iterable.<*>} iterator Any iterator.
16
- * @returns {Number} Number of items returned by that iterator.
13
+ * @param {Iterable.<*>} iterable Any iterable.
14
+ * @returns {Number} Number of items returned by that iterable.
17
15
  */
18
- export default function count( iterator ) {
19
- let count = 0;
20
-
21
- for ( const _ of iterator ) { // eslint-disable-line no-unused-vars
22
- count++;
23
- }
24
-
25
- return count;
16
+ export default function count(iterable) {
17
+ let count = 0;
18
+ for (const _ of iterable) { // eslint-disable-line no-unused-vars
19
+ count++;
20
+ }
21
+ return count;
26
22
  }