@ckeditor/ckeditor5-utils 43.3.1 → 44.0.0-alpha.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.
package/README.md CHANGED
@@ -3,20 +3,26 @@ CKEditor 5 utilities
3
3
 
4
4
  [![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-utils.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-utils)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/ckeditor/ckeditor5/badge.svg?branch=master)](https://coveralls.io/github/ckeditor/ckeditor5?branch=master)
6
- [![Build Status](https://travis-ci.com/ckeditor/ckeditor5.svg?branch=master)](https://app.travis-ci.com/github/ckeditor/ckeditor5)
6
+ [![CircleCI](https://circleci.com/gh/ckeditor/ckeditor5.svg?style=shield)](https://app.circleci.com/pipelines/github/ckeditor/ckeditor5?branch=master)
7
7
 
8
8
  Various utilities used by CKEditor 5 and its features. This is a sort of CKEditor 5's standard library.
9
9
 
10
- ## Documentation
11
-
12
- See the [`@ckeditor/ckeditor5-utils` package](https://ckeditor.com/docs/ckeditor5/latest/api/utils.html) page in [CKEditor 5 documentation](https://ckeditor.com/docs/ckeditor5/latest/).
13
-
14
10
  ## Installation
15
11
 
12
+ This plugin is part of the `ckeditor5` package. Install the whole package to use it.
13
+
16
14
  ```bash
17
15
  npm install ckeditor5
18
16
  ```
19
17
 
18
+ ## Create free account
19
+
20
+ If you want to check full CKEditor 5 capabilities, sign up for a [free non-commitment 14-day trial](https://portal.ckeditor.com/signup).
21
+
22
+ ## Documentation
23
+
24
+ See the [`@ckeditor/ckeditor5-utils` package](https://ckeditor.com/docs/ckeditor5/latest/api/utils.html) page in [CKEditor 5 documentation](https://ckeditor.com/docs/ckeditor5/latest/).
25
+
20
26
  ## License
21
27
 
22
28
  Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html). For full details about the license, please check the `LICENSE.md` file or [https://ckeditor.com/legal/ckeditor-oss-license](https://ckeditor.com/legal/ckeditor-oss-license).
@@ -0,0 +1,30 @@
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
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
7
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
8
+ */
9
+ /**
10
+ * Calculates CRC-32 checksum for a given inputData to verify the integrity of data.
11
+ *
12
+ * @param inputData Accepts a single value (string, number, boolean), an array of strings, or an array of all of the above types.
13
+ * Non-string values are converted to strings before calculating the checksum.
14
+ * The checksum calculation is based on the concatenated string representation of the input values:
15
+ * * `crc32('foo')` is equivalent to `crc32(['foo'])`
16
+ * * `crc32(123)` is equivalent to `crc32(['123'])`
17
+ * * `crc32(true)` is equivalent to `crc32(['true'])`
18
+ * * `crc32(['foo', 123, true])` produces the same result as `crc32('foo123true')`
19
+ * * Nested arrays of strings are flattened, so `crc32([['foo', 'bar'], 'baz'])` is equivalent to `crc32(['foobar', 'baz'])`
20
+ *
21
+ * @returns The CRC-32 checksum, returned as a hexadecimal string.
22
+ */
23
+ export default function crc32(inputData: CRCData): string;
24
+ /**
25
+ * The input data for the CRC-32 checksum calculation.
26
+ * Can be a single value (string, number, boolean), an array of strings, or an array of all of the above types.
27
+ */
28
+ export type CRCData = CRCValue | Array<CRCValue>;
29
+ type CRCValue = string | number | boolean | Array<string>;
30
+ export {};
package/dist/index.d.ts CHANGED
@@ -63,7 +63,8 @@ export { default as insertToPriorityArray } from './inserttopriorityarray.js';
63
63
  export { default as spliceArray } from './splicearray.js';
64
64
  export { default as uid } from './uid.js';
65
65
  export { default as delay, type DelayedFunc } from './delay.js';
66
- export { default as verifyLicense } from './verifylicense.js';
67
66
  export { default as wait } from './wait.js';
67
+ export { default as parseBase64EncodedObject } from './parsebase64encodedobject.js';
68
+ export { default as crc32, type CRCData } from './crc32.js';
68
69
  export * from './unicode.js';
69
70
  export { default as version, releaseDate } from './version.js';
package/dist/index.js CHANGED
@@ -768,13 +768,19 @@ diff.fastDiff = fastDiff;
768
768
  * @param objectToInsert Object with `priority` property.
769
769
  */ function insertToPriorityArray(objects, objectToInsert) {
770
770
  const priority = priorities.get(objectToInsert.priority);
771
- for(let i = 0; i < objects.length; i++){
772
- if (priorities.get(objects[i].priority) < priority) {
773
- objects.splice(i, 0, objectToInsert);
774
- return;
771
+ // Binary search for better performance in large tables.
772
+ let left = 0;
773
+ let right = objects.length;
774
+ while(left < right){
775
+ const mid = left + right >> 1; // Use bitwise operator for faster floor division by 2.
776
+ const midPriority = priorities.get(objects[mid].priority);
777
+ if (midPriority < priority) {
778
+ right = mid;
779
+ } else {
780
+ left = mid + 1;
775
781
  }
776
782
  }
777
- objects.push(objectToInsert);
783
+ objects.splice(left, 0, objectToInsert);
778
784
  }
779
785
 
780
786
  /**
@@ -953,9 +959,9 @@ diff.fastDiff = fastDiff;
953
959
  ];
954
960
  }
955
961
 
956
- const version = '43.3.1';
962
+ const version = '44.0.0-alpha.0';
957
963
  // The second argument is not a month. It is `monthIndex` and starts from `0`.
958
- const releaseDate = new Date(2024, 10, 6);
964
+ const releaseDate = new Date(2024, 10, 20);
959
965
  /* istanbul ignore next -- @preserve */ if (globalThis.CKEDITOR_VERSION) {
960
966
  /**
961
967
  * This error is thrown when, due to a mistake in the way CKEditor&nbsp;5 was installed,
@@ -3973,7 +3979,22 @@ const rectProperties = [
3973
3979
  });
3974
3980
  // Obtain the rect of the target after it has been scrolled within its ancestors.
3975
3981
  // It's time to scroll the viewport.
3976
- const targetRect = getRectRelativeToWindow(target, currentWindow);
3982
+ let targetRect = getRectRelativeToWindow(target, currentWindow);
3983
+ // Detect situation where the target is higher than the first scrollable ancestor.
3984
+ // In such case scrolling the viewport to reveal the target might be malfunctioning because
3985
+ // the target `.top` position is lower than the ancestor's `.top` position. If it's large enough it can be negative.
3986
+ // It causes the `scrollWindowToShowRect` to scroll the viewport to the negative top position which is not possible
3987
+ // and leads to the viewport being scrolled to the absolute top of the document. To prevent this, the target's rect
3988
+ // must be shifted to the ancestor's top position. It should not affect the target's visibility because the ancestor
3989
+ // is already scrolled to reveal the target.
3990
+ // See more: https://github.com/ckeditor/ckeditor5/issues/17079
3991
+ const ancestorWindowRelativeRect = getRectRelativeToWindow(firstAncestorToScroll, currentWindow);
3992
+ if (targetRect.height > ancestorWindowRelativeRect.height) {
3993
+ const ancestorTargetIntersection = targetRect.getIntersection(ancestorWindowRelativeRect);
3994
+ if (ancestorTargetIntersection) {
3995
+ targetRect = ancestorTargetIntersection;
3996
+ }
3997
+ }
3977
3998
  scrollWindowToShowRect({
3978
3999
  window: currentWindow,
3979
4000
  rect: targetRect,
@@ -5924,77 +5945,81 @@ function isFocusedView(subTreeRoot, view) {
5924
5945
  }
5925
5946
 
5926
5947
  /**
5927
- * Checks whether the given string contains information that allows you to verify the license status.
5928
- *
5929
- * @param token The string to check.
5930
- * @returns String that represents the state of given `token` parameter.
5931
- */ function verifyLicense(token) {
5932
- // This function implements naive and partial license key check mechanism,
5933
- // used only to decide whether to show or hide the "Powered by CKEditor" logo.
5934
- //
5935
- // You can read the reasoning behind showing the logo to unlicensed (GPL) users
5936
- // in this thread: https://github.com/ckeditor/ckeditor5/issues/14082.
5937
- //
5938
- // We firmly believe in the values behind creating open-source software, even when that
5939
- // means keeping the license verification logic open for everyone to see.
5940
- //
5941
- // Please keep this code intact. Thank you for your understanding.
5942
- function oldTokenCheck(token) {
5943
- if (token.length >= 40 && token.length <= 255) {
5944
- return 'VALID';
5945
- } else {
5946
- return 'INVALID';
5947
- }
5948
- }
5949
- // TODO: issue ci#3175
5950
- if (!token) {
5951
- return 'INVALID';
5952
- }
5953
- let decryptedData = '';
5948
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
5949
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
5950
+ */ /**
5951
+ * @module utils/parsebase64encodedobject
5952
+ */ /**
5953
+ * Parses a base64-encoded object and returns the decoded object, or null if the decoding was unsuccessful.
5954
+ */ function parseBase64EncodedObject(encoded) {
5954
5955
  try {
5955
- decryptedData = atob(token);
5956
+ if (!encoded.startsWith('ey')) {
5957
+ return null;
5958
+ }
5959
+ const decoded = atob(encoded.replace(/-/g, '+').replace(/_/g, '/'));
5960
+ return JSON.parse(decoded);
5956
5961
  } catch (e) {
5957
- return 'INVALID';
5958
- }
5959
- const splittedDecryptedData = decryptedData.split('-');
5960
- const firstElement = splittedDecryptedData[0];
5961
- const secondElement = splittedDecryptedData[1];
5962
- if (!secondElement) {
5963
- return oldTokenCheck(token);
5962
+ return null;
5964
5963
  }
5965
- try {
5966
- atob(secondElement);
5967
- } catch (e) {
5968
- try {
5969
- atob(firstElement);
5970
- if (!atob(firstElement).length) {
5971
- return oldTokenCheck(token);
5964
+ }
5965
+
5966
+ /**
5967
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
5968
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
5969
+ */ /**
5970
+ * @module utils/crc32
5971
+ */ /**
5972
+ * Generates a CRC lookup table.
5973
+ * This function creates and returns a 256-element array of pre-computed CRC values for quick CRC calculation.
5974
+ * It uses the polynomial 0xEDB88320 to compute each value in the loop, optimizing future CRC calculations.
5975
+ */ function makeCrcTable() {
5976
+ const crcTable = [];
5977
+ for(let n = 0; n < 256; n++){
5978
+ let c = n;
5979
+ for(let k = 0; k < 8; k++){
5980
+ if (c & 1) {
5981
+ c = 0xEDB88320 ^ c >>> 1;
5982
+ } else {
5983
+ c = c >>> 1;
5972
5984
  }
5973
- } catch (e) {
5974
- return oldTokenCheck(token);
5975
5985
  }
5986
+ crcTable[n] = c;
5976
5987
  }
5977
- if (firstElement.length < 40 || firstElement.length > 255) {
5978
- return 'INVALID';
5979
- }
5980
- let decryptedSecondElement = '';
5981
- try {
5982
- atob(firstElement);
5983
- decryptedSecondElement = atob(secondElement);
5984
- } catch (e) {
5985
- return 'INVALID';
5986
- }
5987
- if (decryptedSecondElement.length !== 8) {
5988
- return 'INVALID';
5989
- }
5990
- const year = Number(decryptedSecondElement.substring(0, 4));
5991
- const monthIndex = Number(decryptedSecondElement.substring(4, 6)) - 1;
5992
- const day = Number(decryptedSecondElement.substring(6, 8));
5993
- const date = new Date(year, monthIndex, day);
5994
- if (date < releaseDate || isNaN(Number(date))) {
5995
- return 'INVALID';
5988
+ return crcTable;
5989
+ }
5990
+ /**
5991
+ * Calculates CRC-32 checksum for a given inputData to verify the integrity of data.
5992
+ *
5993
+ * @param inputData Accepts a single value (string, number, boolean), an array of strings, or an array of all of the above types.
5994
+ * Non-string values are converted to strings before calculating the checksum.
5995
+ * The checksum calculation is based on the concatenated string representation of the input values:
5996
+ * * `crc32('foo')` is equivalent to `crc32(['foo'])`
5997
+ * * `crc32(123)` is equivalent to `crc32(['123'])`
5998
+ * * `crc32(true)` is equivalent to `crc32(['true'])`
5999
+ * * `crc32(['foo', 123, true])` produces the same result as `crc32('foo123true')`
6000
+ * * Nested arrays of strings are flattened, so `crc32([['foo', 'bar'], 'baz'])` is equivalent to `crc32(['foobar', 'baz'])`
6001
+ *
6002
+ * @returns The CRC-32 checksum, returned as a hexadecimal string.
6003
+ */ function crc32(inputData) {
6004
+ const dataArray = Array.isArray(inputData) ? inputData : [
6005
+ inputData
6006
+ ];
6007
+ const crcTable = makeCrcTable();
6008
+ let crc = 0 ^ -1;
6009
+ // Convert data to a single string.
6010
+ const dataString = dataArray.map((item)=>{
6011
+ if (Array.isArray(item)) {
6012
+ return item.join('');
6013
+ }
6014
+ return String(item);
6015
+ }).join('');
6016
+ // Calculate the CRC for the resulting string.
6017
+ for(let i = 0; i < dataString.length; i++){
6018
+ const byte = dataString.charCodeAt(i);
6019
+ crc = crc >>> 8 ^ crcTable[(crc ^ byte) & 0xFF];
5996
6020
  }
5997
- return 'VALID';
6021
+ crc = (crc ^ -1) >>> 0; // Force unsigned integer.
6022
+ return crc.toString(16).padStart(8, '0');
5998
6023
  }
5999
6024
 
6000
6025
  /**
@@ -6075,5 +6100,5 @@ function buildEmojiRegexp() {
6075
6100
  return new RegExp(sequence, 'ug');
6076
6101
  }
6077
6102
 
6078
- export { CKEditorError, Collection, Config, DomEmitterMixin, ElementReplacer, EmitterMixin, EventInfo, FocusTracker, KeystrokeHandler, Locale, ObservableMixin, Rect, ResizeObserver, abortableDebounce, compareArrays, count, createElement, delay, diff, diffToChanges, env, exponentialDelay, fastDiff, findClosestScrollableAncestor, first, getAncestors, getBorderWidths, getCode, getDataFromElement, getEnvKeystrokeText, getLanguageDirection, getLocalizedArrowKeyCodeDirection, getOptimalPosition, getRangeFromMouseEvent, global, indexOf, insertAt, insertToPriorityArray, isArrowKeyCode, isCombiningMark, isComment, isForwardArrowKeyCode, isHighSurrogateHalf, isInsideCombinedSymbol, isInsideEmojiSequence, isInsideSurrogatePair, isIterable, isLowSurrogateHalf, isNode, isRange, isText, isValidAttributeName, isViewWithFocusTracker, isVisible, keyCodes, logError, logWarning, mix, parseKeystroke, priorities, releaseDate, remove, retry, scrollAncestorsToShowTarget, scrollViewportToShowTarget, setDataInElement, spliceArray, toArray, toMap, toUnit, uid, verifyLicense, version, wait };
6103
+ export { CKEditorError, Collection, Config, DomEmitterMixin, ElementReplacer, EmitterMixin, EventInfo, FocusTracker, KeystrokeHandler, Locale, ObservableMixin, Rect, ResizeObserver, abortableDebounce, compareArrays, count, crc32, createElement, delay, diff, diffToChanges, env, exponentialDelay, fastDiff, findClosestScrollableAncestor, first, getAncestors, getBorderWidths, getCode, getDataFromElement, getEnvKeystrokeText, getLanguageDirection, getLocalizedArrowKeyCodeDirection, getOptimalPosition, getRangeFromMouseEvent, global, indexOf, insertAt, insertToPriorityArray, isArrowKeyCode, isCombiningMark, isComment, isForwardArrowKeyCode, isHighSurrogateHalf, isInsideCombinedSymbol, isInsideEmojiSequence, isInsideSurrogatePair, isIterable, isLowSurrogateHalf, isNode, isRange, isText, isValidAttributeName, isViewWithFocusTracker, isVisible, keyCodes, logError, logWarning, mix, parseBase64EncodedObject, parseKeystroke, priorities, releaseDate, remove, retry, scrollAncestorsToShowTarget, scrollViewportToShowTarget, setDataInElement, spliceArray, toArray, toMap, toUnit, uid, version, wait };
6079
6104
  //# sourceMappingURL=index.js.map