tinymce-rails 8.3.2 → 8.5.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/source/tinymce/tinymce.js +421 -257
  3. data/lib/tinymce/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/tinymce/icons/default/icons.js +1 -1
  5. data/vendor/assets/javascripts/tinymce/models/dom/model.js +1 -1
  6. data/vendor/assets/javascripts/tinymce/notices.txt +1 -1
  7. data/vendor/assets/javascripts/tinymce/plugins/accordion/plugin.js +1 -1
  8. data/vendor/assets/javascripts/tinymce/plugins/advlist/plugin.js +1 -1
  9. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.js +1 -1
  10. data/vendor/assets/javascripts/tinymce/plugins/autolink/plugin.js +1 -1
  11. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.js +1 -1
  12. data/vendor/assets/javascripts/tinymce/plugins/autosave/plugin.js +1 -1
  13. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.js +1 -1
  14. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.js +1 -1
  15. data/vendor/assets/javascripts/tinymce/plugins/codesample/plugin.js +2 -2
  16. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.js +1 -1
  17. data/vendor/assets/javascripts/tinymce/plugins/emoticons/plugin.js +1 -1
  18. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.js +1 -1
  19. data/vendor/assets/javascripts/tinymce/plugins/help/plugin.js +1 -1
  20. data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +1 -1
  21. data/vendor/assets/javascripts/tinymce/plugins/importcss/plugin.js +1 -1
  22. data/vendor/assets/javascripts/tinymce/plugins/insertdatetime/plugin.js +1 -1
  23. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.js +1 -1
  24. data/vendor/assets/javascripts/tinymce/plugins/lists/plugin.js +1 -1
  25. data/vendor/assets/javascripts/tinymce/plugins/media/plugin.js +1 -1
  26. data/vendor/assets/javascripts/tinymce/plugins/nonbreaking/plugin.js +1 -1
  27. data/vendor/assets/javascripts/tinymce/plugins/pagebreak/plugin.js +1 -1
  28. data/vendor/assets/javascripts/tinymce/plugins/preview/plugin.js +1 -1
  29. data/vendor/assets/javascripts/tinymce/plugins/quickbars/plugin.js +1 -1
  30. data/vendor/assets/javascripts/tinymce/plugins/save/plugin.js +1 -1
  31. data/vendor/assets/javascripts/tinymce/plugins/searchreplace/plugin.js +1 -1
  32. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
  33. data/vendor/assets/javascripts/tinymce/plugins/visualblocks/plugin.js +1 -1
  34. data/vendor/assets/javascripts/tinymce/plugins/visualchars/plugin.js +1 -1
  35. data/vendor/assets/javascripts/tinymce/plugins/wordcount/plugin.js +1 -1
  36. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.css +1 -1
  37. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.css +1 -1
  38. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.js +1 -1
  39. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.min.css +1 -1
  40. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.js +1 -1
  41. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.min.css +1 -1
  42. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.css +1 -1
  43. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.js +1 -1
  44. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.min.css +1 -1
  45. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.css +1 -1
  46. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.css +1 -1
  47. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.js +1 -1
  48. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.min.css +1 -1
  49. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.js +1 -1
  50. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.min.css +1 -1
  51. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.css +1 -1
  52. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.js +1 -1
  53. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.min.css +1 -1
  54. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.css +1 -1
  55. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.css +1 -1
  56. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.js +1 -1
  57. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.min.css +1 -1
  58. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.js +1 -1
  59. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.min.css +1 -1
  60. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.css +1 -1
  61. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.js +1 -1
  62. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.min.css +1 -1
  63. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.css +1 -1
  64. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.css +1 -1
  65. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.js +1 -1
  66. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css +1 -1
  67. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.js +1 -1
  68. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.min.css +1 -1
  69. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.css +1 -1
  70. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.js +1 -1
  71. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.min.css +1 -1
  72. data/vendor/assets/javascripts/tinymce/themes/silver/theme.js +1 -1
  73. data/vendor/assets/javascripts/tinymce/tinymce.d.ts +7 -0
  74. data/vendor/assets/javascripts/tinymce/tinymce.js +3 -3
  75. metadata +2 -2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * TinyMCE version 8.3.2 (2026-01-14)
2
+ * TinyMCE version 8.5.0 (2026-04-29)
3
3
  */
4
4
 
5
5
  (function () {
@@ -625,9 +625,9 @@
625
625
  copy.sort(comparator);
626
626
  return copy;
627
627
  };
628
- const get$b = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
629
- const head = (xs) => get$b(xs, 0);
630
- const last$2 = (xs) => get$b(xs, xs.length - 1);
628
+ const get$c = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
629
+ const head = (xs) => get$c(xs, 0);
630
+ const last$2 = (xs) => get$c(xs, xs.length - 1);
631
631
  const from = isFunction(Array.from) ? Array.from : (x) => nativeSlice.call(x);
632
632
  const findMap = (arr, f) => {
633
633
  for (let i = 0; i < arr.length; i++) {
@@ -709,7 +709,7 @@
709
709
  const values = (obj) => {
710
710
  return mapToArray(obj, identity);
711
711
  };
712
- const get$a = (obj, key) => {
712
+ const get$b = (obj, key) => {
713
713
  return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
714
714
  };
715
715
  const has$2 = (obj, key) => hasOwnProperty$1.call(obj, key);
@@ -2403,7 +2403,7 @@
2403
2403
  throw new Error('Attribute value was not simple');
2404
2404
  }
2405
2405
  };
2406
- const set$4 = (element, key, value) => {
2406
+ const set$5 = (element, key, value) => {
2407
2407
  rawSet(element.dom, key, value);
2408
2408
  };
2409
2409
  const setAll$1 = (element, attrs) => {
@@ -2412,12 +2412,12 @@
2412
2412
  rawSet(dom, k, v);
2413
2413
  });
2414
2414
  };
2415
- const get$9 = (element, key) => {
2415
+ const get$a = (element, key) => {
2416
2416
  const v = element.dom.getAttribute(key);
2417
2417
  // undefined is the more appropriate value for JS, and this matches JQuery
2418
2418
  return v === null ? undefined : v;
2419
2419
  };
2420
- const getOpt = (element, key) => Optional.from(get$9(element, key));
2420
+ const getOpt = (element, key) => Optional.from(get$a(element, key));
2421
2421
  const has$1 = (element, key) => {
2422
2422
  const dom = element.dom;
2423
2423
  // return false for non-element nodes, no point in throwing an error
@@ -2490,8 +2490,8 @@
2490
2490
  };
2491
2491
  const fromDom$1 = (nodes) => map$3(nodes, SugarElement.fromDom);
2492
2492
 
2493
- const get$8 = (element) => element.dom.innerHTML;
2494
- const set$3 = (element, content) => {
2493
+ const get$9 = (element) => element.dom.innerHTML;
2494
+ const set$4 = (element, content) => {
2495
2495
  const owner = owner$1(element);
2496
2496
  const docDom = owner.dom;
2497
2497
  // FireFox has *terrible* performance when using innerHTML = x
@@ -2505,7 +2505,7 @@
2505
2505
  const container = SugarElement.fromTag('div');
2506
2506
  const clone = SugarElement.fromDom(element.dom.cloneNode(true));
2507
2507
  append$1(container, clone);
2508
- return get$8(container);
2508
+ return get$9(container);
2509
2509
  };
2510
2510
 
2511
2511
  // some elements, such as mathml, don't have style attributes
@@ -2552,7 +2552,7 @@
2552
2552
  dom.style.removeProperty(property);
2553
2553
  }
2554
2554
  };
2555
- const set$2 = (element, property, value) => {
2555
+ const set$3 = (element, property, value) => {
2556
2556
  const dom = element.dom;
2557
2557
  internalSet(dom, property, value);
2558
2558
  };
@@ -2568,7 +2568,7 @@
2568
2568
  *
2569
2569
  * https://developer.mozilla.org/en-US/docs/Web/CSS/used_value
2570
2570
  */
2571
- const get$7 = (element, property) => {
2571
+ const get$8 = (element, property) => {
2572
2572
  const dom = element.dom;
2573
2573
  /*
2574
2574
  * IE9 and above per
@@ -2667,7 +2667,7 @@
2667
2667
  const r = getOffset(element);
2668
2668
  // zero or null means non-standard or disconnected, fall back to CSS
2669
2669
  if (r <= 0 || r === null) {
2670
- const css = get$7(element, name);
2670
+ const css = get$8(element, name);
2671
2671
  // ugh this feels dirty, but it saves cycles
2672
2672
  return parseFloat(css) || 0;
2673
2673
  }
@@ -2677,7 +2677,7 @@
2677
2677
  // although these calculations only seem relevant for quirks mode, and edge cases TBIO doesn't rely on
2678
2678
  const getOuter = get;
2679
2679
  const aggregate = (element, properties) => foldl(properties, (acc, property) => {
2680
- const val = get$7(element, property);
2680
+ const val = get$8(element, property);
2681
2681
  const value = val === undefined ? 0 : parseInt(val, 10);
2682
2682
  return isNaN(value) ? acc : acc + value;
2683
2683
  }, 0);
@@ -2701,7 +2701,7 @@
2701
2701
  const dom = element.dom;
2702
2702
  return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
2703
2703
  });
2704
- const get$6 = (element) => api$1.get(element);
2704
+ const get$7 = (element) => api$1.get(element);
2705
2705
 
2706
2706
  const r = (left, top) => {
2707
2707
  const translate = (x, y) => r(left + x, top + y);
@@ -2755,7 +2755,7 @@
2755
2755
  };
2756
2756
 
2757
2757
  // get scroll position (x,y) relative to document _doc (or global if not supplied)
2758
- const get$5 = (_DOC) => {
2758
+ const get$6 = (_DOC) => {
2759
2759
  const doc = _DOC !== undefined ? _DOC.dom : document;
2760
2760
  // ASSUMPTION: This is for cross-browser support, body works for Safari & EDGE, and when we have an iframe body scroller
2761
2761
  const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
@@ -2813,25 +2813,25 @@
2813
2813
  };
2814
2814
 
2815
2815
  const api = NodeValue(isText$c, 'text');
2816
- const get$4 = (element) => api.get(element);
2816
+ const get$5 = (element) => api.get(element);
2817
2817
  const getOption = (element) => api.getOption(element);
2818
- const set$1 = (element, value) => api.set(element, value);
2818
+ const set$2 = (element, value) => api.set(element, value);
2819
2819
 
2820
2820
  // Methods for handling attributes that contain a list of values <div foo="alpha beta theta">
2821
2821
  const read$4 = (element, attr) => {
2822
- const value = get$9(element, attr);
2822
+ const value = get$a(element, attr);
2823
2823
  return value === undefined || value === '' ? [] : value.split(' ');
2824
2824
  };
2825
2825
  const add$4 = (element, attr, id) => {
2826
2826
  const old = read$4(element, attr);
2827
2827
  const nu = old.concat([id]);
2828
- set$4(element, attr, nu.join(' '));
2828
+ set$5(element, attr, nu.join(' '));
2829
2829
  return true;
2830
2830
  };
2831
2831
  const remove$6 = (element, attr, id) => {
2832
2832
  const nu = filter$5(read$4(element, attr), (v) => v !== id);
2833
2833
  if (nu.length > 0) {
2834
- set$4(element, attr, nu.join(' '));
2834
+ set$5(element, attr, nu.join(' '));
2835
2835
  }
2836
2836
  else {
2837
2837
  remove$9(element, attr);
@@ -2911,11 +2911,11 @@
2911
2911
 
2912
2912
  // IE11 Can return undefined for a classList on elements such as math, so we make sure it's not undefined before attempting to use it.
2913
2913
  const supports = (element) => element.dom.classList !== undefined;
2914
- const get$3 = (element) => read$4(element, 'class');
2914
+ const get$4 = (element) => read$4(element, 'class');
2915
2915
  const add$3 = (element, clazz) => add$4(element, 'class', clazz);
2916
2916
  const remove$5 = (element, clazz) => remove$6(element, 'class', clazz);
2917
2917
  const toggle$2 = (element, clazz) => {
2918
- if (contains$2(get$3(element), clazz)) {
2918
+ if (contains$2(get$4(element), clazz)) {
2919
2919
  return remove$5(element, clazz);
2920
2920
  }
2921
2921
  else {
@@ -2939,7 +2939,7 @@
2939
2939
  }
2940
2940
  };
2941
2941
  const cleanClass = (element) => {
2942
- const classList = supports(element) ? element.dom.classList : get$3(element);
2942
+ const classList = supports(element) ? element.dom.classList : get$4(element);
2943
2943
  // classList is a "live list", so this is up to date already
2944
2944
  if (classList.length === 0) {
2945
2945
  // No more classes left, remove the class attribute as well
@@ -2989,10 +2989,15 @@
2989
2989
  }
2990
2990
  };
2991
2991
  const getRaw = (element) => element.dom.contentEditable;
2992
- const set = (element, editable) => {
2992
+ const set$1 = (element, editable) => {
2993
2993
  element.dom.contentEditable = editable ? 'true' : 'false';
2994
2994
  };
2995
2995
 
2996
+ const get$3 = (element) => element.dom.textContent;
2997
+ const set = (element, value) => {
2998
+ element.dom.textContent = value;
2999
+ };
3000
+
2996
3001
  const ancestors$1 = (scope, predicate, isRoot) => filter$5(parents$1(scope, isRoot), predicate);
2997
3002
  const children = (scope, predicate) => filter$5(children$1(scope), predicate);
2998
3003
  const descendants$1 = (scope, predicate) => {
@@ -3054,7 +3059,7 @@
3054
3059
  // For the purposes of finding cursor positions only allow text nodes with content,
3055
3060
  // but trim removes &nbsp; and that's allowed
3056
3061
  text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
3057
- const isContentEditableFalse$b = (elem) => isHTMLElement$1(elem) && (get$9(elem, 'contenteditable') === 'false');
3062
+ const isContentEditableFalse$b = (elem) => isHTMLElement$1(elem) && (get$a(elem, 'contenteditable') === 'false');
3058
3063
  const elementsWithCursorPosition = ['img', 'br'];
3059
3064
  const isCursorPosition = (elem) => {
3060
3065
  const hasCursorPosition = isTextNodeWithCursorPosition(elem);
@@ -3221,7 +3226,7 @@
3221
3226
  const getBounds = (_win) => {
3222
3227
  const win = _win === undefined ? window : _win;
3223
3228
  const doc = win.document;
3224
- const scroll = get$5(SugarElement.fromDom(doc));
3229
+ const scroll = get$6(SugarElement.fromDom(doc));
3225
3230
  return get$2(win).fold(() => {
3226
3231
  const html = win.document.documentElement;
3227
3232
  // Don't use window.innerWidth/innerHeight here, as we don't want to include scrollbars
@@ -3467,7 +3472,7 @@
3467
3472
  const isDetails = matchNodeName$1('details');
3468
3473
  const isSummary$1 = matchNodeName$1('summary');
3469
3474
  const ucVideoNodeName = 'uc-video';
3470
- const isUcVideo = (el) => el.nodeName.toLowerCase() === ucVideoNodeName;
3475
+ const isUcVideo = matchNodeName$1(ucVideoNodeName);
3471
3476
 
3472
3477
  const defaultOptionValues = {
3473
3478
  skipBogus: true,
@@ -3691,7 +3696,7 @@
3691
3696
  const parents = parents$1(SugarElement.fromDom(caretParent), isRoot);
3692
3697
  // Check the element just above below the root so in if caretParent is I in this
3693
3698
  // case <body><p><b><i>|</i></b></p></body> it would use the P as the scope
3694
- get$b(parents, parents.length - 2).filter(isElement$8).fold(() => updateChildren(schema, root), (scope) => updateChildren(schema, scope.dom));
3699
+ get$c(parents, parents.length - 2).filter(isElement$8).fold(() => updateChildren(schema, root), (scope) => updateChildren(schema, scope.dom));
3695
3700
  };
3696
3701
  const hasBlockAttr = (el) => el.hasAttribute(transparentBlockAttr);
3697
3702
  const isTransparentElementName = (schema, name) => has$2(schema.getTransparentElements(), name);
@@ -3729,7 +3734,7 @@
3729
3734
  if (elm) {
3730
3735
  // Use getBoundingClientRect if it exists since it's faster than looping offset nodes
3731
3736
  // Fallback to offsetParent calculations if the body isn't static better since it stops at the body root
3732
- if (rootElm === body && elm.getBoundingClientRect && get$7(SugarElement.fromDom(body), 'position') === 'static') {
3737
+ if (rootElm === body && elm.getBoundingClientRect && get$8(SugarElement.fromDom(body), 'position') === 'static') {
3733
3738
  const pos = elm.getBoundingClientRect();
3734
3739
  // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit
3735
3740
  // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position
@@ -3788,7 +3793,7 @@
3788
3793
  const styleContainer = getStyleContainer(edos);
3789
3794
  descendant$1(styleContainer, '#' + id).each(remove$8);
3790
3795
  };
3791
- const getOrCreateState = (url) => get$a(loadedStates, url).getOrThunk(() => ({
3796
+ const getOrCreateState = (url) => get$b(loadedStates, url).getOrThunk(() => ({
3792
3797
  id: 'mce-u' + (idCount++),
3793
3798
  passed: [],
3794
3799
  failed: [],
@@ -3850,17 +3855,17 @@
3850
3855
  });
3851
3856
  const crossorigin = getCrossOrigin$1(url, settings);
3852
3857
  if (crossorigin !== undefined) {
3853
- set$4(linkElem, 'crossOrigin', crossorigin);
3858
+ set$5(linkElem, 'crossOrigin', crossorigin);
3854
3859
  }
3855
3860
  if (settings.referrerPolicy) {
3856
3861
  // Note: Don't use link.referrerPolicy = ... here as it doesn't work on Safari
3857
- set$4(linkElem, 'referrerpolicy', settings.referrerPolicy);
3862
+ set$5(linkElem, 'referrerpolicy', settings.referrerPolicy);
3858
3863
  }
3859
3864
  link = linkElem.dom;
3860
3865
  link.onload = passed;
3861
3866
  link.onerror = failed;
3862
3867
  addStyle(linkElem);
3863
- set$4(linkElem, 'href', urlWithSuffix);
3868
+ set$5(linkElem, 'href', urlWithSuffix);
3864
3869
  });
3865
3870
  /**
3866
3871
  * Loads the specified css string in as a style element with an unique key.
@@ -3911,7 +3916,7 @@
3911
3916
  */
3912
3917
  const unload = (url) => {
3913
3918
  const urlWithSuffix = Tools._addCacheSuffix(url);
3914
- get$a(loadedStates, urlWithSuffix).each((state) => {
3919
+ get$b(loadedStates, urlWithSuffix).each((state) => {
3915
3920
  const count = --state.count;
3916
3921
  if (count === 0) {
3917
3922
  delete loadedStates[urlWithSuffix];
@@ -3926,7 +3931,7 @@
3926
3931
  * @param {String} key Key of CSS style resource to unload.
3927
3932
  */
3928
3933
  const unloadRawCss = (key) => {
3929
- get$a(loadedStates, key).each((state) => {
3934
+ get$b(loadedStates, key).each((state) => {
3930
3935
  const count = --state.count;
3931
3936
  if (count === 0) {
3932
3937
  delete loadedStates[key];
@@ -5630,7 +5635,9 @@
5630
5635
  compress('border', '-style');
5631
5636
  compress('padding', '');
5632
5637
  compress('margin', '');
5633
- compress2('border', 'border-width', 'border-style', 'border-color');
5638
+ if (!/(#.* rgb(a?)\(.*)|(rgb(a?)\(.*\) )/.test(styles['border-color'])) {
5639
+ compress2('border', 'border-width', 'border-style', 'border-color');
5640
+ }
5634
5641
  // Remove pointless border, IE produces these
5635
5642
  if (styles.border === 'medium none') {
5636
5643
  delete styles.border;
@@ -5705,7 +5712,8 @@
5705
5712
  webkitMovementX: true,
5706
5713
  webkitMovementY: true,
5707
5714
  keyIdentifier: true,
5708
- mozPressure: true
5715
+ mozPressure: true,
5716
+ mozInputSource: true,
5709
5717
  };
5710
5718
  // Note: We can't rely on `instanceof` here as it won't work if the event was fired from another window.
5711
5719
  // Additionally, the constructor name might be `MouseEvent` or similar so we can't rely on the constructor name.
@@ -6160,7 +6168,7 @@
6160
6168
  remove$9(elm, name);
6161
6169
  }
6162
6170
  else {
6163
- set$4(elm, name, value);
6171
+ set$5(elm, name, value);
6164
6172
  }
6165
6173
  };
6166
6174
  // Convert camel cased names back to hyphenated names
@@ -6183,7 +6191,7 @@
6183
6191
  return idx;
6184
6192
  };
6185
6193
  const updateInternalStyleAttr = (styles, elm) => {
6186
- const rawValue = get$9(elm, 'style');
6194
+ const rawValue = get$a(elm, 'style');
6187
6195
  const value = styles.serialize(styles.parse(rawValue), name(elm));
6188
6196
  legacySetAttribute(elm, internalStyleName, value);
6189
6197
  };
@@ -6201,7 +6209,7 @@
6201
6209
  remove$7($elm, normalizedName);
6202
6210
  }
6203
6211
  else {
6204
- set$2($elm, normalizedName, convertStyleToString(cssValue, normalizedName));
6212
+ set$3($elm, normalizedName, convertStyleToString(cssValue, normalizedName));
6205
6213
  }
6206
6214
  };
6207
6215
  const setupAttrHooks = (styles, settings, getContext) => {
@@ -6218,7 +6226,7 @@
6218
6226
  },
6219
6227
  get: (elm, name) => {
6220
6228
  const sugarElm = SugarElement.fromDom(elm);
6221
- return get$9(sugarElm, 'data-mce-' + name) || get$9(sugarElm, name);
6229
+ return get$a(sugarElm, 'data-mce-' + name) || get$a(sugarElm, name);
6222
6230
  }
6223
6231
  };
6224
6232
  const attrHooks = {
@@ -6237,7 +6245,7 @@
6237
6245
  },
6238
6246
  get: (elm) => {
6239
6247
  const sugarElm = SugarElement.fromDom(elm);
6240
- const value = get$9(sugarElm, internalStyleName) || get$9(sugarElm, 'style');
6248
+ const value = get$a(sugarElm, internalStyleName) || get$a(sugarElm, 'style');
6241
6249
  return styles.serialize(styles.parse(value), name(sugarElm));
6242
6250
  }
6243
6251
  }
@@ -6315,7 +6323,7 @@
6315
6323
  value = hook.get($elm.dom, name);
6316
6324
  }
6317
6325
  else {
6318
- value = get$9($elm, name);
6326
+ value = get$a($elm, name);
6319
6327
  }
6320
6328
  }
6321
6329
  return isNonNullable(value) ? value : defaultVal;
@@ -6329,7 +6337,7 @@
6329
6337
  if (isElement$7(e)) {
6330
6338
  const $elm = SugarElement.fromDom(e);
6331
6339
  const val = value === '' ? null : value;
6332
- const originalValue = get$9($elm, name);
6340
+ const originalValue = get$a($elm, name);
6333
6341
  const hook = attrHooks[name];
6334
6342
  if (hook && hook.set) {
6335
6343
  hook.set($elm.dom, val, name);
@@ -6388,7 +6396,7 @@
6388
6396
  return undefined;
6389
6397
  }
6390
6398
  if (computed) {
6391
- return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name));
6399
+ return get$8(SugarElement.fromDom($elm), camelCaseToHyphens(name));
6392
6400
  }
6393
6401
  else {
6394
6402
  // Camelcase it, if needed
@@ -6526,7 +6534,7 @@
6526
6534
  const setHTML = (elm, html) => {
6527
6535
  run(elm, (e) => {
6528
6536
  const $elm = SugarElement.fromDom(e);
6529
- set$3($elm, html);
6537
+ set$4($elm, html);
6530
6538
  });
6531
6539
  };
6532
6540
  const add = (parentElm, name, attrs, html, create) => run(parentElm, (parentElm) => {
@@ -6679,7 +6687,7 @@
6679
6687
  run(elm, (e) => remove$7(SugarElement.fromDom(e), 'display'));
6680
6688
  };
6681
6689
  const hide = (elm) => {
6682
- run(elm, (e) => set$2(SugarElement.fromDom(e), 'display', 'none'));
6690
+ run(elm, (e) => set$3(SugarElement.fromDom(e), 'display', 'none'));
6683
6691
  };
6684
6692
  const isHidden = (elm) => {
6685
6693
  const $elm = _get(elm);
@@ -7735,7 +7743,7 @@
7735
7743
  const self = this;
7736
7744
  const execCallbacks = (name, url) => {
7737
7745
  // Execute URL callback functions
7738
- get$a(self.scriptLoadedCallbacks, url).each((callbacks) => {
7746
+ get$b(self.scriptLoadedCallbacks, url).each((callbacks) => {
7739
7747
  each$e(callbacks, (callback) => callback[name](url));
7740
7748
  });
7741
7749
  delete self.scriptLoadedCallbacks[url];
@@ -7835,7 +7843,7 @@
7835
7843
  const isTokenised = (str) => isArray$1(str) && str.length > 1;
7836
7844
  const data = {};
7837
7845
  const currentCode = Cell('en');
7838
- const getLanguageData = () => get$a(data, currentCode.get());
7846
+ const getLanguageData = () => get$b(data, currentCode.get());
7839
7847
  const getData$1 = () => map$2(data, (value) => ({ ...value }));
7840
7848
  /**
7841
7849
  * Sets the current language code.
@@ -7915,7 +7923,7 @@
7915
7923
  const textStr = toString(text);
7916
7924
  return has$2(langData, textStr)
7917
7925
  ? toString(langData[textStr])
7918
- : get$a(langData, textStr.toLowerCase()).map(toString).getOr(textStr);
7926
+ : get$b(langData, textStr.toLowerCase()).map(toString).getOr(textStr);
7919
7927
  };
7920
7928
  const removeContext = (str) => str.replace(/{context:\w+}$/, '');
7921
7929
  const replaceWithEllipsisChar = (text) => text.replaceAll('...', ellipsis);
@@ -7943,7 +7951,7 @@
7943
7951
  * @return {Boolean} True if the current language pack is rtl.
7944
7952
  */
7945
7953
  const isRtl$1 = () => getLanguageData()
7946
- .bind((items) => get$a(items, '_dir'))
7954
+ .bind((items) => get$b(items, '_dir'))
7947
7955
  .exists((dir) => dir === 'rtl');
7948
7956
  /**
7949
7957
  * Returns true/false if specified language pack exists.
@@ -8166,8 +8174,8 @@
8166
8174
  const directory = {};
8167
8175
  each$e(markers, (m) => {
8168
8176
  if (!isBogusElement(m, body)) {
8169
- const uid = get$9(m, dataAnnotationId());
8170
- const nodesAlready = get$a(directory, uid).getOr([]);
8177
+ const uid = get$a(m, dataAnnotationId());
8178
+ const nodesAlready = get$b(directory, uid).getOr([]);
8171
8179
  directory[uid] = nodesAlready.concat([m]);
8172
8180
  }
8173
8181
  });
@@ -8188,7 +8196,7 @@
8188
8196
  };
8189
8197
  const updateCallbacks = (name, f) => {
8190
8198
  const callbackMap = changeCallbacks.get();
8191
- const data = get$a(callbackMap, name).getOrThunk(initData);
8199
+ const data = get$b(callbackMap, name).getOrThunk(initData);
8192
8200
  const outputData = f(data);
8193
8201
  callbackMap[name] = outputData;
8194
8202
  changeCallbacks.set(callbackMap);
@@ -8209,7 +8217,7 @@
8209
8217
  const toggleActiveAttr = (uid, state) => {
8210
8218
  each$e(findMarkers(editor, uid), (elem) => {
8211
8219
  if (state) {
8212
- set$4(elem, dataAnnotationActive(), 'true');
8220
+ set$5(elem, dataAnnotationActive(), 'true');
8213
8221
  }
8214
8222
  else {
8215
8223
  remove$9(elem, dataAnnotationActive());
@@ -8303,7 +8311,7 @@
8303
8311
  settings
8304
8312
  };
8305
8313
  };
8306
- const lookup = (name) => get$a(annotations, name).map((a) => a.settings);
8314
+ const lookup = (name) => get$b(annotations, name).map((a) => a.settings);
8307
8315
  const getNames = () => keys(annotations);
8308
8316
  return {
8309
8317
  register,
@@ -8417,6 +8425,9 @@
8417
8425
  // WARNING: don't add anything to this file, the intention is to move these checks into the Schema
8418
8426
  const isTable$1 = (node) => name(node) === 'table';
8419
8427
  const isBr$6 = (node) => isElement$8(node) && name(node) === 'br';
8428
+ const isScript = (node) => isElement$8(node) && name(node) === 'script';
8429
+ const isStyle = (node) => isElement$8(node) && name(node) === 'style';
8430
+ const isIframe = (node) => isElement$8(node) && name(node) === 'iframe';
8420
8431
  const isTextBlock$3 = lazyLookup(textBlocks);
8421
8432
  const isList$1 = lazyLookup(lists);
8422
8433
  const isListItem$2 = lazyLookup(listItems$1);
@@ -8442,7 +8453,7 @@
8442
8453
  };
8443
8454
  const createPaddingBr = () => {
8444
8455
  const br = SugarElement.fromTag('br');
8445
- set$4(br, 'data-mce-bogus', '1');
8456
+ set$5(br, 'data-mce-bogus', '1');
8446
8457
  return br;
8447
8458
  };
8448
8459
  const fillWithPaddingBr = (elm) => {
@@ -9648,14 +9659,14 @@
9648
9659
 
9649
9660
  const requiredAccess = (path, obj, key, bundle) =>
9650
9661
  // In required mode, if it is undefined, it is an error.
9651
- get$a(obj, key).fold(() => missingRequired(path, key, obj), bundle);
9662
+ get$b(obj, key).fold(() => missingRequired(path, key, obj), bundle);
9652
9663
  const fallbackAccess = (obj, key, fallback, bundle) => {
9653
- const v = get$a(obj, key).getOrThunk(() => fallback(obj));
9664
+ const v = get$b(obj, key).getOrThunk(() => fallback(obj));
9654
9665
  return bundle(v);
9655
9666
  };
9656
- const optionAccess = (obj, key, bundle) => bundle(get$a(obj, key));
9667
+ const optionAccess = (obj, key, bundle) => bundle(get$b(obj, key));
9657
9668
  const optionDefaultedAccess = (obj, key, fallback, bundle) => {
9658
- const opt = get$a(obj, key).map((val) => val === true ? fallback(obj) : val);
9669
+ const opt = get$b(obj, key).map((val) => val === true ? fallback(obj) : val);
9659
9670
  return bundle(opt);
9660
9671
  };
9661
9672
  const extractField = (field, path, obj, key, prop) => {
@@ -9948,7 +9959,7 @@
9948
9959
  if (valid) {
9949
9960
  if (value.indexOf('=') !== -1) {
9950
9961
  const bodyObj = getHash(value);
9951
- return { value: get$a(bodyObj, editor.id).getOr(defaultValue), valid };
9962
+ return { value: get$b(bodyObj, editor.id).getOr(defaultValue), valid };
9952
9963
  }
9953
9964
  else {
9954
9965
  return { value, valid };
@@ -10180,6 +10191,9 @@
10180
10191
  registerOption('content_style', {
10181
10192
  processor: 'string'
10182
10193
  });
10194
+ registerOption('content_language', {
10195
+ processor: 'string'
10196
+ });
10183
10197
  registerOption('content_css_cors', {
10184
10198
  processor: 'boolean',
10185
10199
  default: false
@@ -10605,6 +10619,10 @@
10605
10619
  },
10606
10620
  default: (_ctx) => []
10607
10621
  });
10622
+ registerOption('allow_noneditable', {
10623
+ processor: 'boolean',
10624
+ default: true
10625
+ });
10608
10626
  registerOption('noneditable_class', {
10609
10627
  processor: 'string',
10610
10628
  default: 'mceNonEditable'
@@ -10688,6 +10706,9 @@
10688
10706
  processor: 'string',
10689
10707
  default: 'Anonymous'
10690
10708
  });
10709
+ registerOption('content_id', {
10710
+ processor: 'string',
10711
+ });
10691
10712
  registerOption('fetch_users', {
10692
10713
  processor: (value) => {
10693
10714
  if (value === undefined) {
@@ -10782,6 +10803,7 @@
10782
10803
  const getIndentation = option('indentation');
10783
10804
  const getContentCss = option('content_css');
10784
10805
  const getContentStyle = option('content_style');
10806
+ const getContentLanguage = option('content_language');
10785
10807
  const getFontCss = option('font_css');
10786
10808
  const getDirectionality = option('directionality');
10787
10809
  const getInlineBoundarySelector = option('inline_boundaries_selector');
@@ -10837,6 +10859,7 @@
10837
10859
  const shouldAllowHtmlDataUrls = option('allow_html_data_urls');
10838
10860
  const getTextPatterns = option('text_patterns');
10839
10861
  const getTextPatternsLookup = option('text_patterns_lookup');
10862
+ const shouldAllowNonEditable = option('allow_noneditable');
10840
10863
  const getNonEditableClass = option('noneditable_class');
10841
10864
  const getEditableClass = option('editable_class');
10842
10865
  const getNonEditableRegExps = option('noneditable_regexp');
@@ -11159,7 +11182,7 @@
11159
11182
  .map((elm) => elm.dom)
11160
11183
  .getOr(rootNode);
11161
11184
  };
11162
- const isAbsPositionedElement = (node) => isElement$7(node) && get$7(SugarElement.fromDom(node), 'position') === 'absolute';
11185
+ const isAbsPositionedElement = (node) => isElement$7(node) && get$8(SugarElement.fromDom(node), 'position') === 'absolute';
11163
11186
  const isInlineBlock = (node, rootNode) => node.parentNode !== rootNode;
11164
11187
  const isInlineAbsPositionedCEF = (node, rootNode) => isContentEditableFalse$6(node) && isAbsPositionedElement(node) && isInlineBlock(node, rootNode);
11165
11188
  const getParentBlock$3 = (node, rootNode) => {
@@ -12193,7 +12216,7 @@
12193
12216
  const isVariableFormatName = (editor, formatName) => {
12194
12217
  const hasVariableValues = (format) => {
12195
12218
  const isVariableValue = (val) => isFunction(val) || val.length > 1 && val.charAt(0) === '%';
12196
- return exists(['styles', 'attributes'], (key) => get$a(format, key).exists((field) => {
12219
+ return exists(['styles', 'attributes'], (key) => get$b(format, key).exists((field) => {
12197
12220
  const fieldValues = isArray$1(field) ? field : values(field);
12198
12221
  return exists(fieldValues, isVariableValue);
12199
12222
  }));
@@ -12221,7 +12244,7 @@
12221
12244
  const isNonWrappingBlockFormat = (format) => isBlockFormat(format) && format.wrapper !== true;
12222
12245
  const isSelectorFormat = (format) => hasNonNullableKey(format, 'selector');
12223
12246
  const isInlineFormat = (format) => hasNonNullableKey(format, 'inline');
12224
- const isMixedFormat = (format) => isSelectorFormat(format) && isInlineFormat(format) && is$4(get$a(format, 'mixed'), true);
12247
+ const isMixedFormat = (format) => isSelectorFormat(format) && isInlineFormat(format) && is$4(get$b(format, 'mixed'), true);
12225
12248
  const shouldExpandToSelector = (format) => isSelectorFormat(format) && format.expand !== false && !isInlineFormat(format);
12226
12249
  const getEmptyCaretContainers = (node) => {
12227
12250
  const nodes = [];
@@ -12621,7 +12644,7 @@
12621
12644
  // Footnootes plugin
12622
12645
  'div.mce-footnotes'
12623
12646
  ];
12624
- const isZeroWidth = (elem) => isText$c(elem) && get$4(elem) === ZWSP$1;
12647
+ const isZeroWidth = (elem) => isText$c(elem) && get$5(elem) === ZWSP$1;
12625
12648
  const context = (editor, elem, wrapName, nodeName) => parentElement(elem).fold(() => "skipping" /* ChildContext.Skipping */, (parent) => {
12626
12649
  // We used to skip these, but given that they might be representing empty paragraphs, it probably
12627
12650
  // makes sense to treat them just like text nodes
@@ -12654,18 +12677,18 @@
12654
12677
  const applyAnnotation = (elem, masterUId, data, annotationName, decorate, directAnnotation) => {
12655
12678
  const { uid = masterUId, ...otherData } = data;
12656
12679
  add$2(elem, annotation());
12657
- set$4(elem, `${dataAnnotationId()}`, uid);
12658
- set$4(elem, `${dataAnnotation()}`, annotationName);
12680
+ set$5(elem, `${dataAnnotationId()}`, uid);
12681
+ set$5(elem, `${dataAnnotation()}`, annotationName);
12659
12682
  const { attributes = {}, classes = [] } = decorate(uid, otherData);
12660
12683
  setAll$1(elem, attributes);
12661
12684
  add$1(elem, classes);
12662
12685
  if (directAnnotation) {
12663
12686
  if (classes.length > 0) {
12664
- set$4(elem, `${dataAnnotationClasses()}`, classes.join(','));
12687
+ set$5(elem, `${dataAnnotationClasses()}`, classes.join(','));
12665
12688
  }
12666
12689
  const attributeNames = keys(attributes);
12667
12690
  if (attributeNames.length > 0) {
12668
- set$4(elem, `${dataAnnotationAttributes()}`, attributeNames.join(','));
12691
+ set$5(elem, `${dataAnnotationAttributes()}`, attributeNames.join(','));
12669
12692
  }
12670
12693
  }
12671
12694
  };
@@ -12754,7 +12777,7 @@
12754
12777
  if (selection.getRng().collapsed && !hasFakeSelection) {
12755
12778
  const wrapper = makeAnnotation(editor.getDoc(), masterUid, data, name, settings.decorate);
12756
12779
  // Put something visible in the marker
12757
- set$3(wrapper, nbsp);
12780
+ set$4(wrapper, nbsp);
12758
12781
  selection.getRng().insertNode(wrapper.dom);
12759
12782
  selection.select(wrapper.dom);
12760
12783
  }
@@ -12931,7 +12954,7 @@
12931
12954
  };
12932
12955
 
12933
12956
  const clamp$1 = (offset, element) => {
12934
- const max = isText$c(element) ? get$4(element).length : children$1(element).length + 1;
12957
+ const max = isText$c(element) ? get$5(element).length : children$1(element).length + 1;
12935
12958
  if (offset > max) {
12936
12959
  return max;
12937
12960
  }
@@ -14181,7 +14204,7 @@
14181
14204
 
14182
14205
  const find = (element) => {
14183
14206
  const doc = getDocument();
14184
- const scroll = get$5(doc);
14207
+ const scroll = get$6(doc);
14185
14208
  const frames = pathTo(element, Navigation);
14186
14209
  const offset = viewport(element);
14187
14210
  const r = foldr(frames, (b, a) => {
@@ -14220,7 +14243,7 @@
14220
14243
  return { element: last, offset: 1 };
14221
14244
  }
14222
14245
  else if (isText$c(last)) {
14223
- return { element: last, offset: get$4(last).length };
14246
+ return { element: last, offset: get$5(last).length };
14224
14247
  }
14225
14248
  else {
14226
14249
  return { element: last, offset: children$1(last).length };
@@ -14230,7 +14253,7 @@
14230
14253
  };
14231
14254
  const markerInfo = (element, cleanupFun) => {
14232
14255
  const pos = absolute(element);
14233
- const height = get$6(element);
14256
+ const height = get$7(element);
14234
14257
  return {
14235
14258
  element,
14236
14259
  bottom: pos.top + height,
@@ -14254,7 +14277,7 @@
14254
14277
  if (fireScrollIntoViewEvent(editor, data)) {
14255
14278
  return;
14256
14279
  }
14257
- const scrollTop = get$5(doc).top;
14280
+ const scrollTop = get$6(doc).top;
14258
14281
  f(editor, doc, scrollTop, marker, alignToTop);
14259
14282
  fireAfterScrollIntoViewEvent(editor, data);
14260
14283
  };
@@ -14937,7 +14960,7 @@
14937
14960
  const trimTemporaryNodes = (tempAttrs, body) => {
14938
14961
  each$e(getTemporaryNodes(tempAttrs, body), (elm) => {
14939
14962
  const element = SugarElement.fromDom(elm);
14940
- if (get$9(element, 'data-mce-bogus') === 'all') {
14963
+ if (get$a(element, 'data-mce-bogus') === 'all') {
14941
14964
  remove$8(element);
14942
14965
  }
14943
14966
  else {
@@ -14990,7 +15013,7 @@
14990
15013
  const cleanupBogusElements = (parent) => {
14991
15014
  const bogusElements = descendants(parent, '[data-mce-bogus]');
14992
15015
  each$e(bogusElements, (elem) => {
14993
- const bogusValue = get$9(elem, 'data-mce-bogus');
15016
+ const bogusValue = get$a(elem, 'data-mce-bogus');
14994
15017
  if (bogusValue === 'all') {
14995
15018
  remove$8(elem);
14996
15019
  }
@@ -15020,13 +15043,13 @@
15020
15043
  const doc = editor.getDoc();
15021
15044
  const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
15022
15045
  const offscreenDiv = SugarElement.fromTag('div', doc);
15023
- set$4(offscreenDiv, 'data-mce-bogus', 'all');
15046
+ set$5(offscreenDiv, 'data-mce-bogus', 'all');
15024
15047
  setAll(offscreenDiv, {
15025
15048
  position: 'fixed',
15026
15049
  left: '-9999999px',
15027
15050
  top: '0'
15028
15051
  });
15029
- set$3(offscreenDiv, body.innerHTML);
15052
+ set$4(offscreenDiv, body.innerHTML);
15030
15053
  cleanupBogusElements(offscreenDiv);
15031
15054
  cleanupInputNames(offscreenDiv);
15032
15055
  // Append the wrapper element so that the browser will evaluate styles when getting the `innerText`
@@ -15418,7 +15441,7 @@
15418
15441
  return isText$b(container) && (container.data.length === 0 || isZwsp(container.data) && BookmarkManager.isBookmarkNode(container.parentNode));
15419
15442
  };
15420
15443
  const matchesElementPosition = (before, predicate) => (pos) => getChildNodeAtRelativeOffset(before ? 0 : -1, pos).filter(predicate).isSome();
15421
- const isImageBlock = (node) => isImg(node) && get$7(SugarElement.fromDom(node), 'display') === 'block';
15444
+ const isImageBlock = (node) => isImg(node) && get$8(SugarElement.fromDom(node), 'display') === 'block';
15422
15445
  const isCefNode = (node) => isContentEditableFalse$a(node) && !isBogusAll(node);
15423
15446
  const isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
15424
15447
  const isAfterImageBlock = matchesElementPosition(false, isImageBlock);
@@ -15489,7 +15512,7 @@
15489
15512
  const isPreValue = (value) => contains$2(['pre', 'pre-wrap'], value);
15490
15513
  const isInPre = (pos) => getElementFromPosition(pos)
15491
15514
  .bind((elm) => closest$5(elm, isElement$8))
15492
- .exists((elm) => isPreValue(get$7(elm, 'white-space')));
15515
+ .exists((elm) => isPreValue(get$8(elm, 'white-space')));
15493
15516
  const isAtBeginningOfBody = (root, pos) => prevPosition(root.dom, pos).isNone();
15494
15517
  const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
15495
15518
  const isAtLineBoundary = (root, pos, schema) => (isAtBeginningOfBody(root, pos) ||
@@ -16112,7 +16135,7 @@
16112
16135
  // Restore the data-mce-selected attribute if multiple cells were selected, as if it was a cef element
16113
16136
  // then selection overrides would remove it as it was using an offscreen selection clone.
16114
16137
  if (selectedCells.length > 1 && exists(selectedCells, (cell) => eq(cell, selectedNode))) {
16115
- set$4(selectedNode, 'data-mce-selected', '1');
16138
+ set$5(selectedNode, 'data-mce-selected', '1');
16116
16139
  }
16117
16140
  };
16118
16141
  /*
@@ -16811,7 +16834,7 @@
16811
16834
  return Optional.none();
16812
16835
  }
16813
16836
  };
16814
- const normalizeNbsps = (node) => set$1(node, get$4(node).replace(new RegExp(`${nbsp}$`), ' '));
16837
+ const normalizeNbsps = (node) => set$2(node, get$5(node).replace(new RegExp(`${nbsp}$`), ' '));
16815
16838
  const normalizeNbspsBetween = (editor, caretContainer) => {
16816
16839
  const handler = () => {
16817
16840
  if (caretContainer !== null && !editor.dom.isEmpty(caretContainer)) {
@@ -18248,13 +18271,14 @@
18248
18271
  const uniqueId$1 = (prefix) => {
18249
18272
  return (prefix || 'blobid') + (count$1++);
18250
18273
  };
18274
+ const utf8Encode = (str) => foldl(new window.TextEncoder().encode(str), (acc, charCode) => acc + String.fromCharCode(charCode), '');
18251
18275
  const processDataUri = (dataUri, base64Only, generateBlobInfo) => {
18252
18276
  return parseDataUri(dataUri).bind(({ data, type, base64Encoded }) => {
18253
18277
  if (base64Only && !base64Encoded) {
18254
18278
  return Optional.none();
18255
18279
  }
18256
18280
  else {
18257
- const base64 = base64Encoded ? data : btoa(data);
18281
+ const base64 = base64Encoded ? data : btoa(utf8Encode(data));
18258
18282
  return generateBlobInfo(base64, type);
18259
18283
  }
18260
18284
  });
@@ -18296,7 +18320,7 @@
18296
18320
  // TINY-10350: A modification of the Regexes.link regex to specifically capture host.
18297
18321
  // eslint-disable-next-line max-len
18298
18322
  const hostCaptureRegex = /^(?:(?:(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)([A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*))(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+)?)?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+)?)?)$/;
18299
- const extractHost = (url) => Optional.from(url.match(hostCaptureRegex)).bind((ms) => get$b(ms, 1)).map((h) => startsWith(h, 'www.') ? h.substring(4) : h);
18323
+ const extractHost = (url) => Optional.from(url.match(hostCaptureRegex)).bind((ms) => get$c(ms, 1)).map((h) => startsWith(h, 'www.') ? h.substring(4) : h);
18300
18324
 
18301
18325
  const sandboxIframe = (iframeNode, exclusions) => {
18302
18326
  if (Optional.from(iframeNode.attr('src')).bind(extractHost).forall((host) => !contains$2(exclusions, host))) {
@@ -18468,7 +18492,7 @@
18468
18492
  }
18469
18493
  };
18470
18494
 
18471
- /*! @license DOMPurify 3.2.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.6/LICENSE */
18495
+ /*! @license DOMPurify 3.3.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.2/LICENSE */
18472
18496
 
18473
18497
  const {
18474
18498
  entries,
@@ -18497,12 +18521,18 @@
18497
18521
  };
18498
18522
  }
18499
18523
  if (!apply) {
18500
- apply = function apply(fun, thisValue, args) {
18501
- return fun.apply(thisValue, args);
18524
+ apply = function apply(func, thisArg) {
18525
+ for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
18526
+ args[_key - 2] = arguments[_key];
18527
+ }
18528
+ return func.apply(thisArg, args);
18502
18529
  };
18503
18530
  }
18504
18531
  if (!construct) {
18505
- construct = function construct(Func, args) {
18532
+ construct = function construct(Func) {
18533
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
18534
+ args[_key2 - 1] = arguments[_key2];
18535
+ }
18506
18536
  return new Func(...args);
18507
18537
  };
18508
18538
  }
@@ -18531,8 +18561,8 @@
18531
18561
  if (thisArg instanceof RegExp) {
18532
18562
  thisArg.lastIndex = 0;
18533
18563
  }
18534
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
18535
- args[_key - 1] = arguments[_key];
18564
+ for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
18565
+ args[_key3 - 1] = arguments[_key3];
18536
18566
  }
18537
18567
  return apply(func, thisArg, args);
18538
18568
  };
@@ -18543,12 +18573,12 @@
18543
18573
  * @param func - The constructor function to be wrapped and called.
18544
18574
  * @returns A new function that constructs an instance of the given constructor function with the provided arguments.
18545
18575
  */
18546
- function unconstruct(func) {
18576
+ function unconstruct(Func) {
18547
18577
  return function () {
18548
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
18549
- args[_key2] = arguments[_key2];
18578
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
18579
+ args[_key4] = arguments[_key4];
18550
18580
  }
18551
- return construct(func, args);
18581
+ return construct(Func, args);
18552
18582
  };
18553
18583
  }
18554
18584
  /**
@@ -18647,8 +18677,8 @@
18647
18677
  return fallbackValue;
18648
18678
  }
18649
18679
 
18650
- const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
18651
- const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
18680
+ const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
18681
+ const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
18652
18682
  const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
18653
18683
  // List of SVG elements that are disallowed by default.
18654
18684
  // We still need to know them so that we can do namespace
@@ -18661,8 +18691,8 @@
18661
18691
  const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
18662
18692
  const text = freeze(['#text']);
18663
18693
 
18664
- const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
18665
- const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
18694
+ const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
18695
+ const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
18666
18696
  const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
18667
18697
  const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
18668
18698
 
@@ -18769,7 +18799,7 @@
18769
18799
  function createDOMPurify() {
18770
18800
  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
18771
18801
  const DOMPurify = root => createDOMPurify(root);
18772
- DOMPurify.version = '3.2.6';
18802
+ DOMPurify.version = '3.3.2';
18773
18803
  DOMPurify.removed = [];
18774
18804
  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
18775
18805
  // Not running in a browser, provide a factory function
@@ -18880,6 +18910,21 @@
18880
18910
  let FORBID_TAGS = null;
18881
18911
  /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
18882
18912
  let FORBID_ATTR = null;
18913
+ /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */
18914
+ const EXTRA_ELEMENT_HANDLING = Object.seal(create$7(null, {
18915
+ tagCheck: {
18916
+ writable: true,
18917
+ configurable: false,
18918
+ enumerable: true,
18919
+ value: null
18920
+ },
18921
+ attributeCheck: {
18922
+ writable: true,
18923
+ configurable: false,
18924
+ enumerable: true,
18925
+ value: null
18926
+ }
18927
+ }));
18883
18928
  /* Decide if ARIA attributes are okay */
18884
18929
  let ALLOW_ARIA_ATTR = true;
18885
18930
  /* Decide if custom data attributes are okay */
@@ -19049,7 +19094,7 @@
19049
19094
  /* Parse profile info */
19050
19095
  if (USE_PROFILES) {
19051
19096
  ALLOWED_TAGS = addToSet({}, text);
19052
- ALLOWED_ATTR = [];
19097
+ ALLOWED_ATTR = create$7(null);
19053
19098
  if (USE_PROFILES.html === true) {
19054
19099
  addToSet(ALLOWED_TAGS, html$1);
19055
19100
  addToSet(ALLOWED_ATTR, html);
@@ -19070,18 +19115,33 @@
19070
19115
  addToSet(ALLOWED_ATTR, xml);
19071
19116
  }
19072
19117
  }
19118
+ /* Prevent function-based ADD_ATTR / ADD_TAGS from leaking across calls */
19119
+ if (!objectHasOwnProperty(cfg, 'ADD_TAGS')) {
19120
+ EXTRA_ELEMENT_HANDLING.tagCheck = null;
19121
+ }
19122
+ if (!objectHasOwnProperty(cfg, 'ADD_ATTR')) {
19123
+ EXTRA_ELEMENT_HANDLING.attributeCheck = null;
19124
+ }
19073
19125
  /* Merge configuration parameters */
19074
19126
  if (cfg.ADD_TAGS) {
19075
- if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
19076
- ALLOWED_TAGS = clone(ALLOWED_TAGS);
19127
+ if (typeof cfg.ADD_TAGS === 'function') {
19128
+ EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
19129
+ } else {
19130
+ if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
19131
+ ALLOWED_TAGS = clone(ALLOWED_TAGS);
19132
+ }
19133
+ addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
19077
19134
  }
19078
- addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
19079
19135
  }
19080
19136
  if (cfg.ADD_ATTR) {
19081
- if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
19082
- ALLOWED_ATTR = clone(ALLOWED_ATTR);
19137
+ if (typeof cfg.ADD_ATTR === 'function') {
19138
+ EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
19139
+ } else {
19140
+ if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
19141
+ ALLOWED_ATTR = clone(ALLOWED_ATTR);
19142
+ }
19143
+ addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
19083
19144
  }
19084
- addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
19085
19145
  }
19086
19146
  if (cfg.ADD_URI_SAFE_ATTR) {
19087
19147
  addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
@@ -19092,6 +19152,12 @@
19092
19152
  }
19093
19153
  addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
19094
19154
  }
19155
+ if (cfg.ADD_FORBID_CONTENTS) {
19156
+ if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
19157
+ FORBID_CONTENTS = clone(FORBID_CONTENTS);
19158
+ }
19159
+ addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
19160
+ }
19095
19161
  /* Add #text in case KEEP_CONTENT is set to true */
19096
19162
  if (KEEP_CONTENT) {
19097
19163
  ALLOWED_TAGS['#text'] = true;
@@ -19389,7 +19455,7 @@
19389
19455
  return true;
19390
19456
  }
19391
19457
  /* Remove element if anything forbids its presence */
19392
- if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
19458
+ if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])) {
19393
19459
  /* Check if we have a custom element to handle */
19394
19460
  if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
19395
19461
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
@@ -19453,6 +19519,10 @@
19453
19519
  */
19454
19520
  // eslint-disable-next-line complexity
19455
19521
  const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
19522
+ /* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
19523
+ if (FORBID_ATTR[lcName]) {
19524
+ return false;
19525
+ }
19456
19526
  /* Make sure attribute cannot clobber */
19457
19527
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
19458
19528
  return false;
@@ -19461,12 +19531,12 @@
19461
19531
  (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
19462
19532
  XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
19463
19533
  We don't need to check the value; it's always URI safe. */
19464
- if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
19534
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
19465
19535
  if (
19466
19536
  // First condition does a very basic check if a) it's basically a valid custom element tagname AND
19467
19537
  // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
19468
19538
  // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
19469
- _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||
19539
+ _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) ||
19470
19540
  // Alternative, second condition checks if it's an `is`-attribute, AND
19471
19541
  // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
19472
19542
  lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {
@@ -19545,7 +19615,12 @@
19545
19615
  value = SANITIZE_NAMED_PROPS_PREFIX + value;
19546
19616
  }
19547
19617
  /* Work around a security issue with comments inside attributes */
19548
- if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title)/i, value)) {
19618
+ if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
19619
+ _removeAttribute(name, currentNode);
19620
+ continue;
19621
+ }
19622
+ /* Make sure we cannot easily use animated hrefs, even if animations are allowed */
19623
+ if (lcName === 'attributename' && stringMatch(value, 'href')) {
19549
19624
  _removeAttribute(name, currentNode);
19550
19625
  continue;
19551
19626
  }
@@ -20268,10 +20343,22 @@
20268
20343
  }
20269
20344
  // Construct the sugar element wrapper
20270
20345
  const element = SugarElement.fromDom(node);
20346
+ if (settings.sanitize) {
20347
+ // TINY-9655: Preserve the content of script and style tags if they are valid elements in the schema
20348
+ const shouldKeepContent = (isScript(element) && schema.isValid('script')) || (isStyle(element) && schema.isValid('style'));
20349
+ if (shouldKeepContent) {
20350
+ Optional.from(get$3(element)).each((content) => set$5(element, 'data-mce-tmp', content));
20351
+ }
20352
+ // TINY-9655: Clear innerHTML of script and iframe tags to prevent DOMPurify from removing them entirely
20353
+ const shouldClearContent = isIframe(element) && schema.isValid('iframe');
20354
+ if (shouldKeepContent || shouldClearContent) {
20355
+ empty(element);
20356
+ }
20357
+ }
20271
20358
  // Determine if we're dealing with an internal attribute
20272
20359
  const isInternalElement = has$1(element, internalElementAttr);
20273
20360
  // Cleanup bogus elements
20274
- const bogus = get$9(element, 'data-mce-bogus');
20361
+ const bogus = get$a(element, 'data-mce-bogus');
20275
20362
  if (!isInternalElement && isString(bogus)) {
20276
20363
  if (bogus === 'all') {
20277
20364
  remove$8(element);
@@ -20302,11 +20389,11 @@
20302
20389
  if (validate && rule && !isInternalElement) {
20303
20390
  // Fix the attributes for the element, unwrapping it if we have to
20304
20391
  each$e(rule.attributesForced ?? [], (attr) => {
20305
- set$4(element, attr.name, attr.value === '{$uid}' ? `mce_${uid++}` : attr.value);
20392
+ set$5(element, attr.name, attr.value === '{$uid}' ? `mce_${uid++}` : attr.value);
20306
20393
  });
20307
20394
  each$e(rule.attributesDefault ?? [], (attr) => {
20308
20395
  if (!has$1(element, attr.name)) {
20309
- set$4(element, attr.name, attr.value === '{$uid}' ? `mce_${uid++}` : attr.value);
20396
+ set$5(element, attr.name, attr.value === '{$uid}' ? `mce_${uid++}` : attr.value);
20310
20397
  }
20311
20398
  });
20312
20399
  // If none of the required attributes were found then remove
@@ -20368,12 +20455,25 @@
20368
20455
  }
20369
20456
  }
20370
20457
  };
20458
+ const restoreValidContent = (node) => {
20459
+ // Construct the sugar element wrapper
20460
+ const element = SugarElement.fromDom(node);
20461
+ if (isScript(element) || isStyle(element)) {
20462
+ getOpt(element, 'data-mce-tmp').each((content) => {
20463
+ set(element, content);
20464
+ remove$9(element, 'data-mce-tmp');
20465
+ });
20466
+ }
20467
+ };
20371
20468
  const setupPurify = (settings, schema, namespaceTracker) => {
20372
20469
  const purify$1 = purify();
20373
20470
  // We use this to add new tags to the allow-list as we parse, if we notice that a tag has been banned but it's still in the schema
20374
20471
  purify$1.addHook('uponSanitizeElement', (ele, evt) => {
20375
20472
  processNode(ele, settings, schema, namespaceTracker.track(ele), evt);
20376
20473
  });
20474
+ purify$1.addHook('afterSanitizeElements', (ele) => {
20475
+ restoreValidContent(ele);
20476
+ });
20377
20477
  // Let's do the same thing for attributes
20378
20478
  purify$1.addHook('uponSanitizeAttribute', (ele, evt) => {
20379
20479
  processAttr(ele, settings, schema, namespaceTracker.current(), evt);
@@ -22197,7 +22297,7 @@
22197
22297
  const addListeners = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
22198
22298
  const formatChangeItems = registeredFormatListeners.get();
22199
22299
  each$e(formats.split(','), (format) => {
22200
- const group = get$a(formatChangeItems, format).getOrThunk(() => {
22300
+ const group = get$b(formatChangeItems, format).getOrThunk(() => {
22201
22301
  const base = {
22202
22302
  withSimilar: {
22203
22303
  state: Cell(false),
@@ -22238,7 +22338,7 @@
22238
22338
  };
22239
22339
  const removeListeners = (registeredFormatListeners, formats, callback) => {
22240
22340
  const formatChangeItems = registeredFormatListeners.get();
22241
- each$e(formats.split(','), (format) => get$a(formatChangeItems, format).each((group) => {
22341
+ each$e(formats.split(','), (format) => get$b(formatChangeItems, format).each((group) => {
22242
22342
  formatChangeItems[format] = {
22243
22343
  withSimilar: {
22244
22344
  ...group.withSimilar,
@@ -22762,12 +22862,12 @@
22762
22862
  };
22763
22863
  const getCleanLevelContent = (isReadonly, level) => {
22764
22864
  const elm = SugarElement.fromTag('body', lazyTempDocument());
22765
- set$3(elm, getLevelContent(level));
22865
+ set$4(elm, getLevelContent(level));
22766
22866
  each$e(descendants(elm, '*[data-mce-bogus]'), unwrap);
22767
22867
  if (isReadonly) {
22768
22868
  each$e(descendants(elm, 'details[open]'), (element) => remove$9(element, 'open'));
22769
22869
  }
22770
- return get$8(elm);
22870
+ return get$9(elm);
22771
22871
  };
22772
22872
  const hasEqualContent = (level1, level2) => getLevelContent(level1) === getLevelContent(level2);
22773
22873
  const hasEqualCleanedContent = (isReadonly, level1, level2) => getCleanLevelContent(isReadonly, level1) === getCleanLevelContent(isReadonly, level2);
@@ -23108,7 +23208,7 @@
23108
23208
  };
23109
23209
  };
23110
23210
  const isRtc = (editor) => has$2(editor.plugins, 'rtc');
23111
- const getRtcSetup = (editor) => get$a(editor.plugins, 'rtc').bind((rtcPlugin) =>
23211
+ const getRtcSetup = (editor) => get$b(editor.plugins, 'rtc').bind((rtcPlugin) =>
23112
23212
  // This might not exist if the stub plugin is loaded on cloud
23113
23213
  Optional.from(rtcPlugin.setup));
23114
23214
  const setup$z = (editor) => {
@@ -24359,7 +24459,7 @@
24359
24459
  const rawElm = elm.dom;
24360
24460
  return rawElm[propName];
24361
24461
  };
24362
- const getComputedSizeProp = (propName, elm) => parseInt(get$7(elm, propName), 10);
24462
+ const getComputedSizeProp = (propName, elm) => parseInt(get$8(elm, propName), 10);
24363
24463
  const getClientWidth = curry(getProp, 'clientWidth');
24364
24464
  const getClientHeight = curry(getProp, 'clientHeight');
24365
24465
  const getMarginTop = curry(getComputedSizeProp, 'margin-top');
@@ -24978,7 +25078,7 @@
24978
25078
  const load = (editor, suffix) => {
24979
25079
  const strategy = determineStrategy(editor);
24980
25080
  if (strategy.type === 'use_plugin') {
24981
- const externalUrl = get$a(getExternalPlugins$1(editor), PLUGIN_CODE).map(trim$4).filter(isNotEmpty);
25081
+ const externalUrl = get$b(getExternalPlugins$1(editor), PLUGIN_CODE).map(trim$4).filter(isNotEmpty);
24982
25082
  const url = externalUrl.getOr(`plugins/${PLUGIN_CODE}/plugin${suffix}.js`);
24983
25083
  addOnManager.load(ADDON_KEY, url).catch(() => {
24984
25084
  licenseKeyManagerLoadError(editor, url);
@@ -25079,7 +25179,7 @@
25079
25179
  const body = SugarElement.fromDom(editor.getBody());
25080
25180
  toggleClass(body, 'mce-content-readonly', false);
25081
25181
  if (editor.hasEditableRoot()) {
25082
- set(body, true);
25182
+ set$1(body, true);
25083
25183
  }
25084
25184
  setCommonEditorCommands(editor, false);
25085
25185
  if (hasEditorOrUiFocus(editor)) {
@@ -25093,21 +25193,21 @@
25093
25193
  const internalContentEditableAttr = 'data-mce-contenteditable';
25094
25194
  const switchOffContentEditableTrue = (elm) => {
25095
25195
  each$e(descendants(elm, '*[contenteditable="true"]'), (elm) => {
25096
- set$4(elm, internalContentEditableAttr, 'true');
25097
- set(elm, false);
25196
+ set$5(elm, internalContentEditableAttr, 'true');
25197
+ set$1(elm, false);
25098
25198
  });
25099
25199
  };
25100
25200
  const switchOnContentEditableTrue = (elm) => {
25101
25201
  each$e(descendants(elm, `*[${internalContentEditableAttr}="true"]`), (elm) => {
25102
25202
  remove$9(elm, internalContentEditableAttr);
25103
- set(elm, true);
25203
+ set$1(elm, true);
25104
25204
  });
25105
25205
  };
25106
25206
  const toggleDisabled = (editor, state) => {
25107
25207
  const body = SugarElement.fromDom(editor.getBody());
25108
25208
  if (state) {
25109
25209
  disableEditor(editor);
25110
- set(body, false);
25210
+ set$1(body, false);
25111
25211
  switchOffContentEditableTrue(body);
25112
25212
  }
25113
25213
  else {
@@ -25203,8 +25303,8 @@
25203
25303
  };
25204
25304
 
25205
25305
  const isContentCssSkinName = (url) => /^[a-z0-9\-]+$/i.test(url);
25206
- const toContentSkinResourceName = (url) => 'content/' + url + '/content.css';
25207
- const isBundledCssSkinName = (url) => tinymce.Resource.has(toContentSkinResourceName(url));
25306
+ const toContentSkinResourceName = (name) => 'content/' + name + '/content.css';
25307
+ const isBundledCssSkinName = (name) => tinymce.Resource.has(toContentSkinResourceName(name));
25208
25308
  const getContentCssUrls = (editor) => {
25209
25309
  return transformToUrls(editor, getContentCss(editor));
25210
25310
  };
@@ -25217,7 +25317,7 @@
25217
25317
  const contentCssFile = `content${suffix}.css`;
25218
25318
  return map$3(cssLinks, (url) => {
25219
25319
  if (isBundledCssSkinName(url)) {
25220
- return url;
25320
+ return toContentSkinResourceName(url);
25221
25321
  }
25222
25322
  else if (isContentCssSkinName(url) && !editor.inline) {
25223
25323
  return `${skinUrl}/${url}/${contentCssFile}`;
@@ -25405,7 +25505,7 @@
25405
25505
  }
25406
25506
  };
25407
25507
  const toBlobInfo = (o) => {
25408
- if (!o.blob || !o.base64) {
25508
+ if (isNullable(o.blob) || isNullable(o.base64) || (o.base64 === '' && !o.allowEmptyFile)) {
25409
25509
  throw new Error('blob and base64 representations of the image are required for BlobInfo to be created');
25410
25510
  }
25411
25511
  const id = o.id || uuid('blobid');
@@ -26765,7 +26865,7 @@
26765
26865
  level.bookmark = getUndoBookmark(editor.selection);
26766
26866
  editor.dispatch('change', {
26767
26867
  level,
26768
- lastLevel: get$b(undoManager.data, index.get()).getOrUndefined()
26868
+ lastLevel: get$c(undoManager.data, index.get()).getOrUndefined()
26769
26869
  });
26770
26870
  },
26771
26871
  /**
@@ -26952,6 +27052,53 @@
26952
27052
  }
26953
27053
  };
26954
27054
 
27055
+ const createAndFireInputEvent = (eventType) => (editor, inputType, specifics = {}) => {
27056
+ const target = editor.getBody();
27057
+ const overrides = {
27058
+ bubbles: true,
27059
+ composed: true,
27060
+ data: null,
27061
+ isComposing: false,
27062
+ detail: 0,
27063
+ view: null,
27064
+ target,
27065
+ currentTarget: target,
27066
+ eventPhase: Event.AT_TARGET,
27067
+ originalTarget: target,
27068
+ explicitOriginalTarget: target,
27069
+ isTrusted: false,
27070
+ srcElement: target,
27071
+ cancelable: false,
27072
+ preventDefault: noop,
27073
+ inputType
27074
+ };
27075
+ const input = clone$2(new InputEvent(eventType));
27076
+ return editor.dispatch(eventType, { ...input, ...overrides, ...specifics });
27077
+ };
27078
+ const fireInputEvent = createAndFireInputEvent('input');
27079
+ const fireBeforeInputEvent = createAndFireInputEvent('beforeinput');
27080
+
27081
+ const symulateDelete = (editor, isForward, deleteFun) => {
27082
+ // Some delete actions may prevent the input event from being fired. If we do not detect it, we fire it ourselves.
27083
+ let shouldFireInput = true;
27084
+ const inputHandler = () => shouldFireInput = false;
27085
+ const beforeInputEvent = fireBeforeInputEvent(editor, isForward ? 'deleteContentForward' : 'deleteContentBackward');
27086
+ if (beforeInputEvent.isDefaultPrevented()) {
27087
+ return false;
27088
+ }
27089
+ editor.on('input', inputHandler);
27090
+ try {
27091
+ deleteFun();
27092
+ }
27093
+ finally {
27094
+ editor.off('input', inputHandler);
27095
+ }
27096
+ if (shouldFireInput) {
27097
+ editor.dispatch('input');
27098
+ }
27099
+ return true;
27100
+ };
27101
+
26955
27102
  const matchNodeName = (name) => (node) => isNonNullable(node) && node.nodeName.toLowerCase() === name;
26956
27103
  const matchNodeNames = (regex) => (node) => isNonNullable(node) && regex.test(node.nodeName);
26957
27104
  const isTextNode$1 = (node) => isNonNullable(node) && node.nodeType === 3;
@@ -26960,6 +27107,7 @@
26960
27107
  const isOlUlNode = matchNodeNames(/^(OL|UL)$/);
26961
27108
  const isListItemNode = matchNodeNames(/^(LI|DT|DD)$/);
26962
27109
  const isDlItemNode = matchNodeNames(/^(DT|DD)$/);
27110
+ const isTableCellNode = matchNodeNames(/^(TH|TD)$/);
26963
27111
  const isBr$1 = matchNodeName('br');
26964
27112
  const isFirstChild$1 = (node) => node.parentNode?.firstChild === node;
26965
27113
  const isTextBlock = (editor, node) => isNonNullable(node) && node.nodeName in editor.schema.getTextBlockElements();
@@ -27045,11 +27193,19 @@
27045
27193
  return outRng;
27046
27194
  };
27047
27195
 
27196
+ const isList = (el) => is$1(el, 'OL,UL');
27197
+ const isListItem$1 = (el) => is$1(el, 'LI');
27198
+ const hasFirstChildList = (el) => firstChild(el).exists(isList);
27199
+ const hasLastChildList = (el) => lastChild(el).exists(isList);
27200
+ const canIncreaseDepthOfList = (editor, amount) => {
27201
+ return getListMaxDepth(editor).map((max) => max >= amount).getOr(true);
27202
+ };
27203
+
27048
27204
  const listNames = ['OL', 'UL', 'DL'];
27049
27205
  const listSelector = listNames.join(',');
27050
27206
  const getParentList = (editor, node) => {
27051
27207
  const selectionStart = node || editor.selection.getStart(true);
27052
- return editor.dom.getParent(selectionStart, listSelector, getClosestListHost(editor, selectionStart));
27208
+ return editor.dom.getParent(selectionStart, listSelector, getClosestListHost(editor, selectionStart, editor.selection.isCollapsed()));
27053
27209
  };
27054
27210
  const isParentListSelected = (parentList, selectedBlocks) => isNonNullable(parentList) && selectedBlocks.length === 1 && selectedBlocks[0] === parentList;
27055
27211
  const findSubLists = (parentList) => filter$5(parentList.querySelectorAll(listSelector), isListNode);
@@ -27065,16 +27221,16 @@
27065
27221
  });
27066
27222
  }
27067
27223
  };
27068
- const findParentListItemsNodes = (editor, elms) => {
27224
+ const findParentListItemsNodes = (editor, elms, isCollapsed) => {
27069
27225
  const listItemsElms = Tools.map(elms, (elm) => {
27070
- const parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListHost(editor, elm));
27226
+ const parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListHost(editor, elm, isCollapsed));
27071
27227
  return parentLi ? parentLi : elm;
27072
27228
  });
27073
27229
  return unique$1(listItemsElms);
27074
27230
  };
27075
27231
  const getSelectedListItems = (editor) => {
27076
27232
  const selectedBlocks = editor.selection.getSelectedBlocks();
27077
- return filter$5(findParentListItemsNodes(editor, selectedBlocks), isListItemNode);
27233
+ return filter$5(findParentListItemsNodes(editor, selectedBlocks, editor.selection.isCollapsed()), isListItemNode);
27078
27234
  };
27079
27235
  const getSelectedDlItems = (editor) => filter$5(getSelectedListItems(editor), isDlItemNode);
27080
27236
  const getClosestEditingHost = (editor, elm) => {
@@ -27082,17 +27238,36 @@
27082
27238
  return parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody();
27083
27239
  };
27084
27240
  const isListHost = (schema, node) => !isListNode(node) && !isListItemNode(node) && exists(listNames, (listName) => schema.isValidChild(node.nodeName, listName));
27085
- const getClosestListHost = (editor, elm) => {
27241
+ const requireLiElementFirst = (parentBlocks) => {
27242
+ const result = findMap(parentBlocks, (element) => {
27243
+ if (isListItem$1(SugarElement.fromDom(element))) {
27244
+ return Optional.some(true);
27245
+ }
27246
+ if (isTableCellNode(element)) {
27247
+ return Optional.some(false);
27248
+ }
27249
+ return Optional.none();
27250
+ });
27251
+ return result.getOr(false);
27252
+ };
27253
+ const getClosestListHost = (editor, elm, isCollapsed) => {
27086
27254
  const parentBlocks = editor.dom.getParents(elm, editor.dom.isBlock);
27255
+ let foundListBlock = !requireLiElementFirst(parentBlocks);
27087
27256
  const isNotForcedRootBlock = (elm) => elm.nodeName.toLowerCase() !== getForcedRootBlock(editor);
27088
- const parentBlock = find$2(parentBlocks, (elm) => isNotForcedRootBlock(elm) && isListHost(editor.schema, elm));
27257
+ const checkListRequirement = (element) => {
27258
+ if (isListItem$1(SugarElement.fromDom(element)) || isList(SugarElement.fromDom(element))) {
27259
+ foundListBlock = true;
27260
+ }
27261
+ return foundListBlock;
27262
+ };
27263
+ const parentBlock = find$2(parentBlocks, (elm) => checkListRequirement(elm) && (!isCollapsed || isNotForcedRootBlock(elm)) && isListHost(editor.schema, elm));
27089
27264
  return parentBlock.getOr(editor.getBody());
27090
27265
  };
27091
27266
  const isListInsideAnLiWithFirstAndLastNotListElement = (list) => parent(list).exists((parent) => isListItemNode(parent.dom)
27092
27267
  && firstChild(parent).exists((firstChild) => !isListNode(firstChild.dom))
27093
27268
  && lastChild(parent).exists((lastChild) => !isListNode(lastChild.dom)));
27094
27269
  const findLastParentListNode = (editor, elm) => {
27095
- const parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListHost(editor, elm));
27270
+ const parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListHost(editor, elm, true));
27096
27271
  return last$2(parentLists);
27097
27272
  };
27098
27273
  const getSelectedLists = (editor) => {
@@ -27102,7 +27277,7 @@
27102
27277
  };
27103
27278
  const getParentLists = (editor) => {
27104
27279
  const elm = editor.selection.getStart();
27105
- return editor.dom.getParents(elm, 'ol,ul', getClosestListHost(editor, elm));
27280
+ return editor.dom.getParents(elm, 'ol,ul', getClosestListHost(editor, elm, editor.selection.isCollapsed()));
27106
27281
  };
27107
27282
  const getSelectedListRoots = (editor) => {
27108
27283
  const selectedLists = getSelectedLists(editor);
@@ -27168,14 +27343,6 @@
27168
27343
  return fragment;
27169
27344
  };
27170
27345
 
27171
- const isList = (el) => is$1(el, 'OL,UL');
27172
- const isListItem$1 = (el) => is$1(el, 'LI');
27173
- const hasFirstChildList = (el) => firstChild(el).exists(isList);
27174
- const hasLastChildList = (el) => lastChild(el).exists(isList);
27175
- const canIncreaseDepthOfList = (editor, amount) => {
27176
- return getListMaxDepth(editor).map((max) => max >= amount).getOr(true);
27177
- };
27178
-
27179
27346
  const isEntryList = (entry) => 'listAttributes' in entry;
27180
27347
  const isEntryComment = (entry) => 'isComment' in entry;
27181
27348
  const isEntryFragment = (entry) => 'isFragment' in entry;
@@ -27225,7 +27392,7 @@
27225
27392
  };
27226
27393
  const populateSegments = (segments, entry) => {
27227
27394
  for (let i = 0; i < segments.length - 1; i++) {
27228
- set$2(segments[i].item, 'list-style-type', 'none');
27395
+ set$3(segments[i].item, 'list-style-type', 'none');
27229
27396
  }
27230
27397
  last$2(segments).each((segment) => {
27231
27398
  if (isEntryList(entry)) {
@@ -27715,7 +27882,7 @@
27715
27882
  const applyList = (editor, listName, detail) => {
27716
27883
  const rng = editor.selection.getRng();
27717
27884
  let listItemName = 'LI';
27718
- const root = getClosestListHost(editor, getRootSearchStart(editor, rng));
27885
+ const root = getClosestListHost(editor, getRootSearchStart(editor, rng), rng.collapsed);
27719
27886
  const dom = editor.dom;
27720
27887
  if (dom.getContentEditable(editor.selection.getNode()) === 'false') {
27721
27888
  return;
@@ -28095,19 +28262,12 @@
28095
28262
  const startListParent = editor.dom.getParent(selectionStartElm, 'LI,DT,DD', root);
28096
28263
  return isNonNullable(startListParent) || getSelectedListItems(editor).length > 0;
28097
28264
  };
28098
- const backspaceDeleteRange$1 = (editor) => {
28265
+ const backspaceDeleteRange$1 = (editor, isForward) => {
28099
28266
  if (hasListSelection(editor)) {
28100
28267
  editor.undoManager.transact(() => {
28101
- // Some delete actions may prevent the input event from being fired. If we do not detect it, we fire it ourselves.
28102
- let shouldFireInput = true;
28103
- const inputHandler = () => shouldFireInput = false;
28104
- editor.on('input', inputHandler);
28105
- editor.execCommand('Delete');
28106
- editor.off('input', inputHandler);
28107
- if (shouldFireInput) {
28108
- editor.dispatch('input');
28268
+ if (symulateDelete(editor, isForward, () => editor.execCommand('Delete'))) {
28269
+ normalizeLists(editor.dom, editor.getBody());
28109
28270
  }
28110
- normalizeLists(editor.dom, editor.getBody());
28111
28271
  });
28112
28272
  return true;
28113
28273
  }
@@ -28116,7 +28276,7 @@
28116
28276
  const backspaceDelete$c = (editor, isForward) => {
28117
28277
  const selection = editor.selection;
28118
28278
  return !isWithinNonEditableList$1(editor, selection.getNode()) && (selection.isCollapsed() ?
28119
- backspaceDeleteCaret$1(editor, isForward) : backspaceDeleteRange$1(editor));
28279
+ backspaceDeleteCaret$1(editor, isForward) : backspaceDeleteRange$1(editor, isForward));
28120
28280
  };
28121
28281
 
28122
28282
  const blockPosition = (block, position) => ({
@@ -29538,7 +29698,7 @@
29538
29698
  const parseIndentValue = (value) => toInt(value ?? '').getOr(0);
29539
29699
  const getIndentStyleName = (useMargin, element) => {
29540
29700
  const indentStyleName = useMargin || isTable$1(element) ? 'margin' : 'padding';
29541
- const suffix = get$7(element, 'direction') === 'rtl' ? '-right' : '-left';
29701
+ const suffix = get$8(element, 'direction') === 'rtl' ? '-right' : '-left';
29542
29702
  return indentStyleName + suffix;
29543
29703
  };
29544
29704
  const indentElement = (dom, command, useMargin, value, unit, element) => {
@@ -29603,9 +29763,10 @@
29603
29763
  };
29604
29764
 
29605
29765
  const deleteRange = (editor, forward) => {
29606
- const rng = normalize(editor.selection.getRng());
29766
+ const range = editor.selection.getRng();
29767
+ const rng = normalize(range);
29607
29768
  return isSelectionOverWholeHTMLElement(rng)
29608
- ? Optional.some(() => deleteElement$2(editor, forward, SugarElement.fromDom(editor.selection.getNode())))
29769
+ ? Optional.some(() => deleteElement$2(editor, forward, SugarElement.fromDom(range.startContainer.childNodes[range.startOffset])))
29609
29770
  : Optional.none();
29610
29771
  };
29611
29772
  const backspaceDelete$1 = (editor, forward) => editor.selection.isCollapsed() ? Optional.none() : deleteRange(editor, forward);
@@ -30349,7 +30510,7 @@
30349
30510
  }
30350
30511
  return contains$2(['br', 'img', 'hr', 'input'], name(element));
30351
30512
  };
30352
- const isNonEditable = (element) => isElement$8(element) && get$9(element, 'contenteditable') === 'false';
30513
+ const isNonEditable = (element) => isElement$8(element) && get$a(element, 'contenteditable') === 'false';
30353
30514
  const comparePosition = (element, other) => {
30354
30515
  return element.dom.compareDocumentPosition(other.dom);
30355
30516
  };
@@ -30376,14 +30537,14 @@
30376
30537
  predicate: descendants$1
30377
30538
  }),
30378
30539
  styles: constant({
30379
- get: get$7,
30540
+ get: get$8,
30380
30541
  getRaw: getRaw$1,
30381
- set: set$2,
30542
+ set: set$3,
30382
30543
  remove: remove$7
30383
30544
  }),
30384
30545
  attrs: constant({
30385
- get: get$9,
30386
- set: set$4,
30546
+ get: get$a,
30547
+ set: set$5,
30387
30548
  remove: remove$9,
30388
30549
  copyTo: copyAttributesTo
30389
30550
  }),
@@ -30420,8 +30581,8 @@
30420
30581
  isElement: isElement$8,
30421
30582
  isSpecial,
30422
30583
  getLanguage,
30423
- getText: get$4,
30424
- setText: set$1,
30584
+ getText: get$5,
30585
+ setText: set$2,
30425
30586
  isBoundary,
30426
30587
  isEmptyTag,
30427
30588
  isNonEditable
@@ -31449,32 +31610,6 @@
31449
31610
  const backspaceDelete = (editor, forward, granularity) => shouldPreventDeleteAction(editor, forward, granularity) || isSafari && handleDeleteActionSafari(editor, forward, granularity)
31450
31611
  ? Optional.some(noop) : Optional.none();
31451
31612
 
31452
- const createAndFireInputEvent = (eventType) => (editor, inputType, specifics = {}) => {
31453
- const target = editor.getBody();
31454
- const overrides = {
31455
- bubbles: true,
31456
- composed: true,
31457
- data: null,
31458
- isComposing: false,
31459
- detail: 0,
31460
- view: null,
31461
- target,
31462
- currentTarget: target,
31463
- eventPhase: Event.AT_TARGET,
31464
- originalTarget: target,
31465
- explicitOriginalTarget: target,
31466
- isTrusted: false,
31467
- srcElement: target,
31468
- cancelable: false,
31469
- preventDefault: noop,
31470
- inputType
31471
- };
31472
- const input = clone$2(new InputEvent(eventType));
31473
- return editor.dispatch(eventType, { ...input, ...overrides, ...specifics });
31474
- };
31475
- const fireInputEvent = createAndFireInputEvent('input');
31476
- const fireBeforeInputEvent = createAndFireInputEvent('beforeinput');
31477
-
31478
31613
  const platform$2 = detect$1();
31479
31614
  const os = platform$2.os;
31480
31615
  const isMacOSOriOS = os.isMacOS() || os.isiOS();
@@ -31563,19 +31698,21 @@
31563
31698
  // track backspace keydown state for emulating Meta + Backspace keyup detection on macOS
31564
31699
  let isBackspaceKeydown = false;
31565
31700
  let formatNodes = [];
31566
- editor.on('keydown', (evt) => {
31567
- isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
31568
- formatNodes = getFormatNodesAtStart(editor);
31569
- if (!evt.isDefaultPrevented()) {
31570
- executeKeydownOverride$3(editor, caret, evt);
31571
- }
31572
- });
31573
- editor.on('keyup', (evt) => {
31574
- if (!evt.isDefaultPrevented()) {
31575
- executeKeyupOverride(editor, evt, isBackspaceKeydown, formatNodes);
31576
- formatNodes.length = 0;
31577
- }
31578
- isBackspaceKeydown = false;
31701
+ editor.on('init', () => {
31702
+ editor.on('keydown', (evt) => {
31703
+ isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
31704
+ formatNodes = getFormatNodesAtStart(editor);
31705
+ if (!evt.isDefaultPrevented()) {
31706
+ executeKeydownOverride$3(editor, caret, evt);
31707
+ }
31708
+ });
31709
+ editor.on('keyup', (evt) => {
31710
+ if (!evt.isDefaultPrevented()) {
31711
+ executeKeyupOverride(editor, evt, isBackspaceKeydown, formatNodes);
31712
+ formatNodes.length = 0;
31713
+ }
31714
+ isBackspaceKeydown = false;
31715
+ });
31579
31716
  });
31580
31717
  };
31581
31718
 
@@ -31613,16 +31750,15 @@
31613
31750
  if (!root) {
31614
31751
  return;
31615
31752
  }
31616
- if (/^(LI|DT|DD)$/.test(root.nodeName)) {
31617
- const isList = (e) => /^(ul|ol|dl)$/.test(name(e));
31618
- const findFirstList = (e) => isList(e) ? Optional.from(e) : descendant$2(e, isList);
31753
+ if (isListItem$2(SugarElement.fromDom(root))) {
31754
+ const findFirstList = (e) => isList$1(e) ? Optional.from(e) : descendant$2(e, isList$1);
31619
31755
  const isEmpty = (e) => dom.isEmpty(e.dom);
31620
31756
  firstNonWhiteSpaceNodeSibling(root.firstChild).each((firstChild) => {
31621
31757
  findFirstList(firstChild).fold(() => {
31622
31758
  if (isEmpty(firstChild)) {
31623
31759
  const element = toLeaf$1(firstChild, 0).element;
31624
31760
  if (isElement$8(element) && !isBr$6(element)) {
31625
- append$1(element, SugarElement.fromText(nbsp));
31761
+ append$1(element, SugarElement.fromHtml('<br data-mce-bogus="1" />'));
31626
31762
  }
31627
31763
  }
31628
31764
  }, (firstList) => {
@@ -32154,6 +32290,16 @@
32154
32290
  }
32155
32291
  return true;
32156
32292
  };
32293
+ const isInsideLiBeforeAList = (newBlock) => {
32294
+ const nextSibling$1 = firstChild(newBlock).bind(nextSibling);
32295
+ return isListItem$2(newBlock) && nextSibling$1.exists(isList$1);
32296
+ };
32297
+ const trimEmptySpacesInLeftLeaf = (newBlock) => {
32298
+ const leaf = toLeaf$1(SugarElement.fromDom(newBlock), 0).element;
32299
+ if (isText$c(leaf) && dom.isEmpty(leaf.dom)) {
32300
+ leaf.dom.remove();
32301
+ }
32302
+ };
32157
32303
  const insertNewBlockAfter = () => {
32158
32304
  let block;
32159
32305
  // If the caret is at the end of a header we produce a P tag after it similar to Word unless we are in a hgroup
@@ -32289,8 +32435,13 @@
32289
32435
  else {
32290
32436
  dom.insertAfter(fragment, parentBlock);
32291
32437
  }
32292
- trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
32293
- addBrToBlockIfNeeded(dom, parentBlock);
32438
+ if (!isInsideLiBeforeAList(SugarElement.fromDom(newBlock))) {
32439
+ trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
32440
+ addBrToBlockIfNeeded(dom, parentBlock);
32441
+ }
32442
+ else {
32443
+ trimEmptySpacesInLeftLeaf(newBlock);
32444
+ }
32294
32445
  if (dom.isEmpty(parentBlock)) {
32295
32446
  emptyBlock(parentBlock);
32296
32447
  }
@@ -32910,17 +33061,23 @@
32910
33061
  };
32911
33062
 
32912
33063
  const setup$e = (editor) => {
32913
- editor.on('keydown', (e) => {
32914
- if (e.keyCode === VK.BACKSPACE) {
32915
- if (backspaceDelete$c(editor, false)) {
32916
- e.preventDefault();
33064
+ editor.on('init', () => {
33065
+ // Init is done after the editor's setup. This places our keydown after any keydowns registered in the setup function, so they can do default prevent.
33066
+ editor.on('keydown', (e) => {
33067
+ if (e.defaultPrevented) {
33068
+ return;
32917
33069
  }
32918
- }
32919
- else if (e.keyCode === VK.DELETE) {
32920
- if (backspaceDelete$c(editor, true)) {
32921
- e.preventDefault();
33070
+ if (e.keyCode === VK.BACKSPACE) {
33071
+ if (backspaceDelete$c(editor, false)) {
33072
+ e.preventDefault();
33073
+ }
32922
33074
  }
32923
- }
33075
+ else if (e.keyCode === VK.DELETE) {
33076
+ if (backspaceDelete$c(editor, true)) {
33077
+ e.preventDefault();
33078
+ }
33079
+ }
33080
+ });
32924
33081
  });
32925
33082
  };
32926
33083
 
@@ -34950,7 +35107,7 @@
34950
35107
  const doc = editor.getDoc();
34951
35108
  const realSelectionContainer = descendant$1(body, '#' + realSelectionId).getOrThunk(() => {
34952
35109
  const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc);
34953
- set$4(newContainer, 'id', realSelectionId);
35110
+ set$5(newContainer, 'id', realSelectionId);
34954
35111
  append$1(body, newContainer);
34955
35112
  return newContainer;
34956
35113
  });
@@ -35542,9 +35699,9 @@
35542
35699
  * as it feels to be the expected behavior.
35543
35700
  */
35544
35701
  const text = SugarElement.fromDom(node);
35545
- const textContent = get$4(text);
35702
+ const textContent = get$5(text);
35546
35703
  if (startsWithSingleSpace(textContent)) {
35547
- set$1(text, textContent.slice(1));
35704
+ set$2(text, textContent.slice(1));
35548
35705
  }
35549
35706
  });
35550
35707
  };
@@ -35780,14 +35937,14 @@
35780
35937
  }
35781
35938
  // Manually empty the editor
35782
35939
  e.preventDefault();
35783
- editor.setContent('');
35784
- if (body.firstChild && dom.isBlock(body.firstChild)) {
35785
- editor.selection.setCursorLocation(body.firstChild, 0);
35786
- }
35787
- else {
35788
- editor.selection.setCursorLocation(body, 0);
35940
+ if (symulateDelete(editor, keyCode === DELETE, () => editor.setContent(''))) {
35941
+ if (body.firstChild && dom.isBlock(body.firstChild)) {
35942
+ editor.selection.setCursorLocation(body.firstChild, 0);
35943
+ }
35944
+ else {
35945
+ editor.selection.setCursorLocation(body, 0);
35946
+ }
35789
35947
  }
35790
- editor.nodeChanged();
35791
35948
  }
35792
35949
  });
35793
35950
  };
@@ -36441,7 +36598,7 @@
36441
36598
  };
36442
36599
  const loadComponentsForInlineEditor = (componentUrls) => {
36443
36600
  return mapToArray(componentUrls, (url, elementName) => {
36444
- return get$a(hostWindowComponentScripts, url).getOrThunk(() => {
36601
+ return get$b(hostWindowComponentScripts, url).getOrThunk(() => {
36445
36602
  // Only load the component if it hasn't already been loaded in inline mode the page might have already loaded it
36446
36603
  if (isNullable(window.customElements.get(elementName))) {
36447
36604
  const loadPromise = loadComponent(url, getDocument());
@@ -36494,7 +36651,7 @@
36494
36651
  const body = SugarElement.fromDom(editor.getBody());
36495
36652
  const container = getStyleContainer(getRootNode(body));
36496
36653
  const style = SugarElement.fromTag('style');
36497
- set$4(style, 'type', 'text/css');
36654
+ set$5(style, 'type', 'text/css');
36498
36655
  append$1(style, SugarElement.fromText(text));
36499
36656
  append$1(container, style);
36500
36657
  editor.on('remove', () => {
@@ -36689,11 +36846,11 @@
36689
36846
  };
36690
36847
  const getStyleSheetLoader$1 = (editor) => editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader;
36691
36848
  const makeStylesheetLoadingPromises = (editor, css, framedFonts) => {
36692
- const { pass: bundledCss, fail: normalCss } = partition$2(css, (name) => tinymce.Resource.has(toContentSkinResourceName(name)));
36693
- const bundledPromises = bundledCss.map((url) => {
36694
- const css = tinymce.Resource.get(toContentSkinResourceName(url));
36849
+ const { pass: bundledCss, fail: normalCss } = partition$2(css, (key) => tinymce.Resource.has(key));
36850
+ const bundledPromises = bundledCss.map((key) => {
36851
+ const css = tinymce.Resource.get(key);
36695
36852
  if (isString(css)) {
36696
- return Promise.resolve(getStyleSheetLoader$1(editor).loadRawCss(url, css));
36853
+ return Promise.resolve(getStyleSheetLoader$1(editor).loadRawCss(key, css));
36697
36854
  }
36698
36855
  return Promise.resolve();
36699
36856
  });
@@ -36809,6 +36966,11 @@
36809
36966
  editor.bodyElement = targetElm;
36810
36967
  editor.contentAreaContainer = targetElm;
36811
36968
  }
36969
+ const contentLanguage = getContentLanguage(editor);
36970
+ if (contentLanguage) {
36971
+ const langTarget = editor.inline ? targetElm : doc.documentElement;
36972
+ DOM$6.setAttrib(langTarget, 'lang', contentLanguage);
36973
+ }
36812
36974
  // It will not steal focus while setting contentEditable
36813
36975
  const body = editor.getBody();
36814
36976
  // disabled isn't valid on all body elements, so need to cast here
@@ -36853,7 +37015,9 @@
36853
37015
  setup$b(editor);
36854
37016
  setup$u(editor);
36855
37017
  setup$6(editor);
36856
- setup$s(editor);
37018
+ if (shouldAllowNonEditable(editor)) {
37019
+ setup$s(editor);
37020
+ }
36857
37021
  if (!isRtc(editor)) {
36858
37022
  setup$5(editor);
36859
37023
  setup$1(editor);
@@ -36894,7 +37058,7 @@
36894
37058
  const createIframeElement = (id, title, customAttrs, tabindex) => {
36895
37059
  const iframe = SugarElement.fromTag('iframe');
36896
37060
  // This can also be explicitly set by customAttrs, so do this first
36897
- tabindex.each((t) => set$4(iframe, 'tabindex', t));
37061
+ tabindex.each((t) => set$5(iframe, 'tabindex', t));
36898
37062
  setAll$1(iframe, customAttrs);
36899
37063
  setAll$1(iframe, {
36900
37064
  id: id + '_ifr',
@@ -37584,7 +37748,7 @@
37584
37748
  };
37585
37749
  const getSection = (sectionResult, name, defaults = {}) => {
37586
37750
  const sections = sectionResult.sections();
37587
- const sectionOptions = get$a(sections, name).getOr({});
37751
+ const sectionOptions = get$b(sections, name).getOr({});
37588
37752
  return Tools.extend({}, defaults, sectionOptions);
37589
37753
  };
37590
37754
  const hasSection = (sectionResult, name) => {
@@ -37599,7 +37763,7 @@
37599
37763
  table_grid: false, // Table grid relies on hover, which isn't available for touch devices so use the dialog instead
37600
37764
  object_resizing: false, // No nice way to do object resizing at this stage
37601
37765
  resize: false, // Editor resize doesn't make sense on mobile
37602
- toolbar_mode: get$a(mobileOptions, 'toolbar_mode').getOr('scrolling'), // Use the default side-scrolling toolbar for tablets/phones
37766
+ toolbar_mode: get$b(mobileOptions, 'toolbar_mode').getOr('scrolling'), // Use the default side-scrolling toolbar for tablets/phones
37603
37767
  toolbar_sticky: false // Only enable sticky toolbar on desktop by default
37604
37768
  };
37605
37769
  const defaultPhoneOptions = {
@@ -37847,7 +38011,7 @@
37847
38011
  const getSpecifiedFontProp = (propName, rootElm, elm) => {
37848
38012
  const getProperty = (elm) => getRaw$1(elm, propName).orThunk(() => {
37849
38013
  if (isFont(elm)) {
37850
- return get$a(legacyPropNames, propName).bind((legacyPropName) => getOpt(elm, legacyPropName));
38014
+ return get$b(legacyPropNames, propName).bind((legacyPropName) => getOpt(elm, legacyPropName));
37851
38015
  }
37852
38016
  else {
37853
38017
  return Optional.none();
@@ -37938,8 +38102,8 @@
37938
38102
  const specifiedStyle = closest$1(elm, (elm) => getRaw$1(elm, 'line-height'), curry(eq, root));
37939
38103
  const computedStyle = () => {
37940
38104
  // Css.get returns computed values (in px), and parseFloat will strip any non-number suffix
37941
- const lineHeight = parseFloat(get$7(elm, 'line-height'));
37942
- const fontSize = parseFloat(get$7(elm, 'font-size'));
38105
+ const lineHeight = parseFloat(get$8(elm, 'line-height'));
38106
+ const fontSize = parseFloat(get$8(elm, 'font-size'));
37943
38107
  return String(lineHeight / fontSize);
37944
38108
  };
37945
38109
  return specifiedStyle.getOrThunk(computedStyle);
@@ -38967,12 +39131,12 @@
38967
39131
  processor
38968
39132
  };
38969
39133
  // Setup the initial values
38970
- const initValue = get$a(values, name).orThunk(() => get$a(initialOptions, name));
39134
+ const initValue = get$b(values, name).orThunk(() => get$b(initialOptions, name));
38971
39135
  initValue.each((value) => setValue(name, value, processor));
38972
39136
  };
38973
39137
  const isRegistered = (name) => has$2(registry, name);
38974
- const get = (name) => get$a(values, name)
38975
- .orThunk(() => get$a(registry, name).map((spec) => spec.default))
39138
+ const get = (name) => get$b(values, name)
39139
+ .orThunk(() => get$b(registry, name).map((spec) => spec.default))
38976
39140
  .getOrUndefined();
38977
39141
  const set = (name, value) => {
38978
39142
  if (!isRegistered(name)) {
@@ -40581,14 +40745,14 @@
40581
40745
  * @property minorVersion
40582
40746
  * @type String
40583
40747
  */
40584
- minorVersion: '3.2',
40748
+ minorVersion: '5.0',
40585
40749
  /**
40586
40750
  * Release date of TinyMCE build.
40587
40751
  *
40588
40752
  * @property releaseDate
40589
40753
  * @type String
40590
40754
  */
40591
- releaseDate: '2026-01-14',
40755
+ releaseDate: '2026-04-29',
40592
40756
  /**
40593
40757
  * Collection of language pack data.
40594
40758
  *
@@ -40760,7 +40924,7 @@
40760
40924
  const createId = (elm) => {
40761
40925
  let id = elm.id;
40762
40926
  if (!id) {
40763
- id = get$a(elm, 'name').filter((name) => !DOM.get(name)).getOrThunk(DOM.uniqueId);
40927
+ id = get$b(elm, 'name').filter((name) => !DOM.get(name)).getOrThunk(DOM.uniqueId);
40764
40928
  elm.setAttribute('id', id);
40765
40929
  }
40766
40930
  return id;
@@ -41100,7 +41264,7 @@
41100
41264
  const FakeClipboardItem = (items) => ({
41101
41265
  items,
41102
41266
  types: keys(items),
41103
- getType: (type) => get$a(items, type).getOrUndefined()
41267
+ getType: (type) => get$b(items, type).getOrUndefined()
41104
41268
  });
41105
41269
  const write = (data) => {
41106
41270
  dataValue.set(data);