tinymce-rails 8.4.0 → 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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/source/tinymce/tinymce.js +203 -139
  3. data/lib/tinymce/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.css +1 -1
  5. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.css +1 -1
  6. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.js +1 -1
  7. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.min.css +1 -1
  8. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.js +1 -1
  9. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.min.css +1 -1
  10. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.css +1 -1
  11. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.js +1 -1
  12. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.min.css +1 -1
  13. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.css +1 -1
  14. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.css +1 -1
  15. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.js +1 -1
  16. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.min.css +1 -1
  17. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.js +1 -1
  18. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.min.css +1 -1
  19. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.css +1 -1
  20. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.js +1 -1
  21. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.min.css +1 -1
  22. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.css +1 -1
  23. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.css +1 -1
  24. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.js +1 -1
  25. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.min.css +1 -1
  26. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.js +1 -1
  27. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.min.css +1 -1
  28. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.css +1 -1
  29. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.js +1 -1
  30. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.min.css +1 -1
  31. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.css +1 -1
  32. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.css +1 -1
  33. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.js +1 -1
  34. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css +1 -1
  35. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.js +1 -1
  36. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.min.css +1 -1
  37. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.css +1 -1
  38. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.js +1 -1
  39. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.min.css +1 -1
  40. data/vendor/assets/javascripts/tinymce/themes/silver/theme.js +1 -1
  41. data/vendor/assets/javascripts/tinymce/tinymce.d.ts +1 -0
  42. data/vendor/assets/javascripts/tinymce/tinymce.js +2 -2
  43. metadata +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * TinyMCE version 8.4.0 (2026-03-31)
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
@@ -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];
@@ -6163,7 +6168,7 @@
6163
6168
  remove$9(elm, name);
6164
6169
  }
6165
6170
  else {
6166
- set$4(elm, name, value);
6171
+ set$5(elm, name, value);
6167
6172
  }
6168
6173
  };
6169
6174
  // Convert camel cased names back to hyphenated names
@@ -6186,7 +6191,7 @@
6186
6191
  return idx;
6187
6192
  };
6188
6193
  const updateInternalStyleAttr = (styles, elm) => {
6189
- const rawValue = get$9(elm, 'style');
6194
+ const rawValue = get$a(elm, 'style');
6190
6195
  const value = styles.serialize(styles.parse(rawValue), name(elm));
6191
6196
  legacySetAttribute(elm, internalStyleName, value);
6192
6197
  };
@@ -6204,7 +6209,7 @@
6204
6209
  remove$7($elm, normalizedName);
6205
6210
  }
6206
6211
  else {
6207
- set$2($elm, normalizedName, convertStyleToString(cssValue, normalizedName));
6212
+ set$3($elm, normalizedName, convertStyleToString(cssValue, normalizedName));
6208
6213
  }
6209
6214
  };
6210
6215
  const setupAttrHooks = (styles, settings, getContext) => {
@@ -6221,7 +6226,7 @@
6221
6226
  },
6222
6227
  get: (elm, name) => {
6223
6228
  const sugarElm = SugarElement.fromDom(elm);
6224
- return get$9(sugarElm, 'data-mce-' + name) || get$9(sugarElm, name);
6229
+ return get$a(sugarElm, 'data-mce-' + name) || get$a(sugarElm, name);
6225
6230
  }
6226
6231
  };
6227
6232
  const attrHooks = {
@@ -6240,7 +6245,7 @@
6240
6245
  },
6241
6246
  get: (elm) => {
6242
6247
  const sugarElm = SugarElement.fromDom(elm);
6243
- const value = get$9(sugarElm, internalStyleName) || get$9(sugarElm, 'style');
6248
+ const value = get$a(sugarElm, internalStyleName) || get$a(sugarElm, 'style');
6244
6249
  return styles.serialize(styles.parse(value), name(sugarElm));
6245
6250
  }
6246
6251
  }
@@ -6318,7 +6323,7 @@
6318
6323
  value = hook.get($elm.dom, name);
6319
6324
  }
6320
6325
  else {
6321
- value = get$9($elm, name);
6326
+ value = get$a($elm, name);
6322
6327
  }
6323
6328
  }
6324
6329
  return isNonNullable(value) ? value : defaultVal;
@@ -6332,7 +6337,7 @@
6332
6337
  if (isElement$7(e)) {
6333
6338
  const $elm = SugarElement.fromDom(e);
6334
6339
  const val = value === '' ? null : value;
6335
- const originalValue = get$9($elm, name);
6340
+ const originalValue = get$a($elm, name);
6336
6341
  const hook = attrHooks[name];
6337
6342
  if (hook && hook.set) {
6338
6343
  hook.set($elm.dom, val, name);
@@ -6391,7 +6396,7 @@
6391
6396
  return undefined;
6392
6397
  }
6393
6398
  if (computed) {
6394
- return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name));
6399
+ return get$8(SugarElement.fromDom($elm), camelCaseToHyphens(name));
6395
6400
  }
6396
6401
  else {
6397
6402
  // Camelcase it, if needed
@@ -6529,7 +6534,7 @@
6529
6534
  const setHTML = (elm, html) => {
6530
6535
  run(elm, (e) => {
6531
6536
  const $elm = SugarElement.fromDom(e);
6532
- set$3($elm, html);
6537
+ set$4($elm, html);
6533
6538
  });
6534
6539
  };
6535
6540
  const add = (parentElm, name, attrs, html, create) => run(parentElm, (parentElm) => {
@@ -6682,7 +6687,7 @@
6682
6687
  run(elm, (e) => remove$7(SugarElement.fromDom(e), 'display'));
6683
6688
  };
6684
6689
  const hide = (elm) => {
6685
- run(elm, (e) => set$2(SugarElement.fromDom(e), 'display', 'none'));
6690
+ run(elm, (e) => set$3(SugarElement.fromDom(e), 'display', 'none'));
6686
6691
  };
6687
6692
  const isHidden = (elm) => {
6688
6693
  const $elm = _get(elm);
@@ -7738,7 +7743,7 @@
7738
7743
  const self = this;
7739
7744
  const execCallbacks = (name, url) => {
7740
7745
  // Execute URL callback functions
7741
- get$a(self.scriptLoadedCallbacks, url).each((callbacks) => {
7746
+ get$b(self.scriptLoadedCallbacks, url).each((callbacks) => {
7742
7747
  each$e(callbacks, (callback) => callback[name](url));
7743
7748
  });
7744
7749
  delete self.scriptLoadedCallbacks[url];
@@ -7838,7 +7843,7 @@
7838
7843
  const isTokenised = (str) => isArray$1(str) && str.length > 1;
7839
7844
  const data = {};
7840
7845
  const currentCode = Cell('en');
7841
- const getLanguageData = () => get$a(data, currentCode.get());
7846
+ const getLanguageData = () => get$b(data, currentCode.get());
7842
7847
  const getData$1 = () => map$2(data, (value) => ({ ...value }));
7843
7848
  /**
7844
7849
  * Sets the current language code.
@@ -7918,7 +7923,7 @@
7918
7923
  const textStr = toString(text);
7919
7924
  return has$2(langData, textStr)
7920
7925
  ? toString(langData[textStr])
7921
- : get$a(langData, textStr.toLowerCase()).map(toString).getOr(textStr);
7926
+ : get$b(langData, textStr.toLowerCase()).map(toString).getOr(textStr);
7922
7927
  };
7923
7928
  const removeContext = (str) => str.replace(/{context:\w+}$/, '');
7924
7929
  const replaceWithEllipsisChar = (text) => text.replaceAll('...', ellipsis);
@@ -7946,7 +7951,7 @@
7946
7951
  * @return {Boolean} True if the current language pack is rtl.
7947
7952
  */
7948
7953
  const isRtl$1 = () => getLanguageData()
7949
- .bind((items) => get$a(items, '_dir'))
7954
+ .bind((items) => get$b(items, '_dir'))
7950
7955
  .exists((dir) => dir === 'rtl');
7951
7956
  /**
7952
7957
  * Returns true/false if specified language pack exists.
@@ -8169,8 +8174,8 @@
8169
8174
  const directory = {};
8170
8175
  each$e(markers, (m) => {
8171
8176
  if (!isBogusElement(m, body)) {
8172
- const uid = get$9(m, dataAnnotationId());
8173
- const nodesAlready = get$a(directory, uid).getOr([]);
8177
+ const uid = get$a(m, dataAnnotationId());
8178
+ const nodesAlready = get$b(directory, uid).getOr([]);
8174
8179
  directory[uid] = nodesAlready.concat([m]);
8175
8180
  }
8176
8181
  });
@@ -8191,7 +8196,7 @@
8191
8196
  };
8192
8197
  const updateCallbacks = (name, f) => {
8193
8198
  const callbackMap = changeCallbacks.get();
8194
- const data = get$a(callbackMap, name).getOrThunk(initData);
8199
+ const data = get$b(callbackMap, name).getOrThunk(initData);
8195
8200
  const outputData = f(data);
8196
8201
  callbackMap[name] = outputData;
8197
8202
  changeCallbacks.set(callbackMap);
@@ -8212,7 +8217,7 @@
8212
8217
  const toggleActiveAttr = (uid, state) => {
8213
8218
  each$e(findMarkers(editor, uid), (elem) => {
8214
8219
  if (state) {
8215
- set$4(elem, dataAnnotationActive(), 'true');
8220
+ set$5(elem, dataAnnotationActive(), 'true');
8216
8221
  }
8217
8222
  else {
8218
8223
  remove$9(elem, dataAnnotationActive());
@@ -8306,7 +8311,7 @@
8306
8311
  settings
8307
8312
  };
8308
8313
  };
8309
- const lookup = (name) => get$a(annotations, name).map((a) => a.settings);
8314
+ const lookup = (name) => get$b(annotations, name).map((a) => a.settings);
8310
8315
  const getNames = () => keys(annotations);
8311
8316
  return {
8312
8317
  register,
@@ -8420,6 +8425,9 @@
8420
8425
  // WARNING: don't add anything to this file, the intention is to move these checks into the Schema
8421
8426
  const isTable$1 = (node) => name(node) === 'table';
8422
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';
8423
8431
  const isTextBlock$3 = lazyLookup(textBlocks);
8424
8432
  const isList$1 = lazyLookup(lists);
8425
8433
  const isListItem$2 = lazyLookup(listItems$1);
@@ -8445,7 +8453,7 @@
8445
8453
  };
8446
8454
  const createPaddingBr = () => {
8447
8455
  const br = SugarElement.fromTag('br');
8448
- set$4(br, 'data-mce-bogus', '1');
8456
+ set$5(br, 'data-mce-bogus', '1');
8449
8457
  return br;
8450
8458
  };
8451
8459
  const fillWithPaddingBr = (elm) => {
@@ -9651,14 +9659,14 @@
9651
9659
 
9652
9660
  const requiredAccess = (path, obj, key, bundle) =>
9653
9661
  // In required mode, if it is undefined, it is an error.
9654
- get$a(obj, key).fold(() => missingRequired(path, key, obj), bundle);
9662
+ get$b(obj, key).fold(() => missingRequired(path, key, obj), bundle);
9655
9663
  const fallbackAccess = (obj, key, fallback, bundle) => {
9656
- const v = get$a(obj, key).getOrThunk(() => fallback(obj));
9664
+ const v = get$b(obj, key).getOrThunk(() => fallback(obj));
9657
9665
  return bundle(v);
9658
9666
  };
9659
- const optionAccess = (obj, key, bundle) => bundle(get$a(obj, key));
9667
+ const optionAccess = (obj, key, bundle) => bundle(get$b(obj, key));
9660
9668
  const optionDefaultedAccess = (obj, key, fallback, bundle) => {
9661
- 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);
9662
9670
  return bundle(opt);
9663
9671
  };
9664
9672
  const extractField = (field, path, obj, key, prop) => {
@@ -9951,7 +9959,7 @@
9951
9959
  if (valid) {
9952
9960
  if (value.indexOf('=') !== -1) {
9953
9961
  const bodyObj = getHash(value);
9954
- return { value: get$a(bodyObj, editor.id).getOr(defaultValue), valid };
9962
+ return { value: get$b(bodyObj, editor.id).getOr(defaultValue), valid };
9955
9963
  }
9956
9964
  else {
9957
9965
  return { value, valid };
@@ -10183,6 +10191,9 @@
10183
10191
  registerOption('content_style', {
10184
10192
  processor: 'string'
10185
10193
  });
10194
+ registerOption('content_language', {
10195
+ processor: 'string'
10196
+ });
10186
10197
  registerOption('content_css_cors', {
10187
10198
  processor: 'boolean',
10188
10199
  default: false
@@ -10792,6 +10803,7 @@
10792
10803
  const getIndentation = option('indentation');
10793
10804
  const getContentCss = option('content_css');
10794
10805
  const getContentStyle = option('content_style');
10806
+ const getContentLanguage = option('content_language');
10795
10807
  const getFontCss = option('font_css');
10796
10808
  const getDirectionality = option('directionality');
10797
10809
  const getInlineBoundarySelector = option('inline_boundaries_selector');
@@ -11170,7 +11182,7 @@
11170
11182
  .map((elm) => elm.dom)
11171
11183
  .getOr(rootNode);
11172
11184
  };
11173
- 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';
11174
11186
  const isInlineBlock = (node, rootNode) => node.parentNode !== rootNode;
11175
11187
  const isInlineAbsPositionedCEF = (node, rootNode) => isContentEditableFalse$6(node) && isAbsPositionedElement(node) && isInlineBlock(node, rootNode);
11176
11188
  const getParentBlock$3 = (node, rootNode) => {
@@ -12204,7 +12216,7 @@
12204
12216
  const isVariableFormatName = (editor, formatName) => {
12205
12217
  const hasVariableValues = (format) => {
12206
12218
  const isVariableValue = (val) => isFunction(val) || val.length > 1 && val.charAt(0) === '%';
12207
- return exists(['styles', 'attributes'], (key) => get$a(format, key).exists((field) => {
12219
+ return exists(['styles', 'attributes'], (key) => get$b(format, key).exists((field) => {
12208
12220
  const fieldValues = isArray$1(field) ? field : values(field);
12209
12221
  return exists(fieldValues, isVariableValue);
12210
12222
  }));
@@ -12232,7 +12244,7 @@
12232
12244
  const isNonWrappingBlockFormat = (format) => isBlockFormat(format) && format.wrapper !== true;
12233
12245
  const isSelectorFormat = (format) => hasNonNullableKey(format, 'selector');
12234
12246
  const isInlineFormat = (format) => hasNonNullableKey(format, 'inline');
12235
- 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);
12236
12248
  const shouldExpandToSelector = (format) => isSelectorFormat(format) && format.expand !== false && !isInlineFormat(format);
12237
12249
  const getEmptyCaretContainers = (node) => {
12238
12250
  const nodes = [];
@@ -12632,7 +12644,7 @@
12632
12644
  // Footnootes plugin
12633
12645
  'div.mce-footnotes'
12634
12646
  ];
12635
- const isZeroWidth = (elem) => isText$c(elem) && get$4(elem) === ZWSP$1;
12647
+ const isZeroWidth = (elem) => isText$c(elem) && get$5(elem) === ZWSP$1;
12636
12648
  const context = (editor, elem, wrapName, nodeName) => parentElement(elem).fold(() => "skipping" /* ChildContext.Skipping */, (parent) => {
12637
12649
  // We used to skip these, but given that they might be representing empty paragraphs, it probably
12638
12650
  // makes sense to treat them just like text nodes
@@ -12665,18 +12677,18 @@
12665
12677
  const applyAnnotation = (elem, masterUId, data, annotationName, decorate, directAnnotation) => {
12666
12678
  const { uid = masterUId, ...otherData } = data;
12667
12679
  add$2(elem, annotation());
12668
- set$4(elem, `${dataAnnotationId()}`, uid);
12669
- set$4(elem, `${dataAnnotation()}`, annotationName);
12680
+ set$5(elem, `${dataAnnotationId()}`, uid);
12681
+ set$5(elem, `${dataAnnotation()}`, annotationName);
12670
12682
  const { attributes = {}, classes = [] } = decorate(uid, otherData);
12671
12683
  setAll$1(elem, attributes);
12672
12684
  add$1(elem, classes);
12673
12685
  if (directAnnotation) {
12674
12686
  if (classes.length > 0) {
12675
- set$4(elem, `${dataAnnotationClasses()}`, classes.join(','));
12687
+ set$5(elem, `${dataAnnotationClasses()}`, classes.join(','));
12676
12688
  }
12677
12689
  const attributeNames = keys(attributes);
12678
12690
  if (attributeNames.length > 0) {
12679
- set$4(elem, `${dataAnnotationAttributes()}`, attributeNames.join(','));
12691
+ set$5(elem, `${dataAnnotationAttributes()}`, attributeNames.join(','));
12680
12692
  }
12681
12693
  }
12682
12694
  };
@@ -12765,7 +12777,7 @@
12765
12777
  if (selection.getRng().collapsed && !hasFakeSelection) {
12766
12778
  const wrapper = makeAnnotation(editor.getDoc(), masterUid, data, name, settings.decorate);
12767
12779
  // Put something visible in the marker
12768
- set$3(wrapper, nbsp);
12780
+ set$4(wrapper, nbsp);
12769
12781
  selection.getRng().insertNode(wrapper.dom);
12770
12782
  selection.select(wrapper.dom);
12771
12783
  }
@@ -12942,7 +12954,7 @@
12942
12954
  };
12943
12955
 
12944
12956
  const clamp$1 = (offset, element) => {
12945
- 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;
12946
12958
  if (offset > max) {
12947
12959
  return max;
12948
12960
  }
@@ -14192,7 +14204,7 @@
14192
14204
 
14193
14205
  const find = (element) => {
14194
14206
  const doc = getDocument();
14195
- const scroll = get$5(doc);
14207
+ const scroll = get$6(doc);
14196
14208
  const frames = pathTo(element, Navigation);
14197
14209
  const offset = viewport(element);
14198
14210
  const r = foldr(frames, (b, a) => {
@@ -14231,7 +14243,7 @@
14231
14243
  return { element: last, offset: 1 };
14232
14244
  }
14233
14245
  else if (isText$c(last)) {
14234
- return { element: last, offset: get$4(last).length };
14246
+ return { element: last, offset: get$5(last).length };
14235
14247
  }
14236
14248
  else {
14237
14249
  return { element: last, offset: children$1(last).length };
@@ -14241,7 +14253,7 @@
14241
14253
  };
14242
14254
  const markerInfo = (element, cleanupFun) => {
14243
14255
  const pos = absolute(element);
14244
- const height = get$6(element);
14256
+ const height = get$7(element);
14245
14257
  return {
14246
14258
  element,
14247
14259
  bottom: pos.top + height,
@@ -14265,7 +14277,7 @@
14265
14277
  if (fireScrollIntoViewEvent(editor, data)) {
14266
14278
  return;
14267
14279
  }
14268
- const scrollTop = get$5(doc).top;
14280
+ const scrollTop = get$6(doc).top;
14269
14281
  f(editor, doc, scrollTop, marker, alignToTop);
14270
14282
  fireAfterScrollIntoViewEvent(editor, data);
14271
14283
  };
@@ -14948,7 +14960,7 @@
14948
14960
  const trimTemporaryNodes = (tempAttrs, body) => {
14949
14961
  each$e(getTemporaryNodes(tempAttrs, body), (elm) => {
14950
14962
  const element = SugarElement.fromDom(elm);
14951
- if (get$9(element, 'data-mce-bogus') === 'all') {
14963
+ if (get$a(element, 'data-mce-bogus') === 'all') {
14952
14964
  remove$8(element);
14953
14965
  }
14954
14966
  else {
@@ -15001,7 +15013,7 @@
15001
15013
  const cleanupBogusElements = (parent) => {
15002
15014
  const bogusElements = descendants(parent, '[data-mce-bogus]');
15003
15015
  each$e(bogusElements, (elem) => {
15004
- const bogusValue = get$9(elem, 'data-mce-bogus');
15016
+ const bogusValue = get$a(elem, 'data-mce-bogus');
15005
15017
  if (bogusValue === 'all') {
15006
15018
  remove$8(elem);
15007
15019
  }
@@ -15031,13 +15043,13 @@
15031
15043
  const doc = editor.getDoc();
15032
15044
  const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
15033
15045
  const offscreenDiv = SugarElement.fromTag('div', doc);
15034
- set$4(offscreenDiv, 'data-mce-bogus', 'all');
15046
+ set$5(offscreenDiv, 'data-mce-bogus', 'all');
15035
15047
  setAll(offscreenDiv, {
15036
15048
  position: 'fixed',
15037
15049
  left: '-9999999px',
15038
15050
  top: '0'
15039
15051
  });
15040
- set$3(offscreenDiv, body.innerHTML);
15052
+ set$4(offscreenDiv, body.innerHTML);
15041
15053
  cleanupBogusElements(offscreenDiv);
15042
15054
  cleanupInputNames(offscreenDiv);
15043
15055
  // Append the wrapper element so that the browser will evaluate styles when getting the `innerText`
@@ -15429,7 +15441,7 @@
15429
15441
  return isText$b(container) && (container.data.length === 0 || isZwsp(container.data) && BookmarkManager.isBookmarkNode(container.parentNode));
15430
15442
  };
15431
15443
  const matchesElementPosition = (before, predicate) => (pos) => getChildNodeAtRelativeOffset(before ? 0 : -1, pos).filter(predicate).isSome();
15432
- 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';
15433
15445
  const isCefNode = (node) => isContentEditableFalse$a(node) && !isBogusAll(node);
15434
15446
  const isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
15435
15447
  const isAfterImageBlock = matchesElementPosition(false, isImageBlock);
@@ -15500,7 +15512,7 @@
15500
15512
  const isPreValue = (value) => contains$2(['pre', 'pre-wrap'], value);
15501
15513
  const isInPre = (pos) => getElementFromPosition(pos)
15502
15514
  .bind((elm) => closest$5(elm, isElement$8))
15503
- .exists((elm) => isPreValue(get$7(elm, 'white-space')));
15515
+ .exists((elm) => isPreValue(get$8(elm, 'white-space')));
15504
15516
  const isAtBeginningOfBody = (root, pos) => prevPosition(root.dom, pos).isNone();
15505
15517
  const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
15506
15518
  const isAtLineBoundary = (root, pos, schema) => (isAtBeginningOfBody(root, pos) ||
@@ -16123,7 +16135,7 @@
16123
16135
  // Restore the data-mce-selected attribute if multiple cells were selected, as if it was a cef element
16124
16136
  // then selection overrides would remove it as it was using an offscreen selection clone.
16125
16137
  if (selectedCells.length > 1 && exists(selectedCells, (cell) => eq(cell, selectedNode))) {
16126
- set$4(selectedNode, 'data-mce-selected', '1');
16138
+ set$5(selectedNode, 'data-mce-selected', '1');
16127
16139
  }
16128
16140
  };
16129
16141
  /*
@@ -16822,7 +16834,7 @@
16822
16834
  return Optional.none();
16823
16835
  }
16824
16836
  };
16825
- 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}$`), ' '));
16826
16838
  const normalizeNbspsBetween = (editor, caretContainer) => {
16827
16839
  const handler = () => {
16828
16840
  if (caretContainer !== null && !editor.dom.isEmpty(caretContainer)) {
@@ -18259,13 +18271,14 @@
18259
18271
  const uniqueId$1 = (prefix) => {
18260
18272
  return (prefix || 'blobid') + (count$1++);
18261
18273
  };
18274
+ const utf8Encode = (str) => foldl(new window.TextEncoder().encode(str), (acc, charCode) => acc + String.fromCharCode(charCode), '');
18262
18275
  const processDataUri = (dataUri, base64Only, generateBlobInfo) => {
18263
18276
  return parseDataUri(dataUri).bind(({ data, type, base64Encoded }) => {
18264
18277
  if (base64Only && !base64Encoded) {
18265
18278
  return Optional.none();
18266
18279
  }
18267
18280
  else {
18268
- const base64 = base64Encoded ? data : btoa(data);
18281
+ const base64 = base64Encoded ? data : btoa(utf8Encode(data));
18269
18282
  return generateBlobInfo(base64, type);
18270
18283
  }
18271
18284
  });
@@ -18307,7 +18320,7 @@
18307
18320
  // TINY-10350: A modification of the Regexes.link regex to specifically capture host.
18308
18321
  // eslint-disable-next-line max-len
18309
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]+)?)?)$/;
18310
- 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);
18311
18324
 
18312
18325
  const sandboxIframe = (iframeNode, exclusions) => {
18313
18326
  if (Optional.from(iframeNode.attr('src')).bind(extractHost).forall((host) => !contains$2(exclusions, host))) {
@@ -20330,10 +20343,22 @@
20330
20343
  }
20331
20344
  // Construct the sugar element wrapper
20332
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
+ }
20333
20358
  // Determine if we're dealing with an internal attribute
20334
20359
  const isInternalElement = has$1(element, internalElementAttr);
20335
20360
  // Cleanup bogus elements
20336
- const bogus = get$9(element, 'data-mce-bogus');
20361
+ const bogus = get$a(element, 'data-mce-bogus');
20337
20362
  if (!isInternalElement && isString(bogus)) {
20338
20363
  if (bogus === 'all') {
20339
20364
  remove$8(element);
@@ -20364,11 +20389,11 @@
20364
20389
  if (validate && rule && !isInternalElement) {
20365
20390
  // Fix the attributes for the element, unwrapping it if we have to
20366
20391
  each$e(rule.attributesForced ?? [], (attr) => {
20367
- 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);
20368
20393
  });
20369
20394
  each$e(rule.attributesDefault ?? [], (attr) => {
20370
20395
  if (!has$1(element, attr.name)) {
20371
- 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);
20372
20397
  }
20373
20398
  });
20374
20399
  // If none of the required attributes were found then remove
@@ -20430,12 +20455,25 @@
20430
20455
  }
20431
20456
  }
20432
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
+ };
20433
20468
  const setupPurify = (settings, schema, namespaceTracker) => {
20434
20469
  const purify$1 = purify();
20435
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
20436
20471
  purify$1.addHook('uponSanitizeElement', (ele, evt) => {
20437
20472
  processNode(ele, settings, schema, namespaceTracker.track(ele), evt);
20438
20473
  });
20474
+ purify$1.addHook('afterSanitizeElements', (ele) => {
20475
+ restoreValidContent(ele);
20476
+ });
20439
20477
  // Let's do the same thing for attributes
20440
20478
  purify$1.addHook('uponSanitizeAttribute', (ele, evt) => {
20441
20479
  processAttr(ele, settings, schema, namespaceTracker.current(), evt);
@@ -22259,7 +22297,7 @@
22259
22297
  const addListeners = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
22260
22298
  const formatChangeItems = registeredFormatListeners.get();
22261
22299
  each$e(formats.split(','), (format) => {
22262
- const group = get$a(formatChangeItems, format).getOrThunk(() => {
22300
+ const group = get$b(formatChangeItems, format).getOrThunk(() => {
22263
22301
  const base = {
22264
22302
  withSimilar: {
22265
22303
  state: Cell(false),
@@ -22300,7 +22338,7 @@
22300
22338
  };
22301
22339
  const removeListeners = (registeredFormatListeners, formats, callback) => {
22302
22340
  const formatChangeItems = registeredFormatListeners.get();
22303
- each$e(formats.split(','), (format) => get$a(formatChangeItems, format).each((group) => {
22341
+ each$e(formats.split(','), (format) => get$b(formatChangeItems, format).each((group) => {
22304
22342
  formatChangeItems[format] = {
22305
22343
  withSimilar: {
22306
22344
  ...group.withSimilar,
@@ -22824,12 +22862,12 @@
22824
22862
  };
22825
22863
  const getCleanLevelContent = (isReadonly, level) => {
22826
22864
  const elm = SugarElement.fromTag('body', lazyTempDocument());
22827
- set$3(elm, getLevelContent(level));
22865
+ set$4(elm, getLevelContent(level));
22828
22866
  each$e(descendants(elm, '*[data-mce-bogus]'), unwrap);
22829
22867
  if (isReadonly) {
22830
22868
  each$e(descendants(elm, 'details[open]'), (element) => remove$9(element, 'open'));
22831
22869
  }
22832
- return get$8(elm);
22870
+ return get$9(elm);
22833
22871
  };
22834
22872
  const hasEqualContent = (level1, level2) => getLevelContent(level1) === getLevelContent(level2);
22835
22873
  const hasEqualCleanedContent = (isReadonly, level1, level2) => getCleanLevelContent(isReadonly, level1) === getCleanLevelContent(isReadonly, level2);
@@ -23170,7 +23208,7 @@
23170
23208
  };
23171
23209
  };
23172
23210
  const isRtc = (editor) => has$2(editor.plugins, 'rtc');
23173
- const getRtcSetup = (editor) => get$a(editor.plugins, 'rtc').bind((rtcPlugin) =>
23211
+ const getRtcSetup = (editor) => get$b(editor.plugins, 'rtc').bind((rtcPlugin) =>
23174
23212
  // This might not exist if the stub plugin is loaded on cloud
23175
23213
  Optional.from(rtcPlugin.setup));
23176
23214
  const setup$z = (editor) => {
@@ -24421,7 +24459,7 @@
24421
24459
  const rawElm = elm.dom;
24422
24460
  return rawElm[propName];
24423
24461
  };
24424
- const getComputedSizeProp = (propName, elm) => parseInt(get$7(elm, propName), 10);
24462
+ const getComputedSizeProp = (propName, elm) => parseInt(get$8(elm, propName), 10);
24425
24463
  const getClientWidth = curry(getProp, 'clientWidth');
24426
24464
  const getClientHeight = curry(getProp, 'clientHeight');
24427
24465
  const getMarginTop = curry(getComputedSizeProp, 'margin-top');
@@ -25040,7 +25078,7 @@
25040
25078
  const load = (editor, suffix) => {
25041
25079
  const strategy = determineStrategy(editor);
25042
25080
  if (strategy.type === 'use_plugin') {
25043
- 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);
25044
25082
  const url = externalUrl.getOr(`plugins/${PLUGIN_CODE}/plugin${suffix}.js`);
25045
25083
  addOnManager.load(ADDON_KEY, url).catch(() => {
25046
25084
  licenseKeyManagerLoadError(editor, url);
@@ -25141,7 +25179,7 @@
25141
25179
  const body = SugarElement.fromDom(editor.getBody());
25142
25180
  toggleClass(body, 'mce-content-readonly', false);
25143
25181
  if (editor.hasEditableRoot()) {
25144
- set(body, true);
25182
+ set$1(body, true);
25145
25183
  }
25146
25184
  setCommonEditorCommands(editor, false);
25147
25185
  if (hasEditorOrUiFocus(editor)) {
@@ -25155,21 +25193,21 @@
25155
25193
  const internalContentEditableAttr = 'data-mce-contenteditable';
25156
25194
  const switchOffContentEditableTrue = (elm) => {
25157
25195
  each$e(descendants(elm, '*[contenteditable="true"]'), (elm) => {
25158
- set$4(elm, internalContentEditableAttr, 'true');
25159
- set(elm, false);
25196
+ set$5(elm, internalContentEditableAttr, 'true');
25197
+ set$1(elm, false);
25160
25198
  });
25161
25199
  };
25162
25200
  const switchOnContentEditableTrue = (elm) => {
25163
25201
  each$e(descendants(elm, `*[${internalContentEditableAttr}="true"]`), (elm) => {
25164
25202
  remove$9(elm, internalContentEditableAttr);
25165
- set(elm, true);
25203
+ set$1(elm, true);
25166
25204
  });
25167
25205
  };
25168
25206
  const toggleDisabled = (editor, state) => {
25169
25207
  const body = SugarElement.fromDom(editor.getBody());
25170
25208
  if (state) {
25171
25209
  disableEditor(editor);
25172
- set(body, false);
25210
+ set$1(body, false);
25173
25211
  switchOffContentEditableTrue(body);
25174
25212
  }
25175
25213
  else {
@@ -26827,7 +26865,7 @@
26827
26865
  level.bookmark = getUndoBookmark(editor.selection);
26828
26866
  editor.dispatch('change', {
26829
26867
  level,
26830
- lastLevel: get$b(undoManager.data, index.get()).getOrUndefined()
26868
+ lastLevel: get$c(undoManager.data, index.get()).getOrUndefined()
26831
26869
  });
26832
26870
  },
26833
26871
  /**
@@ -27069,6 +27107,7 @@
27069
27107
  const isOlUlNode = matchNodeNames(/^(OL|UL)$/);
27070
27108
  const isListItemNode = matchNodeNames(/^(LI|DT|DD)$/);
27071
27109
  const isDlItemNode = matchNodeNames(/^(DT|DD)$/);
27110
+ const isTableCellNode = matchNodeNames(/^(TH|TD)$/);
27072
27111
  const isBr$1 = matchNodeName('br');
27073
27112
  const isFirstChild$1 = (node) => node.parentNode?.firstChild === node;
27074
27113
  const isTextBlock = (editor, node) => isNonNullable(node) && node.nodeName in editor.schema.getTextBlockElements();
@@ -27154,6 +27193,14 @@
27154
27193
  return outRng;
27155
27194
  };
27156
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
+
27157
27204
  const listNames = ['OL', 'UL', 'DL'];
27158
27205
  const listSelector = listNames.join(',');
27159
27206
  const getParentList = (editor, node) => {
@@ -27191,10 +27238,29 @@
27191
27238
  return parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody();
27192
27239
  };
27193
27240
  const isListHost = (schema, node) => !isListNode(node) && !isListItemNode(node) && exists(listNames, (listName) => schema.isValidChild(node.nodeName, listName));
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
+ };
27194
27253
  const getClosestListHost = (editor, elm, isCollapsed) => {
27195
27254
  const parentBlocks = editor.dom.getParents(elm, editor.dom.isBlock);
27255
+ let foundListBlock = !requireLiElementFirst(parentBlocks);
27196
27256
  const isNotForcedRootBlock = (elm) => elm.nodeName.toLowerCase() !== getForcedRootBlock(editor);
27197
- const parentBlock = find$2(parentBlocks, (elm) => (!isCollapsed || 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));
27198
27264
  return parentBlock.getOr(editor.getBody());
27199
27265
  };
27200
27266
  const isListInsideAnLiWithFirstAndLastNotListElement = (list) => parent(list).exists((parent) => isListItemNode(parent.dom)
@@ -27277,14 +27343,6 @@
27277
27343
  return fragment;
27278
27344
  };
27279
27345
 
27280
- const isList = (el) => is$1(el, 'OL,UL');
27281
- const isListItem$1 = (el) => is$1(el, 'LI');
27282
- const hasFirstChildList = (el) => firstChild(el).exists(isList);
27283
- const hasLastChildList = (el) => lastChild(el).exists(isList);
27284
- const canIncreaseDepthOfList = (editor, amount) => {
27285
- return getListMaxDepth(editor).map((max) => max >= amount).getOr(true);
27286
- };
27287
-
27288
27346
  const isEntryList = (entry) => 'listAttributes' in entry;
27289
27347
  const isEntryComment = (entry) => 'isComment' in entry;
27290
27348
  const isEntryFragment = (entry) => 'isFragment' in entry;
@@ -27334,7 +27392,7 @@
27334
27392
  };
27335
27393
  const populateSegments = (segments, entry) => {
27336
27394
  for (let i = 0; i < segments.length - 1; i++) {
27337
- set$2(segments[i].item, 'list-style-type', 'none');
27395
+ set$3(segments[i].item, 'list-style-type', 'none');
27338
27396
  }
27339
27397
  last$2(segments).each((segment) => {
27340
27398
  if (isEntryList(entry)) {
@@ -29640,7 +29698,7 @@
29640
29698
  const parseIndentValue = (value) => toInt(value ?? '').getOr(0);
29641
29699
  const getIndentStyleName = (useMargin, element) => {
29642
29700
  const indentStyleName = useMargin || isTable$1(element) ? 'margin' : 'padding';
29643
- const suffix = get$7(element, 'direction') === 'rtl' ? '-right' : '-left';
29701
+ const suffix = get$8(element, 'direction') === 'rtl' ? '-right' : '-left';
29644
29702
  return indentStyleName + suffix;
29645
29703
  };
29646
29704
  const indentElement = (dom, command, useMargin, value, unit, element) => {
@@ -29705,9 +29763,10 @@
29705
29763
  };
29706
29764
 
29707
29765
  const deleteRange = (editor, forward) => {
29708
- const rng = normalize(editor.selection.getRng());
29766
+ const range = editor.selection.getRng();
29767
+ const rng = normalize(range);
29709
29768
  return isSelectionOverWholeHTMLElement(rng)
29710
- ? 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])))
29711
29770
  : Optional.none();
29712
29771
  };
29713
29772
  const backspaceDelete$1 = (editor, forward) => editor.selection.isCollapsed() ? Optional.none() : deleteRange(editor, forward);
@@ -30451,7 +30510,7 @@
30451
30510
  }
30452
30511
  return contains$2(['br', 'img', 'hr', 'input'], name(element));
30453
30512
  };
30454
- const isNonEditable = (element) => isElement$8(element) && get$9(element, 'contenteditable') === 'false';
30513
+ const isNonEditable = (element) => isElement$8(element) && get$a(element, 'contenteditable') === 'false';
30455
30514
  const comparePosition = (element, other) => {
30456
30515
  return element.dom.compareDocumentPosition(other.dom);
30457
30516
  };
@@ -30478,14 +30537,14 @@
30478
30537
  predicate: descendants$1
30479
30538
  }),
30480
30539
  styles: constant({
30481
- get: get$7,
30540
+ get: get$8,
30482
30541
  getRaw: getRaw$1,
30483
- set: set$2,
30542
+ set: set$3,
30484
30543
  remove: remove$7
30485
30544
  }),
30486
30545
  attrs: constant({
30487
- get: get$9,
30488
- set: set$4,
30546
+ get: get$a,
30547
+ set: set$5,
30489
30548
  remove: remove$9,
30490
30549
  copyTo: copyAttributesTo
30491
30550
  }),
@@ -30522,8 +30581,8 @@
30522
30581
  isElement: isElement$8,
30523
30582
  isSpecial,
30524
30583
  getLanguage,
30525
- getText: get$4,
30526
- setText: set$1,
30584
+ getText: get$5,
30585
+ setText: set$2,
30527
30586
  isBoundary,
30528
30587
  isEmptyTag,
30529
30588
  isNonEditable
@@ -35048,7 +35107,7 @@
35048
35107
  const doc = editor.getDoc();
35049
35108
  const realSelectionContainer = descendant$1(body, '#' + realSelectionId).getOrThunk(() => {
35050
35109
  const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc);
35051
- set$4(newContainer, 'id', realSelectionId);
35110
+ set$5(newContainer, 'id', realSelectionId);
35052
35111
  append$1(body, newContainer);
35053
35112
  return newContainer;
35054
35113
  });
@@ -35640,9 +35699,9 @@
35640
35699
  * as it feels to be the expected behavior.
35641
35700
  */
35642
35701
  const text = SugarElement.fromDom(node);
35643
- const textContent = get$4(text);
35702
+ const textContent = get$5(text);
35644
35703
  if (startsWithSingleSpace(textContent)) {
35645
- set$1(text, textContent.slice(1));
35704
+ set$2(text, textContent.slice(1));
35646
35705
  }
35647
35706
  });
35648
35707
  };
@@ -36539,7 +36598,7 @@
36539
36598
  };
36540
36599
  const loadComponentsForInlineEditor = (componentUrls) => {
36541
36600
  return mapToArray(componentUrls, (url, elementName) => {
36542
- return get$a(hostWindowComponentScripts, url).getOrThunk(() => {
36601
+ return get$b(hostWindowComponentScripts, url).getOrThunk(() => {
36543
36602
  // Only load the component if it hasn't already been loaded in inline mode the page might have already loaded it
36544
36603
  if (isNullable(window.customElements.get(elementName))) {
36545
36604
  const loadPromise = loadComponent(url, getDocument());
@@ -36592,7 +36651,7 @@
36592
36651
  const body = SugarElement.fromDom(editor.getBody());
36593
36652
  const container = getStyleContainer(getRootNode(body));
36594
36653
  const style = SugarElement.fromTag('style');
36595
- set$4(style, 'type', 'text/css');
36654
+ set$5(style, 'type', 'text/css');
36596
36655
  append$1(style, SugarElement.fromText(text));
36597
36656
  append$1(container, style);
36598
36657
  editor.on('remove', () => {
@@ -36907,6 +36966,11 @@
36907
36966
  editor.bodyElement = targetElm;
36908
36967
  editor.contentAreaContainer = targetElm;
36909
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
+ }
36910
36974
  // It will not steal focus while setting contentEditable
36911
36975
  const body = editor.getBody();
36912
36976
  // disabled isn't valid on all body elements, so need to cast here
@@ -36994,7 +37058,7 @@
36994
37058
  const createIframeElement = (id, title, customAttrs, tabindex) => {
36995
37059
  const iframe = SugarElement.fromTag('iframe');
36996
37060
  // This can also be explicitly set by customAttrs, so do this first
36997
- tabindex.each((t) => set$4(iframe, 'tabindex', t));
37061
+ tabindex.each((t) => set$5(iframe, 'tabindex', t));
36998
37062
  setAll$1(iframe, customAttrs);
36999
37063
  setAll$1(iframe, {
37000
37064
  id: id + '_ifr',
@@ -37684,7 +37748,7 @@
37684
37748
  };
37685
37749
  const getSection = (sectionResult, name, defaults = {}) => {
37686
37750
  const sections = sectionResult.sections();
37687
- const sectionOptions = get$a(sections, name).getOr({});
37751
+ const sectionOptions = get$b(sections, name).getOr({});
37688
37752
  return Tools.extend({}, defaults, sectionOptions);
37689
37753
  };
37690
37754
  const hasSection = (sectionResult, name) => {
@@ -37699,7 +37763,7 @@
37699
37763
  table_grid: false, // Table grid relies on hover, which isn't available for touch devices so use the dialog instead
37700
37764
  object_resizing: false, // No nice way to do object resizing at this stage
37701
37765
  resize: false, // Editor resize doesn't make sense on mobile
37702
- 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
37703
37767
  toolbar_sticky: false // Only enable sticky toolbar on desktop by default
37704
37768
  };
37705
37769
  const defaultPhoneOptions = {
@@ -37947,7 +38011,7 @@
37947
38011
  const getSpecifiedFontProp = (propName, rootElm, elm) => {
37948
38012
  const getProperty = (elm) => getRaw$1(elm, propName).orThunk(() => {
37949
38013
  if (isFont(elm)) {
37950
- return get$a(legacyPropNames, propName).bind((legacyPropName) => getOpt(elm, legacyPropName));
38014
+ return get$b(legacyPropNames, propName).bind((legacyPropName) => getOpt(elm, legacyPropName));
37951
38015
  }
37952
38016
  else {
37953
38017
  return Optional.none();
@@ -38038,8 +38102,8 @@
38038
38102
  const specifiedStyle = closest$1(elm, (elm) => getRaw$1(elm, 'line-height'), curry(eq, root));
38039
38103
  const computedStyle = () => {
38040
38104
  // Css.get returns computed values (in px), and parseFloat will strip any non-number suffix
38041
- const lineHeight = parseFloat(get$7(elm, 'line-height'));
38042
- 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'));
38043
38107
  return String(lineHeight / fontSize);
38044
38108
  };
38045
38109
  return specifiedStyle.getOrThunk(computedStyle);
@@ -39067,12 +39131,12 @@
39067
39131
  processor
39068
39132
  };
39069
39133
  // Setup the initial values
39070
- const initValue = get$a(values, name).orThunk(() => get$a(initialOptions, name));
39134
+ const initValue = get$b(values, name).orThunk(() => get$b(initialOptions, name));
39071
39135
  initValue.each((value) => setValue(name, value, processor));
39072
39136
  };
39073
39137
  const isRegistered = (name) => has$2(registry, name);
39074
- const get = (name) => get$a(values, name)
39075
- .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))
39076
39140
  .getOrUndefined();
39077
39141
  const set = (name, value) => {
39078
39142
  if (!isRegistered(name)) {
@@ -40681,14 +40745,14 @@
40681
40745
  * @property minorVersion
40682
40746
  * @type String
40683
40747
  */
40684
- minorVersion: '4.0',
40748
+ minorVersion: '5.0',
40685
40749
  /**
40686
40750
  * Release date of TinyMCE build.
40687
40751
  *
40688
40752
  * @property releaseDate
40689
40753
  * @type String
40690
40754
  */
40691
- releaseDate: '2026-03-31',
40755
+ releaseDate: '2026-04-29',
40692
40756
  /**
40693
40757
  * Collection of language pack data.
40694
40758
  *
@@ -40860,7 +40924,7 @@
40860
40924
  const createId = (elm) => {
40861
40925
  let id = elm.id;
40862
40926
  if (!id) {
40863
- 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);
40864
40928
  elm.setAttribute('id', id);
40865
40929
  }
40866
40930
  return id;
@@ -41200,7 +41264,7 @@
41200
41264
  const FakeClipboardItem = (items) => ({
41201
41265
  items,
41202
41266
  types: keys(items),
41203
- getType: (type) => get$a(items, type).getOrUndefined()
41267
+ getType: (type) => get$b(items, type).getOrUndefined()
41204
41268
  });
41205
41269
  const write = (data) => {
41206
41270
  dataValue.set(data);