@ckeditor/ckeditor5-utils 0.0.0-internal-20241017.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 (213) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +22 -0
  4. package/dist/abortabledebounce.d.ts +21 -0
  5. package/dist/areconnectedthroughproperties.d.ts +15 -0
  6. package/dist/ckeditorerror.d.ts +127 -0
  7. package/dist/collection.d.ts +437 -0
  8. package/dist/comparearrays.d.ts +34 -0
  9. package/dist/config.d.ts +167 -0
  10. package/dist/count.d.ts +22 -0
  11. package/dist/crc32.d.ts +30 -0
  12. package/dist/delay.d.ts +23 -0
  13. package/dist/diff.d.ts +35 -0
  14. package/dist/difftochanges.d.ts +63 -0
  15. package/dist/dom/createelement.d.ts +61 -0
  16. package/dist/dom/emittermixin.d.ts +146 -0
  17. package/dist/dom/findclosestscrollableancestor.d.ts +15 -0
  18. package/dist/dom/getancestors.d.ts +21 -0
  19. package/dist/dom/getborderwidths.d.ts +28 -0
  20. package/dist/dom/getcommonancestor.d.ts +16 -0
  21. package/dist/dom/getdatafromelement.d.ts +18 -0
  22. package/dist/dom/getpositionedancestor.d.ts +14 -0
  23. package/dist/dom/getrangefrommouseevent.d.ts +21 -0
  24. package/dist/dom/global.d.ts +36 -0
  25. package/dist/dom/indexof.d.ts +18 -0
  26. package/dist/dom/insertat.d.ts +19 -0
  27. package/dist/dom/iscomment.d.ts +15 -0
  28. package/dist/dom/isnode.d.ts +15 -0
  29. package/dist/dom/isrange.d.ts +15 -0
  30. package/dist/dom/istext.d.ts +15 -0
  31. package/dist/dom/isvalidattributename.d.ts +14 -0
  32. package/dist/dom/isvisible.d.ts +19 -0
  33. package/dist/dom/iswindow.d.ts +15 -0
  34. package/dist/dom/position.d.ts +215 -0
  35. package/dist/dom/rect.d.ts +199 -0
  36. package/dist/dom/remove.d.ts +17 -0
  37. package/dist/dom/resizeobserver.d.ts +78 -0
  38. package/dist/dom/scroll.d.ts +77 -0
  39. package/dist/dom/setdatainelement.d.ts +18 -0
  40. package/dist/dom/tounit.d.ts +26 -0
  41. package/dist/elementreplacer.d.ts +35 -0
  42. package/dist/emittermixin.d.ts +316 -0
  43. package/dist/env.d.ts +144 -0
  44. package/dist/eventinfo.d.ts +62 -0
  45. package/dist/fastdiff.d.ts +116 -0
  46. package/dist/first.d.ts +15 -0
  47. package/dist/focustracker.d.ts +83 -0
  48. package/dist/index-content.css +4 -0
  49. package/dist/index-editor.css +4 -0
  50. package/dist/index.css +4 -0
  51. package/dist/index.d.ts +70 -0
  52. package/dist/index.js +5871 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/inserttopriorityarray.d.ts +34 -0
  55. package/dist/isiterable.d.ts +18 -0
  56. package/dist/keyboard.d.ts +130 -0
  57. package/dist/keystrokehandler.d.ts +101 -0
  58. package/dist/language.d.ts +21 -0
  59. package/dist/locale.d.ts +145 -0
  60. package/dist/mapsequal.d.ts +19 -0
  61. package/dist/mix.d.ts +89 -0
  62. package/dist/nth.d.ts +20 -0
  63. package/dist/objecttomap.d.ts +27 -0
  64. package/dist/observablemixin.d.ts +564 -0
  65. package/dist/parsebase64encodedobject.d.ts +15 -0
  66. package/dist/priorities.d.ts +37 -0
  67. package/dist/retry.d.ts +37 -0
  68. package/dist/splicearray.d.ts +30 -0
  69. package/dist/spy.d.ts +25 -0
  70. package/dist/toarray.d.ts +29 -0
  71. package/dist/tomap.d.ts +23 -0
  72. package/dist/translation-service.d.ts +178 -0
  73. package/dist/uid.d.ts +19 -0
  74. package/dist/unicode.d.ts +58 -0
  75. package/dist/version.d.ts +14 -0
  76. package/dist/wait.d.ts +20 -0
  77. package/package.json +36 -0
  78. package/src/abortabledebounce.d.ts +17 -0
  79. package/src/abortabledebounce.js +22 -0
  80. package/src/areconnectedthroughproperties.d.ts +11 -0
  81. package/src/areconnectedthroughproperties.js +73 -0
  82. package/src/ckeditorerror.d.ts +123 -0
  83. package/src/ckeditorerror.js +176 -0
  84. package/src/collection.d.ts +433 -0
  85. package/src/collection.js +583 -0
  86. package/src/comparearrays.d.ts +30 -0
  87. package/src/comparearrays.js +47 -0
  88. package/src/config.d.ts +163 -0
  89. package/src/config.js +163 -0
  90. package/src/count.d.ts +18 -0
  91. package/src/count.js +25 -0
  92. package/src/crc32.d.ts +26 -0
  93. package/src/crc32.js +61 -0
  94. package/src/delay.d.ts +19 -0
  95. package/src/delay.js +26 -0
  96. package/src/diff.d.ts +31 -0
  97. package/src/diff.js +115 -0
  98. package/src/difftochanges.d.ts +59 -0
  99. package/src/difftochanges.js +79 -0
  100. package/src/dom/createelement.d.ts +57 -0
  101. package/src/dom/createelement.js +40 -0
  102. package/src/dom/emittermixin.d.ts +142 -0
  103. package/src/dom/emittermixin.js +239 -0
  104. package/src/dom/findclosestscrollableancestor.d.ts +11 -0
  105. package/src/dom/findclosestscrollableancestor.js +31 -0
  106. package/src/dom/getancestors.d.ts +17 -0
  107. package/src/dom/getancestors.js +27 -0
  108. package/src/dom/getborderwidths.d.ts +24 -0
  109. package/src/dom/getborderwidths.js +24 -0
  110. package/src/dom/getcommonancestor.d.ts +12 -0
  111. package/src/dom/getcommonancestor.js +25 -0
  112. package/src/dom/getdatafromelement.d.ts +14 -0
  113. package/src/dom/getdatafromelement.js +20 -0
  114. package/src/dom/getpositionedancestor.d.ts +10 -0
  115. package/src/dom/getpositionedancestor.js +22 -0
  116. package/src/dom/getrangefrommouseevent.d.ts +17 -0
  117. package/src/dom/getrangefrommouseevent.js +33 -0
  118. package/src/dom/global.d.ts +32 -0
  119. package/src/dom/global.js +35 -0
  120. package/src/dom/indexof.d.ts +14 -0
  121. package/src/dom/indexof.js +21 -0
  122. package/src/dom/insertat.d.ts +15 -0
  123. package/src/dom/insertat.js +17 -0
  124. package/src/dom/iscomment.d.ts +11 -0
  125. package/src/dom/iscomment.js +14 -0
  126. package/src/dom/isnode.d.ts +11 -0
  127. package/src/dom/isnode.js +21 -0
  128. package/src/dom/isrange.d.ts +11 -0
  129. package/src/dom/isrange.js +13 -0
  130. package/src/dom/istext.d.ts +11 -0
  131. package/src/dom/istext.js +13 -0
  132. package/src/dom/isvalidattributename.d.ts +10 -0
  133. package/src/dom/isvalidattributename.js +22 -0
  134. package/src/dom/isvisible.d.ts +15 -0
  135. package/src/dom/isvisible.js +30 -0
  136. package/src/dom/iswindow.d.ts +11 -0
  137. package/src/dom/iswindow.js +22 -0
  138. package/src/dom/position.d.ts +211 -0
  139. package/src/dom/position.js +313 -0
  140. package/src/dom/rect.d.ts +195 -0
  141. package/src/dom/rect.js +474 -0
  142. package/src/dom/remove.d.ts +13 -0
  143. package/src/dom/remove.js +18 -0
  144. package/src/dom/resizeobserver.d.ts +74 -0
  145. package/src/dom/resizeobserver.js +127 -0
  146. package/src/dom/scroll.d.ts +73 -0
  147. package/src/dom/scroll.js +383 -0
  148. package/src/dom/setdatainelement.d.ts +14 -0
  149. package/src/dom/setdatainelement.js +20 -0
  150. package/src/dom/tounit.d.ts +22 -0
  151. package/src/dom/tounit.js +16 -0
  152. package/src/elementreplacer.d.ts +31 -0
  153. package/src/elementreplacer.js +43 -0
  154. package/src/emittermixin.d.ts +312 -0
  155. package/src/emittermixin.js +453 -0
  156. package/src/env.d.ts +140 -0
  157. package/src/env.js +145 -0
  158. package/src/eventinfo.d.ts +58 -0
  159. package/src/eventinfo.js +26 -0
  160. package/src/fastdiff.d.ts +112 -0
  161. package/src/fastdiff.js +248 -0
  162. package/src/first.d.ts +11 -0
  163. package/src/first.js +17 -0
  164. package/src/focustracker.d.ts +79 -0
  165. package/src/focustracker.js +101 -0
  166. package/src/index.d.ts +66 -0
  167. package/src/index.js +65 -0
  168. package/src/inserttopriorityarray.d.ts +30 -0
  169. package/src/inserttopriorityarray.js +21 -0
  170. package/src/isiterable.d.ts +14 -0
  171. package/src/isiterable.js +16 -0
  172. package/src/keyboard.d.ts +126 -0
  173. package/src/keyboard.js +252 -0
  174. package/src/keystrokehandler.d.ts +97 -0
  175. package/src/keystrokehandler.js +122 -0
  176. package/src/language.d.ts +17 -0
  177. package/src/language.js +20 -0
  178. package/src/locale.d.ts +141 -0
  179. package/src/locale.js +78 -0
  180. package/src/mapsequal.d.ts +15 -0
  181. package/src/mapsequal.js +27 -0
  182. package/src/mix.d.ts +85 -0
  183. package/src/mix.js +50 -0
  184. package/src/nth.d.ts +16 -0
  185. package/src/nth.js +24 -0
  186. package/src/objecttomap.d.ts +23 -0
  187. package/src/objecttomap.js +27 -0
  188. package/src/observablemixin.d.ts +560 -0
  189. package/src/observablemixin.js +580 -0
  190. package/src/parsebase64encodedobject.d.ts +11 -0
  191. package/src/parsebase64encodedobject.js +22 -0
  192. package/src/priorities.d.ts +33 -0
  193. package/src/priorities.js +23 -0
  194. package/src/retry.d.ts +33 -0
  195. package/src/retry.js +47 -0
  196. package/src/splicearray.d.ts +26 -0
  197. package/src/splicearray.js +40 -0
  198. package/src/spy.d.ts +21 -0
  199. package/src/spy.js +22 -0
  200. package/src/toarray.d.ts +25 -0
  201. package/src/toarray.js +7 -0
  202. package/src/tomap.d.ts +19 -0
  203. package/src/tomap.js +29 -0
  204. package/src/translation-service.d.ts +174 -0
  205. package/src/translation-service.js +209 -0
  206. package/src/uid.d.ts +15 -0
  207. package/src/uid.js +45 -0
  208. package/src/unicode.d.ts +54 -0
  209. package/src/unicode.js +85 -0
  210. package/src/version.d.ts +10 -0
  211. package/src/version.js +179 -0
  212. package/src/wait.d.ts +16 -0
  213. package/src/wait.js +29 -0
package/src/retry.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * Tries calling the given callback until it sucessfully resolves.
7
+ *
8
+ * If the callback fails `maxRetries` times, the returned promise is rejected with the last error.
9
+ *
10
+ * @typeParam TResult The result of a successful callback invocation.
11
+ * @param callback The function to call until it succeeds.
12
+ * @param options.maxRetries Maximum number of retries.
13
+ * @param options.retryDelay The time in milliseconds between attempts. By default it implements exponential back-off policy.
14
+ * @param options.signal The signal to abort further retries. The callback itself is not aborted automatically.
15
+ */
16
+ export default function retry<TResult>(callback: () => Promise<TResult>, options?: {
17
+ maxAttempts?: number;
18
+ retryDelay?: (attempt: number) => number;
19
+ signal?: AbortSignal;
20
+ }): Promise<TResult>;
21
+ /**
22
+ * Creates a function that calculates exponential back-off delay. Pass it as `options.retryDelay` to {@link ~retry}.
23
+ *
24
+ * @param options.delay Base delay between invocations. Defaults to 1s.
25
+ * @param options.factor How much to increase the delay. Defaults to 2x.
26
+ * @param options.maxDelay Maximum timeout. Even if higher timeout is calculated, it cannot get higher than this value. Default to 10s.
27
+ * @returns The function calculating the delay.
28
+ */
29
+ export declare function exponentialDelay(options?: {
30
+ delay?: number;
31
+ factor?: number;
32
+ maxDelay?: number;
33
+ }): (attempt: number) => number;
package/src/retry.js ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/retry
7
+ */
8
+ import wait from './wait.js';
9
+ /**
10
+ * Tries calling the given callback until it sucessfully resolves.
11
+ *
12
+ * If the callback fails `maxRetries` times, the returned promise is rejected with the last error.
13
+ *
14
+ * @typeParam TResult The result of a successful callback invocation.
15
+ * @param callback The function to call until it succeeds.
16
+ * @param options.maxRetries Maximum number of retries.
17
+ * @param options.retryDelay The time in milliseconds between attempts. By default it implements exponential back-off policy.
18
+ * @param options.signal The signal to abort further retries. The callback itself is not aborted automatically.
19
+ */
20
+ export default async function retry(callback, options = {}) {
21
+ const { maxAttempts = 4, retryDelay = exponentialDelay(), signal = (new AbortController()).signal } = options;
22
+ signal.throwIfAborted();
23
+ for (let attempt = 0;; attempt++) {
24
+ try {
25
+ return await callback();
26
+ }
27
+ catch (err) {
28
+ const isLast = attempt + 1 >= maxAttempts;
29
+ if (isLast) {
30
+ throw err;
31
+ }
32
+ }
33
+ await wait(retryDelay(attempt), { signal });
34
+ }
35
+ }
36
+ /**
37
+ * Creates a function that calculates exponential back-off delay. Pass it as `options.retryDelay` to {@link ~retry}.
38
+ *
39
+ * @param options.delay Base delay between invocations. Defaults to 1s.
40
+ * @param options.factor How much to increase the delay. Defaults to 2x.
41
+ * @param options.maxDelay Maximum timeout. Even if higher timeout is calculated, it cannot get higher than this value. Default to 10s.
42
+ * @returns The function calculating the delay.
43
+ */
44
+ export function exponentialDelay(options = {}) {
45
+ const { delay = 1000, factor = 2, maxDelay = 10000 } = options;
46
+ return attempt => Math.min(factor ** attempt * delay, maxDelay);
47
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * Splices one array into another. To be used instead of `Array.prototype.splice` as the latter may
7
+ * throw "Maximum call stack size exceeded" when passed huge number of items to insert.
8
+ *
9
+ * Note: in contrary to Array.splice, this function does not modify the original `target`.
10
+ *
11
+ * ```ts
12
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 0, 0 ); // [ 3, 4, 1, 2 ]
13
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 1 ); // [ 1, 3, 4 ]
14
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 0 ); // [ 1, 3, 4, 2 ]
15
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 2, 0 ); // [ 1, 2, 3, 4 ]
16
+ * spliceArray( [ 1, 2 ], [], 0, 1 ); // [ 2 ]
17
+ * ```
18
+ *
19
+ * @param target Array to be spliced.
20
+ * @param source Array of elements to be inserted to target.
21
+ * @param start Index at which nodes should be inserted/removed.
22
+ * @param count Number of items.
23
+ *
24
+ * @returns New spliced array.
25
+ */
26
+ export default function spliceArray<T>(target: ReadonlyArray<T>, source: ReadonlyArray<T>, start: number, count: number): Array<T>;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/splicearray
7
+ */
8
+ const BIG_CHUNK_SIZE = 10000;
9
+ /**
10
+ * Splices one array into another. To be used instead of `Array.prototype.splice` as the latter may
11
+ * throw "Maximum call stack size exceeded" when passed huge number of items to insert.
12
+ *
13
+ * Note: in contrary to Array.splice, this function does not modify the original `target`.
14
+ *
15
+ * ```ts
16
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 0, 0 ); // [ 3, 4, 1, 2 ]
17
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 1 ); // [ 1, 3, 4 ]
18
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 1, 0 ); // [ 1, 3, 4, 2 ]
19
+ * spliceArray( [ 1, 2 ], [ 3, 4 ], 2, 0 ); // [ 1, 2, 3, 4 ]
20
+ * spliceArray( [ 1, 2 ], [], 0, 1 ); // [ 2 ]
21
+ * ```
22
+ *
23
+ * @param target Array to be spliced.
24
+ * @param source Array of elements to be inserted to target.
25
+ * @param start Index at which nodes should be inserted/removed.
26
+ * @param count Number of items.
27
+ *
28
+ * @returns New spliced array.
29
+ */
30
+ export default function spliceArray(target, source, start, count) {
31
+ // In case of performance problems, see: https://github.com/ckeditor/ckeditor5/pull/12429/files#r965850568
32
+ if (Math.max(source.length, target.length) > BIG_CHUNK_SIZE) {
33
+ return target.slice(0, start).concat(source).concat(target.slice(start + count, target.length));
34
+ }
35
+ else {
36
+ const newTarget = Array.from(target);
37
+ newTarget.splice(start, count, ...source);
38
+ return newTarget;
39
+ }
40
+ }
package/src/spy.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/spy
7
+ */
8
+ /**
9
+ * Creates a spy function (ala Sinon.js) that can be used to inspect call to it.
10
+ *
11
+ * The following are the present features:
12
+ *
13
+ * * spy.called: property set to `true` if the function has been called at least once.
14
+ *
15
+ * @returns The spy function.
16
+ */
17
+ declare function spy(): {
18
+ (): void;
19
+ called?: boolean;
20
+ };
21
+ export default spy;
package/src/spy.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/spy
7
+ */
8
+ /**
9
+ * Creates a spy function (ala Sinon.js) that can be used to inspect call to it.
10
+ *
11
+ * The following are the present features:
12
+ *
13
+ * * spy.called: property set to `true` if the function has been called at least once.
14
+ *
15
+ * @returns The spy function.
16
+ */
17
+ function spy() {
18
+ return function spy() {
19
+ spy.called = true;
20
+ };
21
+ }
22
+ export default spy;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/toarray
7
+ */
8
+ /**
9
+ * Transforms any value to an array. If the provided value is already an array, it is returned unchanged.
10
+ *
11
+ * @label MUTABLE
12
+ * @param data The value to transform to an array.
13
+ * @returns An array created from data.
14
+ */
15
+ export default function toArray<T>(data: ArrayOrItem<T>): Array<T>;
16
+ /**
17
+ * Transforms any value to an array. If the provided value is already an array, it is returned unchanged.
18
+ *
19
+ * @label IMMUTABLE
20
+ * @param data The value to transform to an array.
21
+ * @returns An array created from data.
22
+ */
23
+ export default function toArray<T>(data: ReadonlyArrayOrItem<T>): ReadonlyArray<T>;
24
+ export type ArrayOrItem<T> = T | Array<T>;
25
+ export type ReadonlyArrayOrItem<T> = T | ReadonlyArray<T>;
package/src/toarray.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ export default function toArray(data) {
6
+ return Array.isArray(data) ? data : [data];
7
+ }
package/src/tomap.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * Transforms object or iterable to map. Iterable needs to be in the format acceptable by the `Map` constructor.
7
+ *
8
+ * ```ts
9
+ * map = toMap( { 'foo': 1, 'bar': 2 } );
10
+ * map = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
11
+ * map = toMap( anotherMap );
12
+ * ```
13
+ *
14
+ * @param data Object or iterable to transform.
15
+ * @returns Map created from data.
16
+ */
17
+ export default function toMap<T>(data: {
18
+ readonly [key: string]: T;
19
+ } | Iterable<readonly [string, T]> | null | undefined): Map<string, T>;
package/src/tomap.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/tomap
7
+ */
8
+ import objectToMap from './objecttomap.js';
9
+ import isIterable from './isiterable.js';
10
+ /**
11
+ * Transforms object or iterable to map. Iterable needs to be in the format acceptable by the `Map` constructor.
12
+ *
13
+ * ```ts
14
+ * map = toMap( { 'foo': 1, 'bar': 2 } );
15
+ * map = toMap( [ [ 'foo', 1 ], [ 'bar', 2 ] ] );
16
+ * map = toMap( anotherMap );
17
+ * ```
18
+ *
19
+ * @param data Object or iterable to transform.
20
+ * @returns Map created from data.
21
+ */
22
+ export default function toMap(data) {
23
+ if (isIterable(data)) {
24
+ return new Map(data);
25
+ }
26
+ else {
27
+ return objectToMap(data);
28
+ }
29
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module utils/translation-service
7
+ */
8
+ import type { Translations } from './locale.js';
9
+ import { type ArrayOrItem } from './toarray.js';
10
+ declare global {
11
+ var CKEDITOR_TRANSLATIONS: Translations;
12
+ }
13
+ /**
14
+ * Adds translations to existing ones or overrides the existing translations. These translations will later
15
+ * be available for the {@link module:utils/locale~Locale#t `t()`} function.
16
+ *
17
+ * The `translations` is an object which consists of `messageId: translation` pairs. Note that the message ID can be
18
+ * either constructed from the message string or from the message ID if it was passed
19
+ * (this happens rarely and mostly for short messages or messages with placeholders).
20
+ * Since the editor displays only the message string, the message ID can be found either in the source code or in the
21
+ * built translations for another language.
22
+ *
23
+ * ```ts
24
+ * add( 'pl', {
25
+ * 'Cancel': 'Anuluj',
26
+ * 'IMAGE': 'obraz', // Note that the `IMAGE` comes from the message ID, while the string can be `image`.
27
+ * } );
28
+ * ```
29
+ *
30
+ * If the message is supposed to support various plural forms, make sure to provide an array with the singular form and all plural forms:
31
+ *
32
+ * ```ts
33
+ * add( 'pl', {
34
+ * 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
35
+ * } );
36
+ * ```
37
+ *
38
+ * You should also specify the third argument (the `getPluralForm()` function) that will be used to determine the plural form if no
39
+ * language file was loaded for that language. All language files coming from CKEditor 5 sources will have this option set, so
40
+ * these plural form rules will be reused by other translations added to the registered languages. The `getPluralForm()` function
41
+ * can return either a Boolean or a number.
42
+ *
43
+ * ```ts
44
+ * add( 'en', {
45
+ * // ... Translations.
46
+ * }, n => n !== 1 );
47
+ * add( 'pl', {
48
+ * // ... Translations.
49
+ * }, n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
50
+ * ```
51
+ *
52
+ * All translations extend the global `window.CKEDITOR_TRANSLATIONS` object. An example of this object can be found below:
53
+ *
54
+ * ```ts
55
+ * {
56
+ * pl: {
57
+ * dictionary: {
58
+ * 'Cancel': 'Anuluj',
59
+ * 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
60
+ * },
61
+ * // A function that returns the plural form index.
62
+ * getPluralForm: n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
63
+ * }
64
+ * // Other languages.
65
+ * }
66
+ * ```
67
+ *
68
+ * If you cannot import this function from this module (e.g. because you use a CKEditor 5 build), you can
69
+ * still add translations by extending the global `window.CKEDITOR_TRANSLATIONS` object by using a function like
70
+ * the one below:
71
+ *
72
+ * ```ts
73
+ * function addTranslations( language, translations, getPluralForm ) {
74
+ * if ( !global.window.CKEDITOR_TRANSLATIONS ) {
75
+ * global.window.CKEDITOR_TRANSLATIONS = {};
76
+ * }
77
+
78
+ * if ( !global.window.CKEDITOR_TRANSLATIONS[ language ] ) {
79
+ * global.window.CKEDITOR_TRANSLATIONS[ language ] = {};
80
+ * }
81
+ *
82
+ * const languageTranslations = global.window.CKEDITOR_TRANSLATIONS[ language ];
83
+ *
84
+ * languageTranslations.dictionary = languageTranslations.dictionary || {};
85
+ * languageTranslations.getPluralForm = getPluralForm || languageTranslations.getPluralForm;
86
+ *
87
+ * // Extend the dictionary for the given language.
88
+ * Object.assign( languageTranslations.dictionary, translations );
89
+ * }
90
+ * ```
91
+ *
92
+ * @param language Target language.
93
+ * @param translations An object with translations which will be added to the dictionary.
94
+ * For each message ID the value should be either a translation or an array of translations if the message
95
+ * should support plural forms.
96
+ * @param getPluralForm A function that returns the plural form index (a number).
97
+ */
98
+ export declare function add(language: string, translations: {
99
+ readonly [messageId: string]: string | ReadonlyArray<string>;
100
+ }, getPluralForm?: (n: number) => number): void;
101
+ /**
102
+ * **Note:** This method is internal, use {@link module:utils/locale~Locale#t the `t()` function} instead to translate
103
+ * the editor UI parts.
104
+ *
105
+ * This function is responsible for translating messages to the specified language. It uses translations added perviously
106
+ * by {@link module:utils/translation-service~add} (a translations dictionary and the `getPluralForm()` function
107
+ * to provide accurate translations of plural forms).
108
+ *
109
+ * When no translation is defined in the dictionary or the dictionary does not exist, this function returns
110
+ * the original message string or the message plural depending on the number of elements.
111
+ *
112
+ * ```ts
113
+ * translate( 'pl', { string: 'Cancel' } ); // 'Cancel'
114
+ * ```
115
+ *
116
+ * The third optional argument is the number of elements, based on which the single form or one of the plural forms
117
+ * should be picked when the message is supposed to support various plural forms.
118
+ *
119
+ * ```ts
120
+ * translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 1 ); // 'Add a space'
121
+ * translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 3 ); // 'Add %0 spaces'
122
+ * ```
123
+ *
124
+ * The message should provide an ID using the `id` property when the message strings are not unique and their
125
+ * translations should be different.
126
+ *
127
+ * ```ts
128
+ * translate( 'en', { string: 'image', id: 'ADD_IMAGE' } );
129
+ * translate( 'en', { string: 'image', id: 'AN_IMAGE' } );
130
+ * ```
131
+ *
132
+ * @internal
133
+ * @param language Target language.
134
+ * @param message A message that will be translated.
135
+ * @param quantity The number of elements for which a plural form should be picked from the target language dictionary.
136
+ * @param translations Translations passed in editor config, if not provided use the global `window.CKEDITOR_TRANSLATIONS`.
137
+ * @returns Translated sentence.
138
+ */
139
+ export declare function _translate(language: string, message: Message, quantity?: number, translations?: Translations): string;
140
+ /**
141
+ * Clears dictionaries for test purposes.
142
+ *
143
+ * @internal
144
+ */
145
+ export declare function _clear(): void;
146
+ /**
147
+ * If array then merge objects which are inside otherwise return given object.
148
+ *
149
+ * @internal
150
+ * @param translations Translations passed in editor config.
151
+ */
152
+ export declare function _unifyTranslations(translations?: ArrayOrItem<Translations>): Translations | undefined;
153
+ /**
154
+ * The internationalization message interface. A message that implements this interface can be passed to the `t()` function
155
+ * to be translated to the target UI language.
156
+ */
157
+ export interface Message {
158
+ /**
159
+ * The message string to translate. Acts as a default translation if the translation for a given language
160
+ * is not defined. When the message is supposed to support plural forms, the string should be the English singular form of the message.
161
+ */
162
+ readonly string: string;
163
+ /**
164
+ * The message ID. If passed, the message ID is taken from this property instead of the `message.string`.
165
+ * This property is useful when various messages share the same message string, for example, the `editor` string in `in the editor`
166
+ * and `my editor` sentences.
167
+ */
168
+ readonly id?: string;
169
+ /**
170
+ * The plural form of the message. This property should be skipped when a message is not supposed
171
+ * to support plural forms. Otherwise it should always be set to a string with the English plural form of the message.
172
+ */
173
+ readonly plural?: string;
174
+ }
@@ -0,0 +1,209 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ import CKEditorError from './ckeditorerror.js';
6
+ import global from './dom/global.js';
7
+ import { merge } from 'lodash-es';
8
+ /* istanbul ignore else -- @preserve */
9
+ if (!global.window.CKEDITOR_TRANSLATIONS) {
10
+ global.window.CKEDITOR_TRANSLATIONS = {};
11
+ }
12
+ /**
13
+ * Adds translations to existing ones or overrides the existing translations. These translations will later
14
+ * be available for the {@link module:utils/locale~Locale#t `t()`} function.
15
+ *
16
+ * The `translations` is an object which consists of `messageId: translation` pairs. Note that the message ID can be
17
+ * either constructed from the message string or from the message ID if it was passed
18
+ * (this happens rarely and mostly for short messages or messages with placeholders).
19
+ * Since the editor displays only the message string, the message ID can be found either in the source code or in the
20
+ * built translations for another language.
21
+ *
22
+ * ```ts
23
+ * add( 'pl', {
24
+ * 'Cancel': 'Anuluj',
25
+ * 'IMAGE': 'obraz', // Note that the `IMAGE` comes from the message ID, while the string can be `image`.
26
+ * } );
27
+ * ```
28
+ *
29
+ * If the message is supposed to support various plural forms, make sure to provide an array with the singular form and all plural forms:
30
+ *
31
+ * ```ts
32
+ * add( 'pl', {
33
+ * 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
34
+ * } );
35
+ * ```
36
+ *
37
+ * You should also specify the third argument (the `getPluralForm()` function) that will be used to determine the plural form if no
38
+ * language file was loaded for that language. All language files coming from CKEditor 5 sources will have this option set, so
39
+ * these plural form rules will be reused by other translations added to the registered languages. The `getPluralForm()` function
40
+ * can return either a Boolean or a number.
41
+ *
42
+ * ```ts
43
+ * add( 'en', {
44
+ * // ... Translations.
45
+ * }, n => n !== 1 );
46
+ * add( 'pl', {
47
+ * // ... Translations.
48
+ * }, n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
49
+ * ```
50
+ *
51
+ * All translations extend the global `window.CKEDITOR_TRANSLATIONS` object. An example of this object can be found below:
52
+ *
53
+ * ```ts
54
+ * {
55
+ * pl: {
56
+ * dictionary: {
57
+ * 'Cancel': 'Anuluj',
58
+ * 'Add space': [ 'Dodaj spację', 'Dodaj %0 spacje', 'Dodaj %0 spacji' ]
59
+ * },
60
+ * // A function that returns the plural form index.
61
+ * getPluralForm: n => n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 );
62
+ * }
63
+ * // Other languages.
64
+ * }
65
+ * ```
66
+ *
67
+ * If you cannot import this function from this module (e.g. because you use a CKEditor 5 build), you can
68
+ * still add translations by extending the global `window.CKEDITOR_TRANSLATIONS` object by using a function like
69
+ * the one below:
70
+ *
71
+ * ```ts
72
+ * function addTranslations( language, translations, getPluralForm ) {
73
+ * if ( !global.window.CKEDITOR_TRANSLATIONS ) {
74
+ * global.window.CKEDITOR_TRANSLATIONS = {};
75
+ * }
76
+
77
+ * if ( !global.window.CKEDITOR_TRANSLATIONS[ language ] ) {
78
+ * global.window.CKEDITOR_TRANSLATIONS[ language ] = {};
79
+ * }
80
+ *
81
+ * const languageTranslations = global.window.CKEDITOR_TRANSLATIONS[ language ];
82
+ *
83
+ * languageTranslations.dictionary = languageTranslations.dictionary || {};
84
+ * languageTranslations.getPluralForm = getPluralForm || languageTranslations.getPluralForm;
85
+ *
86
+ * // Extend the dictionary for the given language.
87
+ * Object.assign( languageTranslations.dictionary, translations );
88
+ * }
89
+ * ```
90
+ *
91
+ * @param language Target language.
92
+ * @param translations An object with translations which will be added to the dictionary.
93
+ * For each message ID the value should be either a translation or an array of translations if the message
94
+ * should support plural forms.
95
+ * @param getPluralForm A function that returns the plural form index (a number).
96
+ */
97
+ export function add(language, translations, getPluralForm) {
98
+ if (!global.window.CKEDITOR_TRANSLATIONS[language]) {
99
+ global.window.CKEDITOR_TRANSLATIONS[language] = {};
100
+ }
101
+ const languageTranslations = global.window.CKEDITOR_TRANSLATIONS[language];
102
+ languageTranslations.dictionary = languageTranslations.dictionary || {};
103
+ languageTranslations.getPluralForm = getPluralForm || languageTranslations.getPluralForm;
104
+ Object.assign(languageTranslations.dictionary, translations);
105
+ }
106
+ /**
107
+ * **Note:** This method is internal, use {@link module:utils/locale~Locale#t the `t()` function} instead to translate
108
+ * the editor UI parts.
109
+ *
110
+ * This function is responsible for translating messages to the specified language. It uses translations added perviously
111
+ * by {@link module:utils/translation-service~add} (a translations dictionary and the `getPluralForm()` function
112
+ * to provide accurate translations of plural forms).
113
+ *
114
+ * When no translation is defined in the dictionary or the dictionary does not exist, this function returns
115
+ * the original message string or the message plural depending on the number of elements.
116
+ *
117
+ * ```ts
118
+ * translate( 'pl', { string: 'Cancel' } ); // 'Cancel'
119
+ * ```
120
+ *
121
+ * The third optional argument is the number of elements, based on which the single form or one of the plural forms
122
+ * should be picked when the message is supposed to support various plural forms.
123
+ *
124
+ * ```ts
125
+ * translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 1 ); // 'Add a space'
126
+ * translate( 'en', { string: 'Add a space', plural: 'Add %0 spaces' }, 3 ); // 'Add %0 spaces'
127
+ * ```
128
+ *
129
+ * The message should provide an ID using the `id` property when the message strings are not unique and their
130
+ * translations should be different.
131
+ *
132
+ * ```ts
133
+ * translate( 'en', { string: 'image', id: 'ADD_IMAGE' } );
134
+ * translate( 'en', { string: 'image', id: 'AN_IMAGE' } );
135
+ * ```
136
+ *
137
+ * @internal
138
+ * @param language Target language.
139
+ * @param message A message that will be translated.
140
+ * @param quantity The number of elements for which a plural form should be picked from the target language dictionary.
141
+ * @param translations Translations passed in editor config, if not provided use the global `window.CKEDITOR_TRANSLATIONS`.
142
+ * @returns Translated sentence.
143
+ */
144
+ export function _translate(language, message, quantity = 1, translations) {
145
+ if (typeof quantity !== 'number') {
146
+ /**
147
+ * An incorrect value was passed to the translation function. This was probably caused
148
+ * by an incorrect message interpolation of a plural form. Note that for messages supporting plural forms
149
+ * the second argument of the `t()` function should always be a number or an array with a number as the first element.
150
+ *
151
+ * @error translation-service-quantity-not-a-number
152
+ */
153
+ throw new CKEditorError('translation-service-quantity-not-a-number', null, { quantity });
154
+ }
155
+ const normalizedTranslations = translations || global.window.CKEDITOR_TRANSLATIONS;
156
+ const numberOfLanguages = getNumberOfLanguages(normalizedTranslations);
157
+ if (numberOfLanguages === 1) {
158
+ // Override the language to the only supported one.
159
+ // This can't be done in the `Locale` class, because the translations comes after the `Locale` class initialization.
160
+ language = Object.keys(normalizedTranslations)[0];
161
+ }
162
+ const messageId = message.id || message.string;
163
+ if (numberOfLanguages === 0 || !hasTranslation(language, messageId, normalizedTranslations)) {
164
+ if (quantity !== 1) {
165
+ // Return the default plural form that was passed in the `message.plural` parameter.
166
+ return message.plural;
167
+ }
168
+ return message.string;
169
+ }
170
+ const dictionary = normalizedTranslations[language].dictionary;
171
+ const getPluralForm = normalizedTranslations[language].getPluralForm || (n => n === 1 ? 0 : 1);
172
+ const translation = dictionary[messageId];
173
+ if (typeof translation === 'string') {
174
+ return translation;
175
+ }
176
+ const pluralFormIndex = Number(getPluralForm(quantity));
177
+ // Note: The `translate` function is not responsible for replacing `%0, %1, ...` with values.
178
+ return translation[pluralFormIndex];
179
+ }
180
+ /**
181
+ * Clears dictionaries for test purposes.
182
+ *
183
+ * @internal
184
+ */
185
+ export function _clear() {
186
+ if (global.window.CKEDITOR_TRANSLATIONS) {
187
+ global.window.CKEDITOR_TRANSLATIONS = {};
188
+ }
189
+ }
190
+ /**
191
+ * If array then merge objects which are inside otherwise return given object.
192
+ *
193
+ * @internal
194
+ * @param translations Translations passed in editor config.
195
+ */
196
+ export function _unifyTranslations(translations) {
197
+ return Array.isArray(translations) ?
198
+ translations.reduce((acc, translation) => merge(acc, translation)) :
199
+ translations;
200
+ }
201
+ /**
202
+ * Checks whether the dictionary exists and translation in that dictionary exists.
203
+ */
204
+ function hasTranslation(language, messageId, translations) {
205
+ return !!translations[language] && !!translations[language].dictionary[messageId];
206
+ }
207
+ function getNumberOfLanguages(translations) {
208
+ return Object.keys(translations).length;
209
+ }