@ckeditor/ckeditor5-utils 45.1.0 → 45.2.0-alpha.1

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/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { isObject, isString, isPlainObject, cloneDeepWith, isElement as isElemen
7
7
  /**
8
8
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
9
9
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
10
- */ /* globals window, document */ /**
10
+ */ /**
11
11
  * @module utils/dom/global
12
12
  */ // This interface exists to make our API pages more readable.
13
13
  /**
@@ -34,7 +34,7 @@ try {
34
34
  window,
35
35
  document
36
36
  };
37
- } catch (e) {
37
+ } catch {
38
38
  // It's not possible to mock a window object to simulate lack of a window object without writing extremely convoluted code.
39
39
  /* istanbul ignore next -- @preserve */ // Let's cast it to not change module's API.
40
40
  // We only handle this so loading editor in environments without window and document doesn't fail.
@@ -54,7 +54,7 @@ var global = globalVar;
54
54
  // In some environments navigator API might not be available.
55
55
  try {
56
56
  return navigator.userAgent.toLowerCase();
57
- } catch (e) {
57
+ } catch {
58
58
  return '';
59
59
  }
60
60
  }
@@ -149,7 +149,7 @@ const userAgent = /* #__PURE__ */ getUserAgent();
149
149
  try {
150
150
  // Usage of regular expression literal cause error during build (ckeditor/ckeditor5-dev#534).
151
151
  isSupported = 'ć'.search(new RegExp('[\\p{L}]', 'u')) === 0;
152
- } catch (error) {
152
+ } catch {
153
153
  // Firefox throws a SyntaxError when the group is unsupported.
154
154
  }
155
155
  return isSupported;
@@ -788,7 +788,7 @@ diff.fastDiff = fastDiff;
788
788
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
789
789
  */ /**
790
790
  * @module utils/ckeditorerror
791
- */ /* globals console */ /**
791
+ */ /**
792
792
  * URL to the documentation with error codes.
793
793
  */ const DOCUMENTATION_URL = 'https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html';
794
794
  /**
@@ -959,9 +959,9 @@ diff.fastDiff = fastDiff;
959
959
  ];
960
960
  }
961
961
 
962
- const version = '45.1.0';
962
+ const version = '45.2.0-alpha.1';
963
963
  // The second argument is not a month. It is `monthIndex` and starts from `0`.
964
- const releaseDate = new Date(2025, 4, 14);
964
+ const releaseDate = new Date(2025, 4, 29);
965
965
  /* istanbul ignore next -- @preserve */ if (globalThis.CKEDITOR_VERSION) {
966
966
  /**
967
967
  * This error is thrown when, due to a mistake in the way CKEditor 5 was installed,
@@ -2758,7 +2758,7 @@ function DomEmitterMixin(base) {
2758
2758
  /**
2759
2759
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
2760
2760
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
2761
- */ /* globals Node */ /**
2761
+ */ /**
2762
2762
  * @module utils/dom/getancestors
2763
2763
  */ /**
2764
2764
  * Returns all ancestors of given DOM node, starting from the top-most (root). Includes the given node itself. If the
@@ -2782,7 +2782,7 @@ function DomEmitterMixin(base) {
2782
2782
  /**
2783
2783
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
2784
2784
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
2785
- */ /* globals HTMLTextAreaElement */ /**
2785
+ */ /**
2786
2786
  * @module utils/dom/getdatafromelement
2787
2787
  */ /**
2788
2788
  * Gets data from a given source element.
@@ -3471,7 +3471,7 @@ const rectProperties = [
3471
3471
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
3472
3472
  */ /**
3473
3473
  * @module utils/dom/setdatainelement
3474
- */ /* globals HTMLTextAreaElement */ /**
3474
+ */ /**
3475
3475
  * Sets data in a given element.
3476
3476
  *
3477
3477
  * @param el The element in which the data will be set.
@@ -3534,7 +3534,7 @@ const rectProperties = [
3534
3534
  /**
3535
3535
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
3536
3536
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
3537
- */ /* globals Node */ /**
3537
+ */ /**
3538
3538
  * @module utils/dom/iscomment
3539
3539
  */ /**
3540
3540
  * Checks whether the object is a native DOM Comment node.
@@ -3549,7 +3549,7 @@ const rectProperties = [
3549
3549
  */ function isValidAttributeName(name) {
3550
3550
  try {
3551
3551
  global.document.createAttribute(name);
3552
- } catch (error) {
3552
+ } catch {
3553
3553
  return false;
3554
3554
  }
3555
3555
  return true;
@@ -6037,7 +6037,7 @@ function isFocusedView(subTreeRoot, view) {
6037
6037
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
6038
6038
  */ /**
6039
6039
  * @module utils/delay
6040
- */ /* globals setTimeout, clearTimeout */ /**
6040
+ */ /**
6041
6041
  * Returns a function wrapper that will trigger a function after a specified wait time.
6042
6042
  * The timeout can be canceled by calling the cancel function on the returned wrapped function.
6043
6043
  *
@@ -6069,7 +6069,7 @@ function isFocusedView(subTreeRoot, view) {
6069
6069
  }
6070
6070
  const decoded = atob(encoded.replace(/-/g, '+').replace(/_/g, '/'));
6071
6071
  return JSON.parse(decoded);
6072
- } catch (e) {
6072
+ } catch {
6073
6073
  return null;
6074
6074
  }
6075
6075
  }
@@ -6183,6 +6183,265 @@ function isFocusedView(subTreeRoot, view) {
6183
6183
  ].join(' ').trim();
6184
6184
  }
6185
6185
 
6186
+ /**
6187
+ * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
6188
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
6189
+ */ /**
6190
+ * @module utils/formathtml
6191
+ */ /**
6192
+ * A simple (and naive) HTML code formatter that returns a formatted HTML markup that can be easily
6193
+ * parsed by human eyes. It beautifies the HTML code by adding new lines between elements that behave like block elements
6194
+ * (https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
6195
+ * and a few more like `tr`, `td`, and similar ones) and inserting indents for nested content.
6196
+ *
6197
+ * WARNING: This function works only on a text that does not contain any indentations or new lines.
6198
+ * Calling this function on the already formatted text will damage the formatting.
6199
+ *
6200
+ * @param input An HTML string to format.
6201
+ */ function formatHtml(input) {
6202
+ // A list of block-like elements around which the new lines should be inserted, and within which
6203
+ // the indentation of their children should be increased.
6204
+ // The list is partially based on https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements that contains
6205
+ // a full list of HTML block-level elements.
6206
+ // A void element is an element that cannot have any child - https://html.spec.whatwg.org/multipage/syntax.html#void-elements.
6207
+ // Note that <pre> element is not listed on this list to avoid breaking whitespace formatting.
6208
+ // Note that <br> element is not listed and handled separately so no additional white spaces are injected.
6209
+ const elementsToFormat = [
6210
+ {
6211
+ name: 'address',
6212
+ isVoid: false
6213
+ },
6214
+ {
6215
+ name: 'article',
6216
+ isVoid: false
6217
+ },
6218
+ {
6219
+ name: 'aside',
6220
+ isVoid: false
6221
+ },
6222
+ {
6223
+ name: 'blockquote',
6224
+ isVoid: false
6225
+ },
6226
+ {
6227
+ name: 'details',
6228
+ isVoid: false
6229
+ },
6230
+ {
6231
+ name: 'dialog',
6232
+ isVoid: false
6233
+ },
6234
+ {
6235
+ name: 'dd',
6236
+ isVoid: false
6237
+ },
6238
+ {
6239
+ name: 'div',
6240
+ isVoid: false
6241
+ },
6242
+ {
6243
+ name: 'dl',
6244
+ isVoid: false
6245
+ },
6246
+ {
6247
+ name: 'dt',
6248
+ isVoid: false
6249
+ },
6250
+ {
6251
+ name: 'fieldset',
6252
+ isVoid: false
6253
+ },
6254
+ {
6255
+ name: 'figcaption',
6256
+ isVoid: false
6257
+ },
6258
+ {
6259
+ name: 'figure',
6260
+ isVoid: false
6261
+ },
6262
+ {
6263
+ name: 'footer',
6264
+ isVoid: false
6265
+ },
6266
+ {
6267
+ name: 'form',
6268
+ isVoid: false
6269
+ },
6270
+ {
6271
+ name: 'h1',
6272
+ isVoid: false
6273
+ },
6274
+ {
6275
+ name: 'h2',
6276
+ isVoid: false
6277
+ },
6278
+ {
6279
+ name: 'h3',
6280
+ isVoid: false
6281
+ },
6282
+ {
6283
+ name: 'h4',
6284
+ isVoid: false
6285
+ },
6286
+ {
6287
+ name: 'h5',
6288
+ isVoid: false
6289
+ },
6290
+ {
6291
+ name: 'h6',
6292
+ isVoid: false
6293
+ },
6294
+ {
6295
+ name: 'header',
6296
+ isVoid: false
6297
+ },
6298
+ {
6299
+ name: 'hgroup',
6300
+ isVoid: false
6301
+ },
6302
+ {
6303
+ name: 'hr',
6304
+ isVoid: true
6305
+ },
6306
+ {
6307
+ name: 'li',
6308
+ isVoid: false
6309
+ },
6310
+ {
6311
+ name: 'main',
6312
+ isVoid: false
6313
+ },
6314
+ {
6315
+ name: 'nav',
6316
+ isVoid: false
6317
+ },
6318
+ {
6319
+ name: 'ol',
6320
+ isVoid: false
6321
+ },
6322
+ {
6323
+ name: 'p',
6324
+ isVoid: false
6325
+ },
6326
+ {
6327
+ name: 'section',
6328
+ isVoid: false
6329
+ },
6330
+ {
6331
+ name: 'table',
6332
+ isVoid: false
6333
+ },
6334
+ {
6335
+ name: 'tbody',
6336
+ isVoid: false
6337
+ },
6338
+ {
6339
+ name: 'td',
6340
+ isVoid: false
6341
+ },
6342
+ {
6343
+ name: 'th',
6344
+ isVoid: false
6345
+ },
6346
+ {
6347
+ name: 'thead',
6348
+ isVoid: false
6349
+ },
6350
+ {
6351
+ name: 'tr',
6352
+ isVoid: false
6353
+ },
6354
+ {
6355
+ name: 'ul',
6356
+ isVoid: false
6357
+ }
6358
+ ];
6359
+ const elementNamesToFormat = elementsToFormat.map((element)=>element.name).join('|');
6360
+ // It is not the fastest way to format the HTML markup but the performance should be good enough.
6361
+ const lines = input// Add new line before and after `<tag>` and `</tag>`.
6362
+ // It may separate individual elements with two new lines, but this will be fixed below.
6363
+ .replace(new RegExp(`</?(${elementNamesToFormat})( .*?)?>`, 'g'), '\n$&\n')// Keep `<br>`s at the end of line to avoid adding additional whitespaces before `<br>`.
6364
+ .replace(/<br[^>]*>/g, '$&\n')// Divide input string into lines, which start with either an opening tag, a closing tag, or just a text.
6365
+ .split('\n');
6366
+ let indentCount = 0;
6367
+ let isPreformattedLine = false;
6368
+ return lines.map((line)=>{
6369
+ isPreformattedLine = isPreformattedBlockLine(line, isPreformattedLine);
6370
+ // Ignore empty lines outside a <pre> block.
6371
+ if (!line.length && !isPreformattedLine) {
6372
+ return '';
6373
+ }
6374
+ if (isNonVoidOpeningTag(line, elementsToFormat)) {
6375
+ return indentLine(line, indentCount++);
6376
+ }
6377
+ if (isClosingTag(line, elementsToFormat)) {
6378
+ return indentLine(line, --indentCount);
6379
+ }
6380
+ if (isPreformattedLine === 'middle' || isPreformattedLine === 'last') {
6381
+ return indentLine(line, 0);
6382
+ }
6383
+ return indentLine(line, indentCount);
6384
+ }).join('').trimEnd();
6385
+ }
6386
+ /**
6387
+ * Checks, if an argument is an opening tag of a non-void element to be formatted.
6388
+ *
6389
+ * @param line String to check.
6390
+ * @param elementsToFormat Elements to be formatted.
6391
+ */ function isNonVoidOpeningTag(line, elementsToFormat) {
6392
+ return elementsToFormat.some((element)=>{
6393
+ if (element.isVoid) {
6394
+ return false;
6395
+ }
6396
+ if (!new RegExp(`<${element.name}( .*?)?>`).test(line)) {
6397
+ return false;
6398
+ }
6399
+ return true;
6400
+ });
6401
+ }
6402
+ /**
6403
+ * Checks, if an argument is a closing tag.
6404
+ *
6405
+ * @param line String to check.
6406
+ * @param elementsToFormat Elements to be formatted.
6407
+ */ function isClosingTag(line, elementsToFormat) {
6408
+ return elementsToFormat.some((element)=>{
6409
+ return new RegExp(`</${element.name}>`).test(line);
6410
+ });
6411
+ }
6412
+ /**
6413
+ * Indents a line by a specified number of characters.
6414
+ *
6415
+ * @param line Line to indent.
6416
+ * @param indentCount Number of characters to use for indentation.
6417
+ * @param indentChar Indentation character(s). 4 spaces by default.
6418
+ */ function indentLine(line, indentCount, indentChar = ' ') {
6419
+ // More about Math.max() here in https://github.com/ckeditor/ckeditor5/issues/10698.
6420
+ return `${indentChar.repeat(Math.max(0, indentCount))}${line}\n`;
6421
+ }
6422
+ /**
6423
+ * Checks whether a line belongs to a preformatted (`<pre>`) block.
6424
+ *
6425
+ * @param line Line to check.
6426
+ * @param isPreviousLinePreFormatted Information on whether the previous line was preformatted (and how).
6427
+ */ function isPreformattedBlockLine(line, isPreviousLinePreFormatted) {
6428
+ const isPreOpen = /<pre( .*?)?>/.test(line);
6429
+ const isPreClose = /<\/pre>/.test(line);
6430
+ if (isPreOpen && isPreClose) {
6431
+ // If both an opening and closing a <pre> tag, no special treatment needed.
6432
+ return false;
6433
+ } else if (isPreOpen) {
6434
+ return 'first';
6435
+ } else if (isPreClose) {
6436
+ return 'last';
6437
+ } else if (isPreviousLinePreFormatted === 'first' || isPreviousLinePreFormatted === 'middle') {
6438
+ // This line is just after a 'first' or 'middle' line of a multi-line pre-block.
6439
+ return 'middle';
6440
+ } else {
6441
+ return false;
6442
+ }
6443
+ }
6444
+
6186
6445
  /**
6187
6446
  * @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
6188
6447
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
@@ -6261,5 +6520,5 @@ function buildEmojiRegexp() {
6261
6520
  return new RegExp(sequence, 'ug');
6262
6521
  }
6263
6522
 
6264
- export { CKEditorError, Collection, Config, DomEmitterMixin, ElementReplacer, EmitterMixin, EventInfo, FocusTracker, KeystrokeHandler, Locale, ObservableMixin, Rect, ResizeObserver, abortableDebounce, add, collectStylesheets, compareArrays, count, crc32, createElement, delay, diff, diffToChanges, env, exponentialDelay, fastDiff, findClosestScrollableAncestor, first, getAncestors, getBorderWidths, getCode, getDataFromElement, getEnvKeystrokeText, getLanguageDirection, getLocalizedArrowKeyCodeDirection, getOptimalPosition, getRangeFromMouseEvent, getVisualViewportOffset, 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 };
6523
+ export { CKEditorError, Collection, Config, DomEmitterMixin, ElementReplacer, EmitterMixin, EventInfo, FocusTracker, KeystrokeHandler, Locale, ObservableMixin, Rect, ResizeObserver, abortableDebounce, add, collectStylesheets, compareArrays, count, crc32, createElement, delay, diff, diffToChanges, env, exponentialDelay, fastDiff, findClosestScrollableAncestor, first, formatHtml, getAncestors, getBorderWidths, getCode, getDataFromElement, getEnvKeystrokeText, getLanguageDirection, getLocalizedArrowKeyCodeDirection, getOptimalPosition, getRangeFromMouseEvent, getVisualViewportOffset, 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 };
6265
6524
  //# sourceMappingURL=index.js.map