tinymce-rails 6.7.2 → 6.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/source/tinymce/tinymce.js +1099 -826
  3. data/lib/tinymce/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/tinymce/models/dom/model.js +1 -1
  5. data/vendor/assets/javascripts/tinymce/plugins/accordion/plugin.js +2 -2
  6. data/vendor/assets/javascripts/tinymce/plugins/advlist/plugin.js +1 -1
  7. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.js +1 -1
  8. data/vendor/assets/javascripts/tinymce/plugins/autolink/plugin.js +1 -1
  9. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.js +1 -1
  10. data/vendor/assets/javascripts/tinymce/plugins/autosave/plugin.js +1 -1
  11. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.js +1 -1
  12. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.js +1 -1
  13. data/vendor/assets/javascripts/tinymce/plugins/codesample/plugin.js +1 -1
  14. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.js +1 -1
  15. data/vendor/assets/javascripts/tinymce/plugins/emoticons/plugin.js +1 -1
  16. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.js +1 -1
  17. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/ar.js +5 -5
  18. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/bg_BG.js +5 -5
  19. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/ca.js +5 -5
  20. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/cs.js +5 -5
  21. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/da.js +5 -5
  22. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/de.js +5 -5
  23. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/el.js +5 -5
  24. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/en.js +5 -5
  25. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/es.js +5 -5
  26. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/eu.js +6 -6
  27. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/fa.js +5 -5
  28. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/fi.js +5 -5
  29. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/fr_FR.js +5 -5
  30. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/he_IL.js +5 -5
  31. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/hi.js +5 -5
  32. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/hr.js +5 -5
  33. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/hu_HU.js +5 -5
  34. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/id.js +5 -5
  35. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/it.js +5 -5
  36. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/ja.js +5 -5
  37. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/kk.js +5 -5
  38. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/ko_KR.js +5 -5
  39. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/ms.js +5 -5
  40. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/nb_NO.js +5 -5
  41. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/nl.js +5 -5
  42. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/pl.js +5 -5
  43. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/pt_BR.js +5 -5
  44. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/pt_PT.js +5 -5
  45. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/ro.js +5 -5
  46. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/ru.js +5 -5
  47. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/sk.js +5 -5
  48. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/sl_SI.js +5 -5
  49. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/sv_SE.js +5 -5
  50. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/th_TH.js +5 -5
  51. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/tr.js +5 -5
  52. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/uk.js +5 -5
  53. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/vi.js +5 -5
  54. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/zh_CN.js +5 -5
  55. data/vendor/assets/javascripts/tinymce/plugins/help/js/i18n/keynav/zh_TW.js +5 -5
  56. data/vendor/assets/javascripts/tinymce/plugins/help/plugin.js +1 -1
  57. data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +2 -2
  58. data/vendor/assets/javascripts/tinymce/plugins/importcss/plugin.js +2 -2
  59. data/vendor/assets/javascripts/tinymce/plugins/insertdatetime/plugin.js +1 -1
  60. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.js +2 -2
  61. data/vendor/assets/javascripts/tinymce/plugins/lists/plugin.js +2 -2
  62. data/vendor/assets/javascripts/tinymce/plugins/media/plugin.js +2 -2
  63. data/vendor/assets/javascripts/tinymce/plugins/nonbreaking/plugin.js +1 -1
  64. data/vendor/assets/javascripts/tinymce/plugins/pagebreak/plugin.js +1 -1
  65. data/vendor/assets/javascripts/tinymce/plugins/preview/plugin.js +1 -1
  66. data/vendor/assets/javascripts/tinymce/plugins/quickbars/plugin.js +1 -1
  67. data/vendor/assets/javascripts/tinymce/plugins/save/plugin.js +1 -1
  68. data/vendor/assets/javascripts/tinymce/plugins/searchreplace/plugin.js +2 -2
  69. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
  70. data/vendor/assets/javascripts/tinymce/plugins/template/plugin.js +1 -1
  71. data/vendor/assets/javascripts/tinymce/plugins/visualblocks/plugin.js +1 -1
  72. data/vendor/assets/javascripts/tinymce/plugins/visualchars/plugin.js +1 -1
  73. data/vendor/assets/javascripts/tinymce/plugins/wordcount/plugin.js +1 -1
  74. data/vendor/assets/javascripts/tinymce/skins/content/dark/content.js +2 -0
  75. data/vendor/assets/javascripts/tinymce/skins/content/default/content.js +2 -0
  76. data/vendor/assets/javascripts/tinymce/skins/content/document/content.js +2 -0
  77. data/vendor/assets/javascripts/tinymce/skins/content/tinymce-5/content.js +2 -0
  78. data/vendor/assets/javascripts/tinymce/skins/content/tinymce-5-dark/content.js +2 -0
  79. data/vendor/assets/javascripts/tinymce/skins/content/writer/content.js +2 -0
  80. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.js +2 -0
  81. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.js +2 -0
  82. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.css +1 -1
  83. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.js +2 -0
  84. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.min.css +1 -1
  85. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.shadowdom.js +2 -0
  86. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.js +2 -0
  87. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.js +2 -0
  88. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.css +1 -1
  89. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.js +2 -0
  90. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.min.css +1 -1
  91. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.shadowdom.js +2 -0
  92. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.js +2 -0
  93. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.js +2 -0
  94. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.css +1 -1
  95. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.js +2 -0
  96. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.min.css +1 -1
  97. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.shadowdom.js +2 -0
  98. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.js +2 -0
  99. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.js +2 -0
  100. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.css +1 -1
  101. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.js +2 -0
  102. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.min.css +1 -1
  103. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.shadowdom.js +2 -0
  104. data/vendor/assets/javascripts/tinymce/themes/silver/theme.js +2 -2
  105. data/vendor/assets/javascripts/tinymce/tinymce.d.ts +26 -0
  106. data/vendor/assets/javascripts/tinymce/tinymce.js +2 -2
  107. metadata +24 -2
@@ -1,5 +1,5 @@
1
1
  /**
2
- * TinyMCE version 6.7.2 (2023-10-25)
2
+ * TinyMCE version 6.8.1 (2023-11-29)
3
3
  */
4
4
 
5
5
  (function () {
@@ -448,7 +448,7 @@
448
448
  };
449
449
 
450
450
  const keys = Object.keys;
451
- const hasOwnProperty$2 = Object.hasOwnProperty;
451
+ const hasOwnProperty$1 = Object.hasOwnProperty;
452
452
  const each$d = (obj, f) => {
453
453
  const props = keys(obj);
454
454
  for (let k = 0, len = props.length; k < len; k++) {
@@ -506,7 +506,7 @@
506
506
  const get$a = (obj, key) => {
507
507
  return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
508
508
  };
509
- const has$2 = (obj, key) => hasOwnProperty$2.call(obj, key);
509
+ const has$2 = (obj, key) => hasOwnProperty$1.call(obj, key);
510
510
  const hasNonNullableKey = (obj, key) => has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
511
511
  const equal$1 = (a1, a2, eq = eqAny) => eqRecord(eq).eq(a1, a2);
512
512
 
@@ -1025,7 +1025,7 @@
1025
1025
  }
1026
1026
  return map;
1027
1027
  };
1028
- const hasOwnProperty$1 = has$2;
1028
+ const hasOwnProperty = has$2;
1029
1029
  const extend$3 = (obj, ...exts) => {
1030
1030
  for (let i = 0; i < exts.length; i++) {
1031
1031
  const ext = exts[i];
@@ -1092,7 +1092,7 @@
1092
1092
  map: map$1,
1093
1093
  grep: filter$3,
1094
1094
  inArray: indexOf,
1095
- hasOwn: hasOwnProperty$1,
1095
+ hasOwn: hasOwnProperty,
1096
1096
  extend: extend$3,
1097
1097
  walk: walk$4,
1098
1098
  resolve: resolve$3,
@@ -1163,7 +1163,7 @@
1163
1163
  const type$1 = element => element.dom.nodeType;
1164
1164
  const isType = t => element => type$1(element) === t;
1165
1165
  const isComment$1 = element => type$1(element) === COMMENT || name(element) === '#comment';
1166
- const isHTMLElement = element => isElement$7(element) && isPrototypeOf(element.dom);
1166
+ const isHTMLElement$1 = element => isElement$7(element) && isPrototypeOf(element.dom);
1167
1167
  const isElement$7 = isType(ELEMENT);
1168
1168
  const isText$b = isType(TEXT);
1169
1169
  const isDocument$2 = isType(DOCUMENT);
@@ -1478,7 +1478,7 @@
1478
1478
  const result = find$2(scope.dom.childNodes, pred);
1479
1479
  return result.map(SugarElement.fromDom);
1480
1480
  };
1481
- const descendant$1 = (scope, predicate) => {
1481
+ const descendant$2 = (scope, predicate) => {
1482
1482
  const descend = node => {
1483
1483
  for (let i = 0; i < node.childNodes.length; i++) {
1484
1484
  const child = SugarElement.fromDom(node.childNodes[i]);
@@ -1496,14 +1496,14 @@
1496
1496
  };
1497
1497
 
1498
1498
  const ancestor$3 = (scope, selector, isRoot) => ancestor$4(scope, e => is$1(e, selector), isRoot);
1499
- const descendant = (scope, selector) => one(selector, scope);
1499
+ const descendant$1 = (scope, selector) => one(selector, scope);
1500
1500
  const closest$3 = (scope, selector, isRoot) => {
1501
1501
  const is = (element, selector) => is$1(element, selector);
1502
1502
  return ClosestOrAncestor(is, ancestor$3, scope, selector, isRoot);
1503
1503
  };
1504
1504
 
1505
1505
  const closest$2 = target => closest$3(target, '[contenteditable]');
1506
- const isEditable$3 = (element, assumeEditable = false) => {
1506
+ const isEditable$2 = (element, assumeEditable = false) => {
1507
1507
  if (inBody(element)) {
1508
1508
  return element.dom.isContentEditable;
1509
1509
  } else {
@@ -1881,6 +1881,8 @@
1881
1881
  };
1882
1882
  const isRestrictedNode = node => !!node && !Object.getPrototypeOf(node);
1883
1883
  const isElement$6 = isNodeType(1);
1884
+ const isHTMLElement = node => isElement$6(node) && isHTMLElement$1(SugarElement.fromDom(node));
1885
+ const isSVGElement = node => isElement$6(node) && node.namespaceURI === 'http://www.w3.org/2000/svg';
1884
1886
  const matchNodeName = name => {
1885
1887
  const lowerCasedName = name.toLowerCase();
1886
1888
  return node => isNonNullable(node) && node.nodeName.toLowerCase() === lowerCasedName;
@@ -1928,7 +1930,7 @@
1928
1930
  const isTable$2 = node => isElement$6(node) && node.tagName === 'TABLE';
1929
1931
  const hasContentEditableState = value => {
1930
1932
  return node => {
1931
- if (isElement$6(node)) {
1933
+ if (isHTMLElement(node)) {
1932
1934
  if (node.contentEditable === value) {
1933
1935
  return true;
1934
1936
  }
@@ -1970,7 +1972,7 @@
1970
1972
  ]);
1971
1973
  const isListItem$2 = matchNodeName('li');
1972
1974
  const isDetails = matchNodeName('details');
1973
- const isSummary = matchNodeName('summary');
1975
+ const isSummary$1 = matchNodeName('summary');
1974
1976
 
1975
1977
  const zeroWidth = '\uFEFF';
1976
1978
  const nbsp = '\xA0';
@@ -2003,57 +2005,6 @@
2003
2005
  const getOption = element => api$1.getOption(element);
2004
2006
  const set = (element, value) => api$1.set(element, value);
2005
2007
 
2006
- const blocks = [
2007
- 'article',
2008
- 'aside',
2009
- 'details',
2010
- 'div',
2011
- 'dt',
2012
- 'figcaption',
2013
- 'footer',
2014
- 'form',
2015
- 'fieldset',
2016
- 'header',
2017
- 'hgroup',
2018
- 'html',
2019
- 'main',
2020
- 'nav',
2021
- 'section',
2022
- 'summary',
2023
- 'body',
2024
- 'p',
2025
- 'dl',
2026
- 'multicol',
2027
- 'dd',
2028
- 'figure',
2029
- 'address',
2030
- 'center',
2031
- 'blockquote',
2032
- 'h1',
2033
- 'h2',
2034
- 'h3',
2035
- 'h4',
2036
- 'h5',
2037
- 'h6',
2038
- 'listing',
2039
- 'xmp',
2040
- 'pre',
2041
- 'plaintext',
2042
- 'menu',
2043
- 'dir',
2044
- 'ul',
2045
- 'ol',
2046
- 'li',
2047
- 'hr',
2048
- 'table',
2049
- 'tbody',
2050
- 'thead',
2051
- 'tfoot',
2052
- 'th',
2053
- 'tr',
2054
- 'td',
2055
- 'caption'
2056
- ];
2057
2008
  const tableCells = [
2058
2009
  'td',
2059
2010
  'th'
@@ -2088,14 +2039,6 @@
2088
2039
  'nav',
2089
2040
  'figure'
2090
2041
  ];
2091
- const headings = [
2092
- 'h1',
2093
- 'h2',
2094
- 'h3',
2095
- 'h4',
2096
- 'h5',
2097
- 'h6'
2098
- ];
2099
2042
  const listItems$1 = [
2100
2043
  'li',
2101
2044
  'dd',
@@ -2112,7 +2055,6 @@
2112
2055
  'textarea',
2113
2056
  'style'
2114
2057
  ];
2115
- const wrapBlockElements = ['pre'].concat(headings);
2116
2058
  const lazyLookup = items => {
2117
2059
  let lookup;
2118
2060
  return node => {
@@ -2120,9 +2062,7 @@
2120
2062
  return has$2(lookup, name(node));
2121
2063
  };
2122
2064
  };
2123
- const isBlock$2 = lazyLookup(blocks);
2124
2065
  const isTable$1 = node => name(node) === 'table';
2125
- const isInline$1 = node => isElement$7(node) && !isBlock$2(node);
2126
2066
  const isBr$5 = node => isElement$7(node) && name(node) === 'br';
2127
2067
  const isTextBlock$2 = lazyLookup(textBlocks);
2128
2068
  const isList = lazyLookup(lists);
@@ -2130,8 +2070,6 @@
2130
2070
  const isTableSection = lazyLookup(tableSections);
2131
2071
  const isTableCell$2 = lazyLookup(tableCells);
2132
2072
  const isWsPreserveElement = lazyLookup(wsElements);
2133
- const isWrapBlockElement = lazyLookup(wrapBlockElements);
2134
- const isWrapElement = node => isWrapBlockElement(node) || isInline$1(node);
2135
2073
 
2136
2074
  const getLastChildren$1 = elm => {
2137
2075
  const children = [];
@@ -2158,10 +2096,10 @@
2158
2096
  empty(elm);
2159
2097
  append$1(elm, createPaddingBr());
2160
2098
  };
2161
- const trimBlockTrailingBr = elm => {
2099
+ const trimBlockTrailingBr = (elm, schema) => {
2162
2100
  lastChild(elm).each(lastChild => {
2163
2101
  prevSibling(lastChild).each(lastChildPrevSibling => {
2164
- if (isBlock$2(elm) && isBr$5(lastChild) && isBlock$2(lastChildPrevSibling)) {
2102
+ if (schema.isBlock(name(elm)) && isBr$5(lastChild) && schema.isBlock(name(lastChildPrevSibling))) {
2165
2103
  remove$5(lastChild);
2166
2104
  }
2167
2105
  });
@@ -2171,6 +2109,7 @@
2171
2109
  const ZWSP$1 = zeroWidth;
2172
2110
  const isZwsp$1 = isZwsp$2;
2173
2111
  const trim$2 = removeZwsp;
2112
+ const insert$5 = editor => editor.insertContent(ZWSP$1, { preserve_zwsp: true });
2174
2113
 
2175
2114
  const isElement$5 = isElement$6;
2176
2115
  const isText$9 = isText$a;
@@ -2389,6 +2328,7 @@
2389
2328
  const isBookmark = hasAttribute('data-mce-bookmark');
2390
2329
  const isBogus$1 = hasAttribute('data-mce-bogus');
2391
2330
  const isBogusAll = hasAttributeValue('data-mce-bogus', 'all');
2331
+ const hasNonEditableParent = node => parentElement(SugarElement.fromDom(node)).exists(parent => !isEditable$2(parent));
2392
2332
  const isEmptyNode = (targetNode, skipBogus) => {
2393
2333
  let brCount = 0;
2394
2334
  if (isContent$1(targetNode, targetNode)) {
@@ -2410,6 +2350,9 @@
2410
2350
  continue;
2411
2351
  }
2412
2352
  }
2353
+ if (isContentEditableTrue$3(node) && hasNonEditableParent(node)) {
2354
+ return false;
2355
+ }
2413
2356
  if (isBr$6(node)) {
2414
2357
  brCount++;
2415
2358
  node = walker.next();
@@ -2425,9 +2368,40 @@
2425
2368
  };
2426
2369
  const isEmpty$2 = (elm, skipBogus = true) => isEmptyNode(elm.dom, skipBogus);
2427
2370
 
2371
+ const isNonHtmlElementRootName = name => name.toLowerCase() === 'svg';
2372
+ const isNonHtmlElementRoot = node => isNonHtmlElementRootName(node.nodeName);
2373
+ const toScopeType = node => (node === null || node === void 0 ? void 0 : node.nodeName) === 'svg' ? 'svg' : 'html';
2374
+ const namespaceElements = ['svg'];
2375
+ const createNamespaceTracker = () => {
2376
+ let scopes = [];
2377
+ const peek = () => scopes[scopes.length - 1];
2378
+ const track = node => {
2379
+ if (isNonHtmlElementRoot(node)) {
2380
+ scopes.push(node);
2381
+ }
2382
+ let currentScope = peek();
2383
+ if (currentScope && !currentScope.contains(node)) {
2384
+ scopes.pop();
2385
+ currentScope = peek();
2386
+ }
2387
+ return toScopeType(currentScope);
2388
+ };
2389
+ const current = () => toScopeType(peek());
2390
+ const reset = () => {
2391
+ scopes = [];
2392
+ };
2393
+ return {
2394
+ track,
2395
+ current,
2396
+ reset
2397
+ };
2398
+ };
2399
+
2428
2400
  const transparentBlockAttr = 'data-mce-block';
2429
2401
  const elementNames = map => filter$5(keys(map), key => !/[A-Z]/.test(key));
2430
- const makeSelectorFromSchemaMap = map => elementNames(map).join(',');
2402
+ const makeSelectorFromSchemaMap = map => map$3(elementNames(map), name => {
2403
+ return `${ name }:` + map$3(namespaceElements, ns => `not(${ ns } ${ name })`).join(':');
2404
+ }).join(',');
2431
2405
  const updateTransparent = (blocksSelector, transparent) => {
2432
2406
  if (isNonNullable(transparent.querySelector(blocksSelector))) {
2433
2407
  transparent.setAttribute(transparentBlockAttr, 'true');
@@ -2602,7 +2576,7 @@
2602
2576
  };
2603
2577
  const removeStyle = id => {
2604
2578
  const styleContainer = getStyleContainer(edos);
2605
- descendant(styleContainer, '#' + id).each(remove$5);
2579
+ descendant$1(styleContainer, '#' + id).each(remove$5);
2606
2580
  };
2607
2581
  const getOrCreateState = url => get$a(loadedStates, url).getOrThunk(() => ({
2608
2582
  id: 'mce-u' + idCount++,
@@ -2665,6 +2639,19 @@
2665
2639
  addStyle(linkElem);
2666
2640
  set$3(linkElem, 'href', urlWithSuffix);
2667
2641
  });
2642
+ const loadRawCss = (key, css) => {
2643
+ const state = getOrCreateState(key);
2644
+ loadedStates[key] = state;
2645
+ state.count++;
2646
+ const styleElem = SugarElement.fromTag('style', doc.dom);
2647
+ setAll$1(styleElem, {
2648
+ rel: 'stylesheet',
2649
+ type: 'text/css',
2650
+ id: state.id
2651
+ });
2652
+ styleElem.dom.innerHTML = css;
2653
+ addStyle(styleElem);
2654
+ };
2668
2655
  const loadAll = urls => {
2669
2656
  const loadedUrls = Promise.allSettled(map$3(urls, url => load(url).then(constant(url))));
2670
2657
  return loadedUrls.then(results => {
@@ -2686,6 +2673,15 @@
2686
2673
  }
2687
2674
  });
2688
2675
  };
2676
+ const unloadRawCss = key => {
2677
+ get$a(loadedStates, key).each(state => {
2678
+ const count = --state.count;
2679
+ if (count === 0) {
2680
+ delete loadedStates[key];
2681
+ removeStyle(state.id);
2682
+ }
2683
+ });
2684
+ };
2689
2685
  const unloadAll = urls => {
2690
2686
  each$e(urls, url => {
2691
2687
  unload(url);
@@ -2693,8 +2689,10 @@
2693
2689
  };
2694
2690
  return {
2695
2691
  load,
2692
+ loadRawCss,
2696
2693
  loadAll,
2697
2694
  unload,
2695
+ unloadRawCss,
2698
2696
  unloadAll,
2699
2697
  _setReferrerPolicy,
2700
2698
  _setContentCssCors
@@ -2717,19 +2715,19 @@
2717
2715
  const instance = create$d();
2718
2716
 
2719
2717
  const isSpan = node => node.nodeName.toLowerCase() === 'span';
2720
- const isInlineContent = (node, root) => isNonNullable(node) && (isContent$1(node, root) || isInline$1(SugarElement.fromDom(node)));
2721
- const surroundedByInlineContent = (node, root) => {
2718
+ const isInlineContent = (node, root, schema) => isNonNullable(node) && (isContent$1(node, root) || schema.isInline(node.nodeName.toLowerCase()));
2719
+ const surroundedByInlineContent = (node, root, schema) => {
2722
2720
  const prev = new DomTreeWalker(node, root).prev(false);
2723
2721
  const next = new DomTreeWalker(node, root).next(false);
2724
- const prevIsInline = isUndefined(prev) || isInlineContent(prev, root);
2725
- const nextIsInline = isUndefined(next) || isInlineContent(next, root);
2722
+ const prevIsInline = isUndefined(prev) || isInlineContent(prev, root, schema);
2723
+ const nextIsInline = isUndefined(next) || isInlineContent(next, root, schema);
2726
2724
  return prevIsInline && nextIsInline;
2727
2725
  };
2728
2726
  const isBookmarkNode$2 = node => isSpan(node) && node.getAttribute('data-mce-type') === 'bookmark';
2729
- const isKeepTextNode = (node, root) => isText$a(node) && node.data.length > 0 && surroundedByInlineContent(node, root);
2727
+ const isKeepTextNode = (node, root, schema) => isText$a(node) && node.data.length > 0 && surroundedByInlineContent(node, root, schema);
2730
2728
  const isKeepElement = node => isElement$6(node) ? node.childNodes.length > 0 : false;
2731
2729
  const isDocument = node => isDocumentFragment(node) || isDocument$1(node);
2732
- const trimNode = (dom, node, root) => {
2730
+ const trimNode = (dom, node, schema, root) => {
2733
2731
  var _a;
2734
2732
  const rootNode = root || node;
2735
2733
  if (isElement$6(node) && isBookmarkNode$2(node)) {
@@ -2737,7 +2735,7 @@
2737
2735
  }
2738
2736
  const children = node.childNodes;
2739
2737
  for (let i = children.length - 1; i >= 0; i--) {
2740
- trimNode(dom, children[i], rootNode);
2738
+ trimNode(dom, children[i], schema, rootNode);
2741
2739
  }
2742
2740
  if (isElement$6(node)) {
2743
2741
  const currentChildren = node.childNodes;
@@ -2745,7 +2743,7 @@
2745
2743
  (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(currentChildren[0], node);
2746
2744
  }
2747
2745
  }
2748
- if (!isDocument(node) && !isContent$1(node, rootNode) && !isKeepElement(node) && !isKeepTextNode(node, rootNode)) {
2746
+ if (!isDocument(node) && !isContent$1(node, rootNode) && !isKeepElement(node) && !isKeepTextNode(node, rootNode, schema)) {
2749
2747
  dom.remove(node);
2750
2748
  }
2751
2749
  return node;
@@ -2925,7 +2923,7 @@
2925
2923
 
2926
2924
  const getElementSetsAsStrings = type => {
2927
2925
  let globalAttributes, blockContent;
2928
- let phrasingContent, flowContent;
2926
+ let phrasingContent;
2929
2927
  globalAttributes = 'id accesskey class dir lang style tabindex title role';
2930
2928
  blockContent = 'address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul';
2931
2929
  phrasingContent = 'a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd ' + 'label map noscript object q s samp script select small span strong sub sup ' + 'textarea u var #text #comment';
@@ -2933,7 +2931,7 @@
2933
2931
  const transparentContent = 'a ins del canvas map';
2934
2932
  globalAttributes += ' contenteditable contextmenu draggable dropzone ' + 'hidden spellcheck translate';
2935
2933
  blockContent += ' article aside details dialog figure main header footer hgroup section nav ' + transparentContent;
2936
- phrasingContent += ' audio canvas command datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen';
2934
+ phrasingContent += ' audio canvas command datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen svg';
2937
2935
  }
2938
2936
  if (type !== 'html5-strict') {
2939
2937
  globalAttributes += ' xml:lang';
@@ -2947,12 +2945,8 @@
2947
2945
  blockContent,
2948
2946
  html4BlockContent
2949
2947
  ].join(' ');
2950
- flowContent = [
2951
- blockContent,
2952
- phrasingContent
2953
- ].join(' ');
2954
2948
  }
2955
- flowContent = flowContent || [
2949
+ const flowContent = [
2956
2950
  blockContent,
2957
2951
  phrasingContent
2958
2952
  ].join(' ');
@@ -2967,20 +2961,23 @@
2967
2961
  const makeSchema = type => {
2968
2962
  const {globalAttributes, phrasingContent, flowContent} = getElementSetsAsStrings(type);
2969
2963
  const schema = {};
2964
+ const addElement = (name, attributes, children) => {
2965
+ schema[name] = {
2966
+ attributes: mapToObject(attributes, constant({})),
2967
+ attributesOrder: attributes,
2968
+ children: mapToObject(children, constant({}))
2969
+ };
2970
+ };
2970
2971
  const add = (name, attributes = '', children = '') => {
2971
2972
  const childNames = split$1(children);
2972
2973
  const names = split$1(name);
2973
2974
  let ni = names.length;
2975
+ const allAttributes = split$1([
2976
+ globalAttributes,
2977
+ attributes
2978
+ ].join(' '));
2974
2979
  while (ni--) {
2975
- const attributesOrder = split$1([
2976
- globalAttributes,
2977
- attributes
2978
- ].join(' '));
2979
- schema[names[ni]] = {
2980
- attributes: mapToObject(attributesOrder, constant({})),
2981
- attributesOrder,
2982
- children: mapToObject(childNames, constant({}))
2983
- };
2980
+ addElement(names[ni], allAttributes.slice(), childNames);
2984
2981
  }
2985
2982
  };
2986
2983
  const addAttrs = (name, attributes) => {
@@ -3069,7 +3066,11 @@
3069
3066
  'rt rp'
3070
3067
  ].join(' '));
3071
3068
  add('figcaption', '', flowContent);
3072
- add('mark rt rp summary bdi', '', phrasingContent);
3069
+ add('mark rt rp bdi', '', phrasingContent);
3070
+ add('summary', '', [
3071
+ phrasingContent,
3072
+ 'h1 h2 h3 h4 h5 h6'
3073
+ ].join(' '));
3073
3074
  add('canvas', 'width height', flowContent);
3074
3075
  add('video', 'src crossorigin poster preload autoplay mediagroup loop ' + 'muted controls width height buffered', [
3075
3076
  flowContent,
@@ -3103,6 +3104,7 @@
3103
3104
  'summary'
3104
3105
  ].join(' '));
3105
3106
  add('keygen', 'autofocus challenge disabled form keytype name');
3107
+ addElement('svg', 'id tabindex lang xml:space class style x y width height viewBox preserveAspectRatio zoomAndPan transform'.split(' '), []);
3106
3108
  }
3107
3109
  if (type !== 'html5-strict') {
3108
3110
  addAttrs('script', 'language xml:space');
@@ -3352,12 +3354,14 @@
3352
3354
  const voidElementsMap = createLookupTable('void_elements', 'area base basefont br col frame hr img input isindex link ' + 'meta param embed source wbr track');
3353
3355
  const boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' + 'noshade nowrap readonly selected autoplay loop controls allowfullscreen');
3354
3356
  const nonEmptyOrMoveCaretBeforeOnEnter = 'td th iframe video audio object script code';
3355
- const nonEmptyElementsMap = createLookupTable('non_empty_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' pre', voidElementsMap);
3357
+ const nonEmptyElementsMap = createLookupTable('non_empty_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' pre svg', voidElementsMap);
3356
3358
  const moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' table', voidElementsMap);
3357
- const textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' + 'blockquote center dir fieldset header footer article section hgroup aside main nav figure');
3358
- const blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' + 'th tr td li ol ul caption dl dt dd noscript menu isindex option ' + 'datalist select optgroup figcaption details summary', textBlockElementsMap);
3359
+ const headings = 'h1 h2 h3 h4 h5 h6';
3360
+ const textBlockElementsMap = createLookupTable('text_block_elements', headings + ' p div address pre form ' + 'blockquote center dir fieldset header footer article section hgroup aside main nav figure');
3361
+ const blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' + 'th tr td li ol ul caption dl dt dd noscript menu isindex option ' + 'datalist select optgroup figcaption details summary html body multicol listing', textBlockElementsMap);
3359
3362
  const textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font s strike u var cite ' + 'dfn code mark q sup sub samp');
3360
3363
  const transparentElementsMap = createLookupTable('transparent_elements', 'a ins del canvas map');
3364
+ const wrapBlockElementsMap = createLookupTable('wrap_block_elements', 'pre ' + headings);
3361
3365
  each$b('script noscript iframe noframes noembed title style textarea xmp plaintext'.split(' '), name => {
3362
3366
  specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi');
3363
3367
  });
@@ -3477,6 +3481,7 @@
3477
3481
  children[name] = element.children;
3478
3482
  });
3479
3483
  }
3484
+ delete elements.svg;
3480
3485
  addCustomElements(settings.custom_elements);
3481
3486
  addValidChildren(settings.valid_children);
3482
3487
  addValidElements(settings.extended_valid_elements);
@@ -3522,6 +3527,7 @@
3522
3527
  const getMoveCaretBeforeOnEnterElements = constant(moveCaretBeforeOnEnterElementsMap);
3523
3528
  const getWhitespaceElements = constant(whitespaceElementsMap);
3524
3529
  const getTransparentElements = constant(transparentElementsMap);
3530
+ const getWrapBlockElements = constant(wrapBlockElementsMap);
3525
3531
  const getSpecialElements = constant(Object.seal(specialElements));
3526
3532
  const isValidChild = (name, child) => {
3527
3533
  const parent = children[name.toLowerCase()];
@@ -3549,6 +3555,9 @@
3549
3555
  }
3550
3556
  return false;
3551
3557
  };
3558
+ const isBlock = name => has$2(getBlockElements(), name);
3559
+ const isInline = name => !startsWith(name, '#') && isValid(name) && !isBlock(name);
3560
+ const isWrapper = name => has$2(getWrapBlockElements(), name) || isInline(name);
3552
3561
  const getCustomElements = constant(customElementsMap);
3553
3562
  return {
3554
3563
  type: schemaType,
@@ -3571,6 +3580,9 @@
3571
3580
  getSpecialElements,
3572
3581
  isValidChild,
3573
3582
  isValid,
3583
+ isBlock,
3584
+ isInline,
3585
+ isWrapper,
3574
3586
  getCustomElements,
3575
3587
  addValidElements,
3576
3588
  setValidElements,
@@ -3579,6 +3591,50 @@
3579
3591
  };
3580
3592
  };
3581
3593
 
3594
+ const hexColour = value => ({ value: normalizeHex(value) });
3595
+ const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
3596
+ const toHex = component => {
3597
+ const hex = component.toString(16);
3598
+ return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
3599
+ };
3600
+ const fromRgba = rgbaColour => {
3601
+ const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
3602
+ return hexColour(value);
3603
+ };
3604
+
3605
+ const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
3606
+ const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
3607
+ const rgbaColour = (red, green, blue, alpha) => ({
3608
+ red,
3609
+ green,
3610
+ blue,
3611
+ alpha
3612
+ });
3613
+ const fromStringValues = (red, green, blue, alpha) => {
3614
+ const r = parseInt(red, 10);
3615
+ const g = parseInt(green, 10);
3616
+ const b = parseInt(blue, 10);
3617
+ const a = parseFloat(alpha);
3618
+ return rgbaColour(r, g, b, a);
3619
+ };
3620
+ const fromString = rgbaString => {
3621
+ if (rgbaString === 'transparent') {
3622
+ return Optional.some(rgbaColour(0, 0, 0, 0));
3623
+ }
3624
+ const rgbMatch = rgbRegex.exec(rgbaString);
3625
+ if (rgbMatch !== null) {
3626
+ return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
3627
+ }
3628
+ const rgbaMatch = rgbaRegex.exec(rgbaString);
3629
+ if (rgbaMatch !== null) {
3630
+ return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
3631
+ }
3632
+ return Optional.none();
3633
+ };
3634
+ const toString = rgba => `rgba(${ rgba.red },${ rgba.green },${ rgba.blue },${ rgba.alpha })`;
3635
+
3636
+ const rgbaToHexString = color => fromString(color).map(fromRgba).map(h => '#' + h.value).getOr(color);
3637
+
3582
3638
  const Styles = (settings = {}, schema) => {
3583
3639
  const urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
3584
3640
  const styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
@@ -3736,6 +3792,13 @@
3736
3792
  } else if (name === 'color' || name === 'background-color') {
3737
3793
  value = value.toLowerCase();
3738
3794
  }
3795
+ if (isString(settings.force_hex_color) && settings.force_hex_color !== 'off') {
3796
+ fromString(value).each(rgba => {
3797
+ if (settings.force_hex_color === 'always' || rgba.alpha === 1) {
3798
+ value = rgbaToHexString(toString(rgba));
3799
+ }
3800
+ });
3801
+ }
3739
3802
  value = value.replace(urlOrStrRegExp, processUrl);
3740
3803
  styles[name] = isEncoded ? decode(value, true) : value;
3741
3804
  }
@@ -3823,6 +3886,9 @@
3823
3886
  if (isNonNullable(originalEvent.getModifierState)) {
3824
3887
  event.getModifierState = keyArg => originalEvent.getModifierState(keyArg);
3825
3888
  }
3889
+ if (isNonNullable(originalEvent.getTargetRanges)) {
3890
+ event.getTargetRanges = () => originalEvent.getTargetRanges();
3891
+ }
3826
3892
  return event;
3827
3893
  };
3828
3894
  const normalize$3 = (type, originalEvent, fallbackTarget, data) => {
@@ -4216,7 +4282,8 @@
4216
4282
  const schema = settings.schema ? settings.schema : Schema({});
4217
4283
  const styles = Styles({
4218
4284
  url_converter: settings.url_converter,
4219
- url_converter_scope: settings.url_converter_scope
4285
+ url_converter_scope: settings.url_converter_scope,
4286
+ force_hex_color: settings.force_hex_color
4220
4287
  }, settings.schema);
4221
4288
  const events = settings.ownEvents ? new EventUtils() : EventUtils.Event;
4222
4289
  const blockElementsMap = schema.getBlockElements();
@@ -4307,7 +4374,7 @@
4307
4374
  };
4308
4375
  const getStyle = (elm, name, computed) => {
4309
4376
  const $elm = get(elm);
4310
- if (isNullable($elm) || !isElement$6($elm)) {
4377
+ if (isNullable($elm) || !isHTMLElement($elm) && !isSVGElement($elm)) {
4311
4378
  return undefined;
4312
4379
  }
4313
4380
  if (computed) {
@@ -4725,13 +4792,13 @@
4725
4792
  range.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
4726
4793
  range.setEnd(parentNode, findNodeIndex(parentElm) + 1);
4727
4794
  afterFragment = range.extractContents();
4728
- parentNode.insertBefore(trimNode(self, beforeFragment), parentElm);
4795
+ parentNode.insertBefore(trimNode(self, beforeFragment, schema), parentElm);
4729
4796
  if (replacementElm) {
4730
4797
  parentNode.insertBefore(replacementElm, parentElm);
4731
4798
  } else {
4732
4799
  parentNode.insertBefore(splitElm, parentElm);
4733
4800
  }
4734
- parentNode.insertBefore(trimNode(self, afterFragment), parentElm);
4801
+ parentNode.insertBefore(trimNode(self, afterFragment, schema), parentElm);
4735
4802
  remove(parentElm);
4736
4803
  return replacementElm || splitElm;
4737
4804
  } else {
@@ -4782,7 +4849,7 @@
4782
4849
  const dispatch = (target, name, evt) => events.dispatch(target, name, evt);
4783
4850
  const fire = (target, name, evt) => events.dispatch(target, name, evt);
4784
4851
  const getContentEditable = node => {
4785
- if (node && isElement$6(node)) {
4852
+ if (node && isHTMLElement(node)) {
4786
4853
  const contentEditable = node.getAttribute('data-mce-contenteditable');
4787
4854
  if (contentEditable && contentEditable !== 'inherit') {
4788
4855
  return contentEditable;
@@ -4806,7 +4873,7 @@
4806
4873
  const isEditable = node => {
4807
4874
  if (isNonNullable(node)) {
4808
4875
  const scope = isElement$6(node) ? node : node.parentElement;
4809
- return isNonNullable(scope) && isEditable$3(SugarElement.fromDom(scope));
4876
+ return isNonNullable(scope) && isHTMLElement(scope) && isEditable$2(SugarElement.fromDom(scope));
4810
4877
  } else {
4811
4878
  return false;
4812
4879
  }
@@ -5394,7 +5461,7 @@
5394
5461
  return directory;
5395
5462
  };
5396
5463
 
5397
- const setup$x = (editor, registry) => {
5464
+ const setup$y = (editor, registry) => {
5398
5465
  const changeCallbacks = Cell({});
5399
5466
  const initData = () => ({
5400
5467
  listeners: [],
@@ -5476,7 +5543,7 @@
5476
5543
  return { addListener };
5477
5544
  };
5478
5545
 
5479
- const setup$w = (editor, registry) => {
5546
+ const setup$x = (editor, registry) => {
5480
5547
  const dataAnnotation$1 = dataAnnotation();
5481
5548
  const identifyParserNode = node => Optional.from(node.attr(dataAnnotation$1)).bind(registry.lookup);
5482
5549
  const removeDirectAnnotation = node => {
@@ -5746,7 +5813,7 @@
5746
5813
 
5747
5814
  const isElement$4 = isElement$6;
5748
5815
  const isCaretCandidate$2 = isCaretCandidate$3;
5749
- const isBlock$1 = matchStyleValues('display', 'block table');
5816
+ const isBlock$2 = matchStyleValues('display', 'block table');
5750
5817
  const isFloated = matchStyleValues('float', 'left right');
5751
5818
  const isValidElementCaretCandidate = and(isElement$4, isCaretCandidate$2, not(isFloated));
5752
5819
  const isNotPre = not(matchStyleValues('white-space', 'pre pre-line pre-wrap'));
@@ -5886,7 +5953,7 @@
5886
5953
  }
5887
5954
  const beforeNode = resolveIndex$1(caretPosition.container(), caretPosition.offset() - 1);
5888
5955
  if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
5889
- if (isBlock$1(beforeNode) || isBlock$1(node) || !isValidElementCaretCandidate(node)) {
5956
+ if (isBlock$2(beforeNode) || isBlock$2(node) || !isValidElementCaretCandidate(node)) {
5890
5957
  addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(beforeNode), false));
5891
5958
  }
5892
5959
  }
@@ -6867,7 +6934,7 @@
6867
6934
  };
6868
6935
  }
6869
6936
  },
6870
- default: isInline(editor) ? [] : ['default']
6937
+ default: isInline$1(editor) ? [] : ['default']
6871
6938
  });
6872
6939
  registerOption('content_style', { processor: 'string' });
6873
6940
  registerOption('content_css_cors', {
@@ -7336,6 +7403,32 @@
7336
7403
  processor: 'string',
7337
7404
  default: ''
7338
7405
  });
7406
+ registerOption('force_hex_color', {
7407
+ processor: value => {
7408
+ const options = [
7409
+ 'always',
7410
+ 'rgb_only',
7411
+ 'off'
7412
+ ];
7413
+ const valid = contains$2(options, value);
7414
+ return valid ? {
7415
+ value,
7416
+ valid
7417
+ } : {
7418
+ valid: false,
7419
+ message: `Must be one of: ${ options.join(', ') }.`
7420
+ };
7421
+ },
7422
+ default: 'off'
7423
+ });
7424
+ registerOption('sandbox_iframes', {
7425
+ processor: 'boolean',
7426
+ default: false
7427
+ });
7428
+ registerOption('convert_unsafe_embeds', {
7429
+ processor: 'boolean',
7430
+ default: false
7431
+ });
7339
7432
  editor.on('ScriptsLoaded', () => {
7340
7433
  registerOption('directionality', {
7341
7434
  processor: 'string',
@@ -7396,7 +7489,7 @@
7396
7489
  const canFormatEmptyLines = option('format_empty_lines');
7397
7490
  const getFormatNoneditableSelector = option('format_noneditable_selector');
7398
7491
  const getCustomUiSelector = option('custom_ui_selector');
7399
- const isInline = option('inline');
7492
+ const isInline$1 = option('inline');
7400
7493
  const hasHiddenInput = option('hidden_input');
7401
7494
  const shouldPatchSubmit = option('submit_patch');
7402
7495
  const shouldAddFormSubmitTrigger = option('add_form_submit_trigger');
@@ -7448,6 +7541,8 @@
7448
7541
  const hasTableTabNavigation = option('table_tab_navigation');
7449
7542
  const getDetailsInitialState = option('details_initial_state');
7450
7543
  const getDetailsSerializedState = option('details_serialized_state');
7544
+ const shouldForceHexColor = option('force_hex_color');
7545
+ const shouldSandboxIframes = option('sandbox_iframes');
7451
7546
 
7452
7547
  const isElement$3 = isElement$6;
7453
7548
  const isText$5 = isText$a;
@@ -7664,7 +7759,7 @@
7664
7759
  const isInlineFakeCaretTarget = node => isContentEditableFalse$8(node) || isMedia$1(node);
7665
7760
  const isFakeCaretTarget = node => {
7666
7761
  const isTarget = isInlineFakeCaretTarget(node) || isTable$2(node) && isFakeCaretTableBrowser();
7667
- return isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$3);
7762
+ return isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$2);
7668
7763
  };
7669
7764
 
7670
7765
  const isContentEditableTrue$1 = isContentEditableTrue$3;
@@ -8345,49 +8440,6 @@
8345
8440
  const isWhiteSpace = chr => chr !== '' && ' \f\n\r\t\x0B'.indexOf(chr) !== -1;
8346
8441
  const isContent = chr => !isWhiteSpace(chr) && !isNbsp(chr) && !isZwsp$2(chr);
8347
8442
 
8348
- const hexColour = value => ({ value: normalizeHex(value) });
8349
- const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
8350
- const toHex = component => {
8351
- const hex = component.toString(16);
8352
- return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
8353
- };
8354
- const fromRgba = rgbaColour => {
8355
- const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
8356
- return hexColour(value);
8357
- };
8358
-
8359
- const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
8360
- const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
8361
- const rgbaColour = (red, green, blue, alpha) => ({
8362
- red,
8363
- green,
8364
- blue,
8365
- alpha
8366
- });
8367
- const fromStringValues = (red, green, blue, alpha) => {
8368
- const r = parseInt(red, 10);
8369
- const g = parseInt(green, 10);
8370
- const b = parseInt(blue, 10);
8371
- const a = parseFloat(alpha);
8372
- return rgbaColour(r, g, b, a);
8373
- };
8374
- const fromString = rgbaString => {
8375
- if (rgbaString === 'transparent') {
8376
- return Optional.some(rgbaColour(0, 0, 0, 0));
8377
- }
8378
- const rgbMatch = rgbRegex.exec(rgbaString);
8379
- if (rgbMatch !== null) {
8380
- return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
8381
- }
8382
- const rgbaMatch = rgbaRegex.exec(rgbaString);
8383
- if (rgbaMatch !== null) {
8384
- return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
8385
- }
8386
- return Optional.none();
8387
- };
8388
-
8389
- const rgbaToHexString = color => fromString(color).map(fromRgba).map(h => '#' + h.value).getOr(color);
8390
-
8391
8443
  const getRanges$1 = selection => {
8392
8444
  const ranges = [];
8393
8445
  if (selection) {
@@ -8529,7 +8581,6 @@
8529
8581
  return false;
8530
8582
  }
8531
8583
  };
8532
- const isEditable$2 = elm => elm.isContentEditable === true;
8533
8584
  const preserveSelection = (editor, action, shouldMoveStart) => {
8534
8585
  const {selection, dom} = editor;
8535
8586
  const selectedNodeBeforeAction = selection.getNode();
@@ -8706,6 +8757,26 @@
8706
8757
  const isInlineFormat = format => hasNonNullableKey(format, 'inline');
8707
8758
  const isMixedFormat = format => isSelectorFormat(format) && isInlineFormat(format) && is$2(get$a(format, 'mixed'), true);
8708
8759
  const shouldExpandToSelector = format => isSelectorFormat(format) && format.expand !== false && !isInlineFormat(format);
8760
+ const getEmptyCaretContainers = node => {
8761
+ const nodes = [];
8762
+ let tempNode = node;
8763
+ while (tempNode) {
8764
+ if (isText$a(tempNode) && tempNode.data !== ZWSP$1 || tempNode.childNodes.length > 1) {
8765
+ return [];
8766
+ }
8767
+ if (isElement$6(tempNode)) {
8768
+ nodes.push(tempNode);
8769
+ }
8770
+ tempNode = tempNode.firstChild;
8771
+ }
8772
+ return nodes;
8773
+ };
8774
+ const isCaretContainerEmpty = node => {
8775
+ return getEmptyCaretContainers(node).length > 0;
8776
+ };
8777
+ const isEmptyCaretFormatElement = element => {
8778
+ return isCaretNode(element.dom) && isCaretContainerEmpty(element.dom);
8779
+ };
8709
8780
 
8710
8781
  const isBookmarkNode = isBookmarkNode$1;
8711
8782
  const getParents$1 = getParents$2;
@@ -8792,7 +8863,7 @@
8792
8863
  node = format.wrapper ? null : dom.getParent(container, format.block, root);
8793
8864
  }
8794
8865
  if (!node) {
8795
- const scopeRoot = (_a = dom.getParent(container, 'LI,TD,TH')) !== null && _a !== void 0 ? _a : root;
8866
+ const scopeRoot = (_a = dom.getParent(container, 'LI,TD,TH,SUMMARY')) !== null && _a !== void 0 ? _a : root;
8796
8867
  node = dom.getParent(isText$a(container) ? container.parentNode : container, node => node !== root && isTextBlock(dom.schema, node), scopeRoot);
8797
8868
  }
8798
8869
  if (node && isBlockFormat(format) && format.wrapper) {
@@ -9136,8 +9207,8 @@
9136
9207
 
9137
9208
  const Annotator = editor => {
9138
9209
  const registry = create$c();
9139
- setup$w(editor, registry);
9140
- const changes = setup$x(editor, registry);
9210
+ setup$x(editor, registry);
9211
+ const changes = setup$y(editor, registry);
9141
9212
  const isSpan = isTag('span');
9142
9213
  const removeAnnotations = elements => {
9143
9214
  each$e(elements, element => {
@@ -9598,7 +9669,7 @@
9598
9669
  return;
9599
9670
  }
9600
9671
  const targetElm = e.type === 'mousedown' ? e.target : selection.getNode();
9601
- const controlElm = closest$3(SugarElement.fromDom(targetElm), controlElmSelector).map(e => e.dom).filter(e => dom.isEditable(e.parentElement)).getOrUndefined();
9672
+ const controlElm = closest$3(SugarElement.fromDom(targetElm), controlElmSelector).map(e => e.dom).filter(e => dom.isEditable(e.parentElement) || e.nodeName === 'IMG' && dom.isEditable(e)).getOrUndefined();
9602
9673
  const selectedValue = isNonNullable(controlElm) ? dom.getAttrib(controlElm, elementSelectionAttr, '1') : '1';
9603
9674
  each$e(dom.select(`img[${ elementSelectionAttr }],hr[${ elementSelectionAttr }]`), img => {
9604
9675
  img.removeAttribute(elementSelectionAttr);
@@ -10025,6 +10096,9 @@
10025
10096
  if (hasContentEditableFalseParent(body, container) || isCaretContainer$2(container)) {
10026
10097
  return Optional.none();
10027
10098
  }
10099
+ if (isDetails(container)) {
10100
+ return Optional.none();
10101
+ }
10028
10102
  if (container.hasChildNodes() && !isTable$2(container)) {
10029
10103
  node = container;
10030
10104
  const walker = new DomTreeWalker(container, body);
@@ -10418,7 +10492,7 @@
10418
10492
  scroller(editor, rng, alignToTop);
10419
10493
  };
10420
10494
 
10421
- const focus$1 = element => element.dom.focus();
10495
+ const focus$1 = (element, preventScroll = false) => element.dom.focus({ preventScroll });
10422
10496
  const hasFocus$1 = element => {
10423
10497
  const root = getRootNode(element).dom;
10424
10498
  return element.dom === root.activeElement;
@@ -10641,7 +10715,7 @@
10641
10715
  documentFocusInHandler = null;
10642
10716
  }
10643
10717
  };
10644
- const setup$v = editorManager => {
10718
+ const setup$w = editorManager => {
10645
10719
  editorManager.on('AddEditor', curry(registerEvents$1, editorManager));
10646
10720
  editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
10647
10721
  };
@@ -10729,6 +10803,14 @@
10729
10803
  }
10730
10804
  };
10731
10805
 
10806
+ const isEditableRange = (dom, rng) => {
10807
+ if (rng.collapsed) {
10808
+ return dom.isEditable(rng.startContainer);
10809
+ } else {
10810
+ return dom.isEditable(rng.startContainer) && dom.isEditable(rng.endContainer);
10811
+ }
10812
+ };
10813
+
10732
10814
  const getEndpointElement = (root, rng, start, real, resolve) => {
10733
10815
  const container = start ? rng.startContainer : rng.endContainer;
10734
10816
  const offset = start ? rng.startOffset : rng.endOffset;
@@ -10777,7 +10859,7 @@
10777
10859
  }
10778
10860
  }
10779
10861
  const elm = isText$a(node) ? node.parentNode : node;
10780
- return isElement$6(elm) ? elm : root;
10862
+ return isHTMLElement(elm) ? elm : root;
10781
10863
  };
10782
10864
  const getSelectedBlocks = (dom, rng, startElm, endElm) => {
10783
10865
  const selectedBlocks = [];
@@ -10820,7 +10902,7 @@
10820
10902
 
10821
10903
  const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$1(element).length, v => v.length);
10822
10904
  const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
10823
- const isContentEditableFalse$5 = elem => isHTMLElement(elem) && get$9(elem, 'contenteditable') === 'false';
10905
+ const isContentEditableFalse$5 = elem => isHTMLElement$1(elem) && get$9(elem, 'contenteditable') === 'false';
10824
10906
  const elementsWithCursorPosition = [
10825
10907
  'img',
10826
10908
  'br'
@@ -10830,7 +10912,7 @@
10830
10912
  return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse$5(elem);
10831
10913
  };
10832
10914
 
10833
- const first = element => descendant$1(element, isCursorPosition);
10915
+ const first = element => descendant$2(element, isCursorPosition);
10834
10916
  const last = element => descendantRtl(element, isCursorPosition);
10835
10917
  const descendantRtl = (scope, predicate) => {
10836
10918
  const descend = element => {
@@ -10863,7 +10945,7 @@
10863
10945
  }
10864
10946
  };
10865
10947
  const detect$1 = elm => closest$3(elm, autocompleteSelector);
10866
- const findIn = elm => descendant(elm, autocompleteSelector);
10948
+ const findIn = elm => descendant$1(elm, autocompleteSelector);
10867
10949
  const remove$2 = (editor, elm) => findIn(elm).each(wrapper => {
10868
10950
  const bookmark = editor.selection.getBookmark();
10869
10951
  unwrap(wrapper);
@@ -11168,13 +11250,24 @@
11168
11250
  }
11169
11251
  }
11170
11252
 
11253
+ const unescapedTextParents = Tools.makeMap('NOSCRIPT STYLE SCRIPT XMP IFRAME NOEMBED NOFRAMES PLAINTEXT', ' ');
11254
+ const containsZwsp = node => isString(node.nodeValue) && node.nodeValue.includes(ZWSP$1);
11171
11255
  const getTemporaryNodeSelector = tempAttrs => `${ tempAttrs.length === 0 ? '' : `${ map$3(tempAttrs, attr => `[${ attr }]`).join(',') },` }[data-mce-bogus="all"]`;
11172
- const getTemporaryNodes = (body, tempAttrs) => body.querySelectorAll(getTemporaryNodeSelector(tempAttrs));
11173
- const createCommentWalker = body => document.createTreeWalker(body, NodeFilter.SHOW_COMMENT, null);
11174
- const hasComments = body => createCommentWalker(body).nextNode() !== null;
11175
- const hasTemporaryNodes = (body, tempAttrs) => body.querySelector(getTemporaryNodeSelector(tempAttrs)) !== null;
11176
- const trimTemporaryNodes = (body, tempAttrs) => {
11177
- each$e(getTemporaryNodes(body, tempAttrs), elm => {
11256
+ const getTemporaryNodes = (tempAttrs, body) => body.querySelectorAll(getTemporaryNodeSelector(tempAttrs));
11257
+ const createZwspCommentWalker = body => document.createTreeWalker(body, NodeFilter.SHOW_COMMENT, node => containsZwsp(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP);
11258
+ const createUnescapedZwspTextWalker = body => document.createTreeWalker(body, NodeFilter.SHOW_TEXT, node => {
11259
+ if (containsZwsp(node)) {
11260
+ const parent = node.parentNode;
11261
+ return parent && has$2(unescapedTextParents, parent.nodeName) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
11262
+ } else {
11263
+ return NodeFilter.FILTER_SKIP;
11264
+ }
11265
+ });
11266
+ const hasZwspComment = body => createZwspCommentWalker(body).nextNode() !== null;
11267
+ const hasUnescapedZwspText = body => createUnescapedZwspTextWalker(body).nextNode() !== null;
11268
+ const hasTemporaryNode = (tempAttrs, body) => body.querySelector(getTemporaryNodeSelector(tempAttrs)) !== null;
11269
+ const trimTemporaryNodes = (tempAttrs, body) => {
11270
+ each$e(getTemporaryNodes(tempAttrs, body), elm => {
11178
11271
  const element = SugarElement.fromDom(elm);
11179
11272
  if (get$9(element, 'data-mce-bogus') === 'all') {
11180
11273
  remove$5(element);
@@ -11187,30 +11280,41 @@
11187
11280
  }
11188
11281
  });
11189
11282
  };
11190
- const removeCommentsContainingZwsp = body => {
11191
- const walker = createCommentWalker(body);
11192
- let nextNode = walker.nextNode();
11193
- while (nextNode !== null) {
11194
- const comment = walker.currentNode;
11195
- nextNode = walker.nextNode();
11196
- if (isString(comment.nodeValue) && comment.nodeValue.includes(ZWSP$1)) {
11197
- remove$5(SugarElement.fromDom(comment));
11198
- }
11283
+ const emptyAllNodeValuesInWalker = walker => {
11284
+ let curr = walker.nextNode();
11285
+ while (curr !== null) {
11286
+ curr.nodeValue = null;
11287
+ curr = walker.nextNode();
11199
11288
  }
11200
11289
  };
11201
- const deepClone = body => body.cloneNode(true);
11290
+ const emptyZwspComments = compose(emptyAllNodeValuesInWalker, createZwspCommentWalker);
11291
+ const emptyUnescapedZwspTexts = compose(emptyAllNodeValuesInWalker, createUnescapedZwspTextWalker);
11202
11292
  const trim$1 = (body, tempAttrs) => {
11293
+ const conditionalTrims = [
11294
+ {
11295
+ condition: curry(hasTemporaryNode, tempAttrs),
11296
+ action: curry(trimTemporaryNodes, tempAttrs)
11297
+ },
11298
+ {
11299
+ condition: hasZwspComment,
11300
+ action: emptyZwspComments
11301
+ },
11302
+ {
11303
+ condition: hasUnescapedZwspText,
11304
+ action: emptyUnescapedZwspTexts
11305
+ }
11306
+ ];
11203
11307
  let trimmed = body;
11204
- if (hasComments(body)) {
11205
- trimmed = deepClone(body);
11206
- removeCommentsContainingZwsp(trimmed);
11207
- if (hasTemporaryNodes(trimmed, tempAttrs)) {
11208
- trimTemporaryNodes(trimmed, tempAttrs);
11308
+ let cloned = false;
11309
+ each$e(conditionalTrims, ({condition, action}) => {
11310
+ if (condition(trimmed)) {
11311
+ if (!cloned) {
11312
+ trimmed = body.cloneNode(true);
11313
+ cloned = true;
11314
+ }
11315
+ action(trimmed);
11209
11316
  }
11210
- } else if (hasTemporaryNodes(body, tempAttrs)) {
11211
- trimmed = deepClone(body);
11212
- trimTemporaryNodes(trimmed, tempAttrs);
11213
- }
11317
+ });
11214
11318
  return trimmed;
11215
11319
  };
11216
11320
 
@@ -11427,17 +11531,24 @@
11427
11531
  }
11428
11532
  }
11429
11533
  writer.start(name, attrs, isEmpty);
11430
- if (!isEmpty) {
11431
- let child = node.firstChild;
11432
- if (child) {
11433
- if ((name === 'pre' || name === 'textarea') && child.type === 3 && ((_a = child.value) === null || _a === void 0 ? void 0 : _a[0]) === '\n') {
11434
- writer.text('\n', true);
11435
- }
11436
- do {
11437
- walk(child);
11438
- } while (child = child.next);
11534
+ if (isNonHtmlElementRootName(name)) {
11535
+ if (isString(node.value)) {
11536
+ writer.text(node.value, true);
11439
11537
  }
11440
11538
  writer.end(name);
11539
+ } else {
11540
+ if (!isEmpty) {
11541
+ let child = node.firstChild;
11542
+ if (child) {
11543
+ if ((name === 'pre' || name === 'textarea') && child.type === 3 && ((_a = child.value) === null || _a === void 0 ? void 0 : _a[0]) === '\n') {
11544
+ writer.text('\n', true);
11545
+ }
11546
+ do {
11547
+ walk(child);
11548
+ } while (child = child.next);
11549
+ }
11550
+ writer.end(name);
11551
+ }
11441
11552
  }
11442
11553
  } else {
11443
11554
  handler(node);
@@ -11576,42 +11687,43 @@
11576
11687
  const parentsAndSelf = (start, root) => [start].concat(parents(start, root));
11577
11688
 
11578
11689
  const navigateIgnoreEmptyTextNodes = (forward, root, from) => navigateIgnore(forward, root, from, isEmptyText);
11579
- const getClosestBlock$1 = (root, pos) => find$2(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2);
11580
- const isAtBeforeAfterBlockBoundary = (forward, root, pos) => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => getClosestBlock$1(root, pos).fold(() => !isInSameBlock(newPos, pos, root.dom), fromBlock => !isInSameBlock(newPos, pos, root.dom) && contains(fromBlock, SugarElement.fromDom(newPos.container()))));
11581
- const isAtBlockBoundary = (forward, root, pos) => getClosestBlock$1(root, pos).fold(() => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => !isInSameBlock(newPos, pos, root.dom)), parent => navigateIgnoreEmptyTextNodes(forward, parent.dom, pos).isNone());
11690
+ const isBlock$1 = schema => el => schema.isBlock(name(el));
11691
+ const getClosestBlock$1 = (root, pos, schema) => find$2(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$1(schema));
11692
+ const isAtBeforeAfterBlockBoundary = (forward, root, pos, schema) => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => getClosestBlock$1(root, pos, schema).fold(() => !isInSameBlock(newPos, pos, root.dom), fromBlock => !isInSameBlock(newPos, pos, root.dom) && contains(fromBlock, SugarElement.fromDom(newPos.container()))));
11693
+ const isAtBlockBoundary = (forward, root, pos, schema) => getClosestBlock$1(root, pos, schema).fold(() => navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(newPos => !isInSameBlock(newPos, pos, root.dom)), parent => navigateIgnoreEmptyTextNodes(forward, parent.dom, pos).isNone());
11582
11694
  const isAtStartOfBlock = curry(isAtBlockBoundary, false);
11583
11695
  const isAtEndOfBlock = curry(isAtBlockBoundary, true);
11584
11696
  const isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false);
11585
11697
  const isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true);
11586
11698
 
11587
11699
  const isBr$1 = pos => getElementFromPosition(pos).exists(isBr$5);
11588
- const findBr = (forward, root, pos) => {
11589
- const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2);
11700
+ const findBr = (forward, root, pos, schema) => {
11701
+ const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), el => schema.isBlock(name(el)));
11590
11702
  const scope = head(parentBlocks).getOr(root);
11591
11703
  return fromPosition(forward, scope.dom, pos).filter(isBr$1);
11592
11704
  };
11593
- const isBeforeBr$1 = (root, pos) => getElementFromPosition(pos).exists(isBr$5) || findBr(true, root, pos).isSome();
11594
- const isAfterBr = (root, pos) => getElementFromPrevPosition(pos).exists(isBr$5) || findBr(false, root, pos).isSome();
11705
+ const isBeforeBr$1 = (root, pos, schema) => getElementFromPosition(pos).exists(isBr$5) || findBr(true, root, pos, schema).isSome();
11706
+ const isAfterBr = (root, pos, schema) => getElementFromPrevPosition(pos).exists(isBr$5) || findBr(false, root, pos, schema).isSome();
11595
11707
  const findPreviousBr = curry(findBr, false);
11596
11708
  const findNextBr = curry(findBr, true);
11597
11709
 
11598
11710
  const isInMiddleOfText = pos => CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
11599
- const getClosestBlock = (root, pos) => {
11600
- const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$2);
11711
+ const getClosestBlock = (root, pos, schema) => {
11712
+ const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), el => schema.isBlock(name(el)));
11601
11713
  return head(parentBlocks).getOr(root);
11602
11714
  };
11603
- const hasSpaceBefore = (root, pos) => {
11715
+ const hasSpaceBefore = (root, pos, schema) => {
11604
11716
  if (isInMiddleOfText(pos)) {
11605
11717
  return isAfterSpace(pos);
11606
11718
  } else {
11607
- return isAfterSpace(pos) || prevPosition(getClosestBlock(root, pos).dom, pos).exists(isAfterSpace);
11719
+ return isAfterSpace(pos) || prevPosition(getClosestBlock(root, pos, schema).dom, pos).exists(isAfterSpace);
11608
11720
  }
11609
11721
  };
11610
- const hasSpaceAfter = (root, pos) => {
11722
+ const hasSpaceAfter = (root, pos, schema) => {
11611
11723
  if (isInMiddleOfText(pos)) {
11612
11724
  return isBeforeSpace(pos);
11613
11725
  } else {
11614
- return isBeforeSpace(pos) || nextPosition(getClosestBlock(root, pos).dom, pos).exists(isBeforeSpace);
11726
+ return isBeforeSpace(pos) || nextPosition(getClosestBlock(root, pos, schema).dom, pos).exists(isBeforeSpace);
11615
11727
  }
11616
11728
  };
11617
11729
  const isPreValue = value => contains$2([
@@ -11621,7 +11733,7 @@
11621
11733
  const isInPre = pos => getElementFromPosition(pos).bind(elm => closest$4(elm, isElement$7)).exists(elm => isPreValue(get$7(elm, 'white-space')));
11622
11734
  const isAtBeginningOfBody = (root, pos) => prevPosition(root.dom, pos).isNone();
11623
11735
  const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
11624
- const isAtLineBoundary = (root, pos) => isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos) || isAtEndOfBlock(root, pos) || isAfterBr(root, pos) || isBeforeBr$1(root, pos);
11736
+ const isAtLineBoundary = (root, pos, schema) => isAtBeginningOfBody(root, pos) || isAtEndOfBody(root, pos) || isAtStartOfBlock(root, pos, schema) || isAtEndOfBlock(root, pos, schema) || isAfterBr(root, pos, schema) || isBeforeBr$1(root, pos, schema);
11625
11737
  const isCefBlock = node => isNonNullable(node) && isContentEditableFalse$b(node) && isBlockLike(node);
11626
11738
  const isSiblingCefBlock = (root, direction) => container => {
11627
11739
  return isCefBlock(new DomTreeWalker(container, root)[direction]());
@@ -11636,18 +11748,18 @@
11636
11748
  const isPrevCefBlock = isSiblingCefBlock(root.dom, 'prev');
11637
11749
  return pos.isAtStart() && (isPrevCefBlock(pos.container()) || isPrevCefBlock(prevPos.container()));
11638
11750
  };
11639
- const needsToHaveNbsp = (root, pos) => {
11751
+ const needsToHaveNbsp = (root, pos, schema) => {
11640
11752
  if (isInPre(pos)) {
11641
11753
  return false;
11642
11754
  } else {
11643
- return isAtLineBoundary(root, pos) || hasSpaceBefore(root, pos) || hasSpaceAfter(root, pos);
11755
+ return isAtLineBoundary(root, pos, schema) || hasSpaceBefore(root, pos, schema) || hasSpaceAfter(root, pos, schema);
11644
11756
  }
11645
11757
  };
11646
- const needsToBeNbspLeft = (root, pos) => {
11758
+ const needsToBeNbspLeft = (root, pos, schema) => {
11647
11759
  if (isInPre(pos)) {
11648
11760
  return false;
11649
11761
  } else {
11650
- return isAtStartOfBlock(root, pos) || isBeforeBlock(root, pos) || isAfterBr(root, pos) || hasSpaceBefore(root, pos) || isAfterCefBlock(root, pos);
11762
+ return isAtStartOfBlock(root, pos, schema) || isBeforeBlock(root, pos, schema) || isAfterBr(root, pos, schema) || hasSpaceBefore(root, pos, schema) || isAfterCefBlock(root, pos);
11651
11763
  }
11652
11764
  };
11653
11765
  const leanRight = pos => {
@@ -11659,14 +11771,14 @@
11659
11771
  return pos;
11660
11772
  }
11661
11773
  };
11662
- const needsToBeNbspRight = (root, pos) => {
11774
+ const needsToBeNbspRight = (root, pos, schema) => {
11663
11775
  if (isInPre(pos)) {
11664
11776
  return false;
11665
11777
  } else {
11666
- return isAtEndOfBlock(root, pos) || isAfterBlock(root, pos) || isBeforeBr$1(root, pos) || hasSpaceAfter(root, pos) || isBeforeCefBlock(root, pos);
11778
+ return isAtEndOfBlock(root, pos, schema) || isAfterBlock(root, pos, schema) || isBeforeBr$1(root, pos, schema) || hasSpaceAfter(root, pos, schema) || isBeforeCefBlock(root, pos);
11667
11779
  }
11668
11780
  };
11669
- const needsToBeNbsp = (root, pos) => needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, leanRight(pos));
11781
+ const needsToBeNbsp = (root, pos, schema) => needsToBeNbspLeft(root, pos, schema) || needsToBeNbspRight(root, leanRight(pos), schema);
11670
11782
  const isNbspAt = (text, offset) => isNbsp(text.charAt(offset));
11671
11783
  const isWhiteSpaceAt = (text, offset) => isWhiteSpace(text.charAt(offset));
11672
11784
  const hasNbsp = pos => {
@@ -11683,13 +11795,13 @@
11683
11795
  }
11684
11796
  }).join('');
11685
11797
  };
11686
- const normalizeNbspAtStart = (root, node, makeNbsp) => {
11798
+ const normalizeNbspAtStart = (root, node, makeNbsp, schema) => {
11687
11799
  const text = node.data;
11688
11800
  const firstPos = CaretPosition(node, 0);
11689
- if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) {
11801
+ if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos, schema)) {
11690
11802
  node.data = ' ' + text.slice(1);
11691
11803
  return true;
11692
- } else if (makeNbsp && isWhiteSpaceAt(text, 0) && needsToBeNbspLeft(root, firstPos)) {
11804
+ } else if (makeNbsp && isWhiteSpaceAt(text, 0) && needsToBeNbspLeft(root, firstPos, schema)) {
11693
11805
  node.data = nbsp + text.slice(1);
11694
11806
  return true;
11695
11807
  } else {
@@ -11706,29 +11818,29 @@
11706
11818
  return false;
11707
11819
  }
11708
11820
  };
11709
- const normalizeNbspAtEnd = (root, node, makeNbsp) => {
11821
+ const normalizeNbspAtEnd = (root, node, makeNbsp, schema) => {
11710
11822
  const text = node.data;
11711
11823
  const lastPos = CaretPosition(node, text.length - 1);
11712
- if (!makeNbsp && isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos)) {
11824
+ if (!makeNbsp && isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos, schema)) {
11713
11825
  node.data = text.slice(0, -1) + ' ';
11714
11826
  return true;
11715
- } else if (makeNbsp && isWhiteSpaceAt(text, text.length - 1) && needsToBeNbspRight(root, lastPos)) {
11827
+ } else if (makeNbsp && isWhiteSpaceAt(text, text.length - 1) && needsToBeNbspRight(root, lastPos, schema)) {
11716
11828
  node.data = text.slice(0, -1) + nbsp;
11717
11829
  return true;
11718
11830
  } else {
11719
11831
  return false;
11720
11832
  }
11721
11833
  };
11722
- const normalizeNbsps = (root, pos) => {
11834
+ const normalizeNbsps = (root, pos, schema) => {
11723
11835
  const container = pos.container();
11724
11836
  if (!isText$a(container)) {
11725
11837
  return Optional.none();
11726
11838
  }
11727
11839
  if (hasNbsp(pos)) {
11728
- const normalized = normalizeNbspAtStart(root, container, false) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container, false);
11840
+ const normalized = normalizeNbspAtStart(root, container, false, schema) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container, false, schema);
11729
11841
  return someIf(normalized, pos);
11730
- } else if (needsToBeNbsp(root, pos)) {
11731
- const normalized = normalizeNbspAtStart(root, container, true) || normalizeNbspAtEnd(root, container, true);
11842
+ } else if (needsToBeNbsp(root, pos, schema)) {
11843
+ const normalized = normalizeNbspAtStart(root, container, true, schema) || normalizeNbspAtEnd(root, container, true, schema);
11732
11844
  return someIf(normalized, pos);
11733
11845
  } else {
11734
11846
  return Optional.none();
@@ -11737,34 +11849,34 @@
11737
11849
  const normalizeNbspsInEditor = editor => {
11738
11850
  const root = SugarElement.fromDom(editor.getBody());
11739
11851
  if (editor.selection.isCollapsed()) {
11740
- normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng())).each(pos => {
11852
+ normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng()), editor.schema).each(pos => {
11741
11853
  editor.selection.setRng(pos.toRange());
11742
11854
  });
11743
11855
  }
11744
11856
  };
11745
11857
 
11746
- const normalize$1 = (node, offset, count) => {
11858
+ const normalize$1 = (node, offset, count, schema) => {
11747
11859
  if (count === 0) {
11748
11860
  return;
11749
11861
  }
11750
11862
  const elm = SugarElement.fromDom(node);
11751
- const root = ancestor$4(elm, isBlock$2).getOr(elm);
11863
+ const root = ancestor$4(elm, el => schema.isBlock(name(el))).getOr(elm);
11752
11864
  const whitespace = node.data.slice(offset, offset + count);
11753
- const isEndOfContent = offset + count >= node.data.length && needsToBeNbspRight(root, CaretPosition(node, node.data.length));
11754
- const isStartOfContent = offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0));
11865
+ const isEndOfContent = offset + count >= node.data.length && needsToBeNbspRight(root, CaretPosition(node, node.data.length), schema);
11866
+ const isStartOfContent = offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0), schema);
11755
11867
  node.replaceData(offset, count, normalize$4(whitespace, 4, isStartOfContent, isEndOfContent));
11756
11868
  };
11757
- const normalizeWhitespaceAfter = (node, offset) => {
11869
+ const normalizeWhitespaceAfter = (node, offset, schema) => {
11758
11870
  const content = node.data.slice(offset);
11759
11871
  const whitespaceCount = content.length - lTrim(content).length;
11760
- normalize$1(node, offset, whitespaceCount);
11872
+ normalize$1(node, offset, whitespaceCount, schema);
11761
11873
  };
11762
- const normalizeWhitespaceBefore = (node, offset) => {
11874
+ const normalizeWhitespaceBefore = (node, offset, schema) => {
11763
11875
  const content = node.data.slice(0, offset);
11764
11876
  const whitespaceCount = content.length - rTrim(content).length;
11765
- normalize$1(node, offset - whitespaceCount, whitespaceCount);
11877
+ normalize$1(node, offset - whitespaceCount, whitespaceCount, schema);
11766
11878
  };
11767
- const mergeTextNodes = (prevNode, nextNode, normalizeWhitespace, mergeToPrev = true) => {
11879
+ const mergeTextNodes = (prevNode, nextNode, schema, normalizeWhitespace, mergeToPrev = true) => {
11768
11880
  const whitespaceOffset = rTrim(prevNode.data).length;
11769
11881
  const newNode = mergeToPrev ? prevNode : nextNode;
11770
11882
  const removeNode = mergeToPrev ? nextNode : prevNode;
@@ -11775,7 +11887,7 @@
11775
11887
  }
11776
11888
  remove$5(SugarElement.fromDom(removeNode));
11777
11889
  if (normalizeWhitespace) {
11778
- normalizeWhitespaceAfter(newNode, whitespaceOffset);
11890
+ normalizeWhitespaceAfter(newNode, whitespaceOffset, schema);
11779
11891
  }
11780
11892
  return newNode;
11781
11893
  };
@@ -11819,43 +11931,51 @@
11819
11931
  };
11820
11932
  const eqRawNode = rawNode => elm => elm.dom === rawNode;
11821
11933
  const isBlock = (editor, elm) => elm && has$2(editor.schema.getBlockElements(), name(elm));
11822
- const paddEmptyBlock = elm => {
11934
+ const paddEmptyBlock = (elm, preserveEmptyCaret) => {
11823
11935
  if (isEmpty$2(elm)) {
11824
11936
  const br = SugarElement.fromHtml('<br data-mce-bogus="1">');
11825
- empty(elm);
11937
+ if (preserveEmptyCaret) {
11938
+ each$e(children$1(elm), node => {
11939
+ if (!isEmptyCaretFormatElement(node)) {
11940
+ remove$5(node);
11941
+ }
11942
+ });
11943
+ } else {
11944
+ empty(elm);
11945
+ }
11826
11946
  append$1(elm, br);
11827
11947
  return Optional.some(CaretPosition.before(br.dom));
11828
11948
  } else {
11829
11949
  return Optional.none();
11830
11950
  }
11831
11951
  };
11832
- const deleteNormalized = (elm, afterDeletePosOpt, normalizeWhitespace) => {
11952
+ const deleteNormalized = (elm, afterDeletePosOpt, schema, normalizeWhitespace) => {
11833
11953
  const prevTextOpt = prevSibling(elm).filter(isText$b);
11834
11954
  const nextTextOpt = nextSibling(elm).filter(isText$b);
11835
11955
  remove$5(elm);
11836
11956
  return lift3(prevTextOpt, nextTextOpt, afterDeletePosOpt, (prev, next, pos) => {
11837
11957
  const prevNode = prev.dom, nextNode = next.dom;
11838
11958
  const offset = prevNode.data.length;
11839
- mergeTextNodes(prevNode, nextNode, normalizeWhitespace);
11959
+ mergeTextNodes(prevNode, nextNode, schema, normalizeWhitespace);
11840
11960
  return pos.container() === nextNode ? CaretPosition(prevNode, offset) : pos;
11841
11961
  }).orThunk(() => {
11842
11962
  if (normalizeWhitespace) {
11843
- prevTextOpt.each(elm => normalizeWhitespaceBefore(elm.dom, elm.dom.length));
11844
- nextTextOpt.each(elm => normalizeWhitespaceAfter(elm.dom, 0));
11963
+ prevTextOpt.each(elm => normalizeWhitespaceBefore(elm.dom, elm.dom.length, schema));
11964
+ nextTextOpt.each(elm => normalizeWhitespaceAfter(elm.dom, 0, schema));
11845
11965
  }
11846
11966
  return afterDeletePosOpt;
11847
11967
  });
11848
11968
  };
11849
11969
  const isInlineElement = (editor, element) => has$2(editor.schema.getTextInlineElements(), name(element));
11850
- const deleteElement$2 = (editor, forward, elm, moveCaret = true) => {
11970
+ const deleteElement$2 = (editor, forward, elm, moveCaret = true, preserveEmptyCaret = false) => {
11851
11971
  const afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom);
11852
11972
  const parentBlock = ancestor$4(elm, curry(isBlock, editor), eqRawNode(editor.getBody()));
11853
- const normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, isInlineElement(editor, elm));
11973
+ const normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, editor.schema, isInlineElement(editor, elm));
11854
11974
  if (editor.dom.isEmpty(editor.getBody())) {
11855
11975
  editor.setContent('');
11856
11976
  editor.selection.setCursorLocation();
11857
11977
  } else {
11858
- parentBlock.bind(paddEmptyBlock).fold(() => {
11978
+ parentBlock.bind(elm => paddEmptyBlock(elm, preserveEmptyCaret)).fold(() => {
11859
11979
  if (moveCaret) {
11860
11980
  setSelection$1(editor, forward, normalizedAfterDeletePos);
11861
11981
  }
@@ -11975,24 +12095,44 @@
11975
12095
  }
11976
12096
  };
11977
12097
 
12098
+ const ancestor$1 = (scope, predicate, isRoot) => ancestor$4(scope, predicate, isRoot).isSome();
12099
+ const sibling = (scope, predicate) => sibling$1(scope, predicate).isSome();
12100
+ const descendant = (scope, predicate) => descendant$2(scope, predicate).isSome();
12101
+
11978
12102
  const isRootFromElement = root => cur => eq(root, cur);
11979
12103
  const getTableCells = table => descendants(table, 'td,th');
12104
+ const getTable$1 = (node, isRoot) => getClosestTable(SugarElement.fromDom(node), isRoot);
12105
+ const selectionInTableWithNestedTable = details => {
12106
+ return lift2(details.startTable, details.endTable, (startTable, endTable) => {
12107
+ const isStartTableParentOfEndTable = descendant(startTable, t => eq(t, endTable));
12108
+ const isEndTableParentOfStartTable = descendant(endTable, t => eq(t, startTable));
12109
+ return !isStartTableParentOfEndTable && !isEndTableParentOfStartTable ? details : {
12110
+ ...details,
12111
+ startTable: isStartTableParentOfEndTable ? Optional.none() : details.startTable,
12112
+ endTable: isEndTableParentOfStartTable ? Optional.none() : details.endTable,
12113
+ isSameTable: false,
12114
+ isMultiTable: false
12115
+ };
12116
+ }).getOr(details);
12117
+ };
12118
+ const adjustQuirksInDetails = details => {
12119
+ return selectionInTableWithNestedTable(details);
12120
+ };
11980
12121
  const getTableDetailsFromRange = (rng, isRoot) => {
11981
- const getTable = node => getClosestTable(SugarElement.fromDom(node), isRoot);
11982
- const startTable = getTable(rng.startContainer);
11983
- const endTable = getTable(rng.endContainer);
12122
+ const startTable = getTable$1(rng.startContainer, isRoot);
12123
+ const endTable = getTable$1(rng.endContainer, isRoot);
11984
12124
  const isStartInTable = startTable.isSome();
11985
12125
  const isEndInTable = endTable.isSome();
11986
12126
  const isSameTable = lift2(startTable, endTable, eq).getOr(false);
11987
12127
  const isMultiTable = !isSameTable && isStartInTable && isEndInTable;
11988
- return {
12128
+ return adjustQuirksInDetails({
11989
12129
  startTable,
11990
12130
  endTable,
11991
12131
  isStartInTable,
11992
12132
  isEndInTable,
11993
12133
  isSameTable,
11994
12134
  isMultiTable
11995
- };
12135
+ });
11996
12136
  };
11997
12137
 
11998
12138
  const tableCellRng = (start, end) => ({
@@ -12299,6 +12439,16 @@
12299
12439
  };
12300
12440
  };
12301
12441
 
12442
+ const isHeading = node => [
12443
+ 'h1',
12444
+ 'h2',
12445
+ 'h3',
12446
+ 'h4',
12447
+ 'h5',
12448
+ 'h6'
12449
+ ].includes(node.name);
12450
+ const isSummary = node => node.name === 'summary';
12451
+
12302
12452
  const traverse = (root, fn) => {
12303
12453
  let node = root;
12304
12454
  while (node = node.walk()) {
@@ -12464,7 +12614,7 @@
12464
12614
  parents.push(parent);
12465
12615
  }
12466
12616
  if (parent && parents.length > 1) {
12467
- if (schema.isValidChild(parent.name, node.name)) {
12617
+ if (!isInvalid(schema, node, parent)) {
12468
12618
  parents.reverse();
12469
12619
  newParent = parents[0].clone();
12470
12620
  onCreate(newParent);
@@ -12535,13 +12685,19 @@
12535
12685
  return false;
12536
12686
  };
12537
12687
  const isInvalid = (schema, node, parent = node.parent) => {
12538
- if (parent && schema.children[node.name] && !schema.isValidChild(parent.name, node.name)) {
12688
+ if (!parent) {
12689
+ return false;
12690
+ }
12691
+ if (schema.children[node.name] && !schema.isValidChild(parent.name, node.name)) {
12539
12692
  return true;
12540
- } else if (parent && node.name === 'a' && hasClosest(parent, 'a')) {
12693
+ }
12694
+ if (node.name === 'a' && hasClosest(parent, 'a')) {
12541
12695
  return true;
12542
- } else {
12543
- return false;
12544
12696
  }
12697
+ if (isSummary(parent) && isHeading(node)) {
12698
+ return !((parent === null || parent === void 0 ? void 0 : parent.firstChild) === node && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node);
12699
+ }
12700
+ return false;
12545
12701
  };
12546
12702
 
12547
12703
  const createRange = (sc, so, ec, eo) => {
@@ -12749,8 +12905,8 @@
12749
12905
  }
12750
12906
  }
12751
12907
  };
12752
- const trimBrsFromTableCell = (dom, elm) => {
12753
- Optional.from(dom.getParent(elm, 'td,th')).map(SugarElement.fromDom).each(trimBlockTrailingBr);
12908
+ const trimBrsFromTableCell = (dom, elm, schema) => {
12909
+ Optional.from(dom.getParent(elm, 'td,th')).map(SugarElement.fromDom).each(el => trimBlockTrailingBr(el, schema));
12754
12910
  };
12755
12911
  const reduceInlineTextElements = (editor, merge) => {
12756
12912
  const textInlineElements = editor.schema.getTextInlineElements();
@@ -12865,6 +13021,10 @@
12865
13021
  }
12866
13022
  return Optional.none();
12867
13023
  };
13024
+ const notHeadingsInSummary = (dom, node, fragment) => {
13025
+ var _a;
13026
+ return exists(fragment.children(), isHeading) && ((_a = dom.getParent(node, dom.isBlock)) === null || _a === void 0 ? void 0 : _a.nodeName) === 'SUMMARY';
13027
+ };
12868
13028
  const insertHtmlAtCaret = (editor, value, details) => {
12869
13029
  var _a, _b;
12870
13030
  const selection = editor.selection;
@@ -12873,6 +13033,9 @@
12873
13033
  const merge = details.merge;
12874
13034
  const serializer = HtmlSerializer({ validate: true }, editor.schema);
12875
13035
  const bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;</span>';
13036
+ if (!details.preserve_zwsp) {
13037
+ value = trim$2(value);
13038
+ }
12876
13039
  if (value.indexOf('{$caret}') === -1) {
12877
13040
  value += '{$caret}';
12878
13041
  }
@@ -12922,7 +13085,7 @@
12922
13085
  }
12923
13086
  }
12924
13087
  editor._selectionOverrides.showBlockCaretContainer(parentNode);
12925
- if (!parserArgs.invalid) {
13088
+ if (!parserArgs.invalid && !notHeadingsInSummary(dom, parentNode, fragment)) {
12926
13089
  value = serializer.serialize(fragment);
12927
13090
  validInsertion(editor, value, parentNode);
12928
13091
  } else {
@@ -12960,7 +13123,7 @@
12960
13123
  reduceInlineTextElements(editor, merge);
12961
13124
  moveSelectionToMarker(editor, dom.get('mce_marker'));
12962
13125
  unmarkFragmentElements(editor.getBody());
12963
- trimBrsFromTableCell(dom, selection.getStart());
13126
+ trimBrsFromTableCell(dom, selection.getStart(), editor.schema);
12964
13127
  updateCaret(editor.schema, editor.getBody(), selection.getStart());
12965
13128
  return value;
12966
13129
  };
@@ -12983,6 +13146,7 @@
12983
13146
  }
12984
13147
  };
12985
13148
  const setContentString = (editor, body, content, args) => {
13149
+ content = trim$2(content);
12986
13150
  if (content.length === 0 || /^\s+$/.test(content)) {
12987
13151
  const padd = '<br data-mce-bogus="1">';
12988
13152
  if (body.nodeName === 'TABLE') {
@@ -13020,7 +13184,7 @@
13020
13184
  const setContentTree = (editor, body, content, args) => {
13021
13185
  filter$2(editor.parser.getNodeFilters(), editor.parser.getAttributeFilters(), content);
13022
13186
  const html = HtmlSerializer({ validate: false }, editor.schema).serialize(content);
13023
- const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body)) ? html : Tools.trim(html);
13187
+ const trimmedHtml = trim$2(isWsPreserveElement(SugarElement.fromDom(body)) ? html : Tools.trim(html));
13024
13188
  setEditorHtml(editor, trimmedHtml, args.no_selection);
13025
13189
  return {
13026
13190
  content,
@@ -13040,9 +13204,6 @@
13040
13204
  });
13041
13205
  };
13042
13206
 
13043
- const ancestor$1 = (scope, predicate, isRoot) => ancestor$4(scope, predicate, isRoot).isSome();
13044
- const sibling = (scope, predicate) => sibling$1(scope, predicate).isSome();
13045
-
13046
13207
  const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
13047
13208
  const ancestor = (scope, transform, isRoot) => {
13048
13209
  let element = scope.dom;
@@ -13227,23 +13388,6 @@
13227
13388
  const importNode = (ownerDocument, node) => {
13228
13389
  return ownerDocument.importNode(node, true);
13229
13390
  };
13230
- const getEmptyCaretContainers = node => {
13231
- const nodes = [];
13232
- let tempNode = node;
13233
- while (tempNode) {
13234
- if (isText$a(tempNode) && tempNode.data !== ZWSP || tempNode.childNodes.length > 1) {
13235
- return [];
13236
- }
13237
- if (isElement$6(tempNode)) {
13238
- nodes.push(tempNode);
13239
- }
13240
- tempNode = tempNode.firstChild;
13241
- }
13242
- return nodes;
13243
- };
13244
- const isCaretContainerEmpty = node => {
13245
- return getEmptyCaretContainers(node).length > 0;
13246
- };
13247
13391
  const findFirstTextNode = node => {
13248
13392
  if (node) {
13249
13393
  const walker = new DomTreeWalker(node, node);
@@ -13274,10 +13418,10 @@
13274
13418
  }
13275
13419
  return textNode;
13276
13420
  };
13277
- const removeCaretContainerNode = (editor, node, moveCaret = true) => {
13421
+ const removeCaretContainerNode = (editor, node, moveCaret) => {
13278
13422
  const dom = editor.dom, selection = editor.selection;
13279
13423
  if (isCaretContainerEmpty(node)) {
13280
- deleteElement$2(editor, false, SugarElement.fromDom(node), moveCaret);
13424
+ deleteElement$2(editor, false, SugarElement.fromDom(node), moveCaret, true);
13281
13425
  } else {
13282
13426
  const rng = selection.getRng();
13283
13427
  const block = dom.getParent(node, dom.isBlock);
@@ -13299,7 +13443,7 @@
13299
13443
  selection.setRng(rng);
13300
13444
  }
13301
13445
  };
13302
- const removeCaretContainer = (editor, node, moveCaret = true) => {
13446
+ const removeCaretContainer = (editor, node, moveCaret) => {
13303
13447
  const dom = editor.dom, selection = editor.selection;
13304
13448
  if (!node) {
13305
13449
  node = getParentCaretContainer(editor.getBody(), selection.getStart());
@@ -13432,12 +13576,17 @@
13432
13576
  selection.moveToBookmark(bookmark);
13433
13577
  } else {
13434
13578
  const caretContainer = getParentCaretContainer(editor.getBody(), formatNode);
13579
+ const parentsAfter = isNonNullable(caretContainer) ? dom.getParents(formatNode.parentNode, always, caretContainer) : [];
13435
13580
  const newCaretContainer = createCaretContainer(false).dom;
13436
13581
  insertCaretContainerNode(editor, newCaretContainer, caretContainer !== null && caretContainer !== void 0 ? caretContainer : formatNode);
13437
13582
  const cleanedFormatNode = cleanFormatNode(editor, newCaretContainer, formatNode, name, vars, similar);
13438
- const caretTextNode = insertFormatNodesIntoCaretContainer(parents.concat(cleanedFormatNode.toArray()), newCaretContainer);
13583
+ const caretTextNode = insertFormatNodesIntoCaretContainer([
13584
+ ...parents,
13585
+ ...cleanedFormatNode.toArray(),
13586
+ ...parentsAfter
13587
+ ], newCaretContainer);
13439
13588
  if (caretContainer) {
13440
- removeCaretContainerNode(editor, caretContainer, false);
13589
+ removeCaretContainerNode(editor, caretContainer, isNonNullable(caretContainer));
13441
13590
  }
13442
13591
  selection.setCursorLocation(caretTextNode, 1);
13443
13592
  if (dom.isEmpty(formatNode)) {
@@ -13449,14 +13598,14 @@
13449
13598
  const selection = editor.selection, body = editor.getBody();
13450
13599
  removeCaretContainer(editor, null, moveCaret);
13451
13600
  if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP) {
13452
- removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
13601
+ removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
13453
13602
  }
13454
13603
  if (keyCode === 37 || keyCode === 39) {
13455
- removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()));
13604
+ removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
13456
13605
  }
13457
13606
  };
13458
13607
  const endsWithNbsp = element => isText$a(element) && endsWith(element.data, nbsp);
13459
- const setup$u = editor => {
13608
+ const setup$v = editor => {
13460
13609
  editor.on('mouseup keydown', e => {
13461
13610
  disableCaretContainer(editor, e.keyCode, endsWithNbsp(editor.selection.getRng().endContainer));
13462
13611
  });
@@ -13481,12 +13630,12 @@
13481
13630
  return caretPosition;
13482
13631
  };
13483
13632
  const isFormatElement = (editor, element) => {
13633
+ if (isCaretNode(element.dom)) {
13634
+ return false;
13635
+ }
13484
13636
  const inlineElements = editor.schema.getTextInlineElements();
13485
13637
  return has$2(inlineElements, name(element)) && !isCaretNode(element.dom) && !isBogus$2(element.dom);
13486
13638
  };
13487
- const isEmptyCaretFormatElement = element => {
13488
- return isCaretNode(element.dom) && isCaretContainerEmpty(element.dom);
13489
- };
13490
13639
 
13491
13640
  const postProcessHooks = {};
13492
13641
  const isPre = matchNodeNames(['pre']);
@@ -13580,8 +13729,8 @@
13580
13729
  };
13581
13730
  const mergeSiblingsNodes = (editor, prev, next) => {
13582
13731
  const elementUtils = ElementUtils(editor);
13583
- const isPrevEditable = isElement$6(prev) && isEditable$2(prev);
13584
- const isNextEditable = isElement$6(next) && isEditable$2(next);
13732
+ const isPrevEditable = isHTMLElement(prev) && editor.dom.isEditable(prev);
13733
+ const isNextEditable = isHTMLElement(next) && editor.dom.isEditable(next);
13585
13734
  if (isPrevEditable && isNextEditable) {
13586
13735
  const prevSibling = findElementSibling(prev, 'previousSibling');
13587
13736
  const nextSibling = findElementSibling(next, 'nextSibling');
@@ -13611,7 +13760,7 @@
13611
13760
  if (format.clear_child_styles) {
13612
13761
  const selector = format.links ? '*:not(a)' : '*';
13613
13762
  each$8(dom.select(selector, node), childNode => {
13614
- if (isElementNode(childNode) && isEditable$2(childNode)) {
13763
+ if (isElementNode(childNode) && dom.isEditable(childNode)) {
13615
13764
  each$8(format.styles, (_value, name) => {
13616
13765
  dom.setStyle(childNode, name, '');
13617
13766
  });
@@ -14078,7 +14227,7 @@
14078
14227
  const each$6 = Tools.each;
14079
14228
  const mergeTextDecorationsAndColor = (dom, format, vars, node) => {
14080
14229
  const processTextDecorationsAndColor = n => {
14081
- if (isElement$6(n) && isElement$6(n.parentNode) && isEditable$2(n)) {
14230
+ if (isHTMLElement(n) && isElement$6(n.parentNode) && dom.isEditable(n)) {
14082
14231
  const parentTextDecoration = getTextDecoration(dom, n.parentNode);
14083
14232
  if (dom.getStyle(n, 'color') && parentTextDecoration) {
14084
14233
  dom.setStyle(n, 'text-decoration', parentTextDecoration);
@@ -14095,14 +14244,14 @@
14095
14244
  const mergeBackgroundColorAndFontSize = (dom, format, vars, node) => {
14096
14245
  if (format.styles && format.styles.backgroundColor) {
14097
14246
  const hasFontSize = hasStyle(dom, 'fontSize');
14098
- processChildElements(node, elm => hasFontSize(elm) && isEditable$2(elm), applyStyle(dom, 'backgroundColor', replaceVars(format.styles.backgroundColor, vars)));
14247
+ processChildElements(node, elm => hasFontSize(elm) && dom.isEditable(elm), applyStyle(dom, 'backgroundColor', replaceVars(format.styles.backgroundColor, vars)));
14099
14248
  }
14100
14249
  };
14101
14250
  const mergeSubSup = (dom, format, vars, node) => {
14102
14251
  if (isInlineFormat(format) && (format.inline === 'sub' || format.inline === 'sup')) {
14103
14252
  const hasFontSize = hasStyle(dom, 'fontSize');
14104
- processChildElements(node, elm => hasFontSize(elm) && isEditable$2(elm), applyStyle(dom, 'fontSize', ''));
14105
- const inverseTagDescendants = filter$5(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), isEditable$2);
14253
+ processChildElements(node, elm => hasFontSize(elm) && dom.isEditable(elm), applyStyle(dom, 'fontSize', ''));
14254
+ const inverseTagDescendants = filter$5(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), dom.isEditable);
14106
14255
  dom.remove(inverseTagDescendants, true);
14107
14256
  }
14108
14257
  };
@@ -14388,7 +14537,7 @@
14388
14537
  };
14389
14538
 
14390
14539
  const hasVars = value => has$2(value, 'vars');
14391
- const setup$t = (registeredFormatListeners, editor) => {
14540
+ const setup$u = (registeredFormatListeners, editor) => {
14392
14541
  registeredFormatListeners.set({});
14393
14542
  editor.on('NodeChange', e => {
14394
14543
  updateAndFireChangeCallbacks(editor, e.element, registeredFormatListeners.get());
@@ -14809,6 +14958,34 @@
14809
14958
  parser.addAttributeFilter('src', nodes => each$e(nodes, processImage));
14810
14959
  }
14811
14960
  };
14961
+ const isMimeType = (mime, type) => startsWith(mime, `${ type }/`);
14962
+ const createSafeEmbed = (mime, src, width, height, sandboxIframes) => {
14963
+ let name;
14964
+ if (isUndefined(mime)) {
14965
+ name = 'iframe';
14966
+ } else if (isMimeType(mime, 'image')) {
14967
+ name = 'img';
14968
+ } else if (isMimeType(mime, 'video')) {
14969
+ name = 'video';
14970
+ } else if (isMimeType(mime, 'audio')) {
14971
+ name = 'audio';
14972
+ } else {
14973
+ name = 'iframe';
14974
+ }
14975
+ const embed = new AstNode(name, 1);
14976
+ embed.attr(name === 'audio' ? { src } : {
14977
+ src,
14978
+ width,
14979
+ height
14980
+ });
14981
+ if (name === 'audio' || name === 'video') {
14982
+ embed.attr('controls', '');
14983
+ }
14984
+ if (name === 'iframe' && sandboxIframes) {
14985
+ embed.attr('sandbox', '');
14986
+ }
14987
+ return embed;
14988
+ };
14812
14989
  const register$4 = (parser, settings) => {
14813
14990
  const schema = parser.schema;
14814
14991
  if (settings.remove_trailing_brs) {
@@ -14908,91 +15085,19 @@
14908
15085
  });
14909
15086
  }
14910
15087
  registerBase64ImageFilter(parser, settings);
14911
- };
14912
-
14913
- function _typeof(obj) {
14914
- '@babel/helpers - typeof';
14915
- return _typeof = 'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator ? function (obj) {
14916
- return typeof obj;
14917
- } : function (obj) {
14918
- return obj && 'function' == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj;
14919
- }, _typeof(obj);
14920
- }
14921
- function _setPrototypeOf(o, p) {
14922
- _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
14923
- o.__proto__ = p;
14924
- return o;
14925
- };
14926
- return _setPrototypeOf(o, p);
14927
- }
14928
- function _isNativeReflectConstruct() {
14929
- if (typeof Reflect === 'undefined' || !Reflect.construct)
14930
- return false;
14931
- if (Reflect.construct.sham)
14932
- return false;
14933
- if (typeof Proxy === 'function')
14934
- return true;
14935
- try {
14936
- Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {
15088
+ if (settings.convert_unsafe_embeds) {
15089
+ parser.addNodeFilter('object,embed', nodes => each$e(nodes, node => {
15090
+ node.replace(createSafeEmbed(node.attr('type'), node.name === 'object' ? node.attr('data') : node.attr('src'), node.attr('width'), node.attr('height'), settings.sandbox_iframes));
14937
15091
  }));
14938
- return true;
14939
- } catch (e) {
14940
- return false;
14941
15092
  }
14942
- }
14943
- function _construct(Parent, args, Class) {
14944
- if (_isNativeReflectConstruct()) {
14945
- _construct = Reflect.construct;
14946
- } else {
14947
- _construct = function _construct(Parent, args, Class) {
14948
- var a = [null];
14949
- a.push.apply(a, args);
14950
- var Constructor = Function.bind.apply(Parent, a);
14951
- var instance = new Constructor();
14952
- if (Class)
14953
- _setPrototypeOf(instance, Class.prototype);
14954
- return instance;
14955
- };
15093
+ if (settings.sandbox_iframes) {
15094
+ parser.addNodeFilter('iframe', nodes => each$e(nodes, node => node.attr('sandbox', '')));
14956
15095
  }
14957
- return _construct.apply(null, arguments);
14958
- }
14959
- function _toConsumableArray(arr) {
14960
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
14961
- }
14962
- function _arrayWithoutHoles(arr) {
14963
- if (Array.isArray(arr))
14964
- return _arrayLikeToArray(arr);
14965
- }
14966
- function _iterableToArray(iter) {
14967
- if (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null || iter['@@iterator'] != null)
14968
- return Array.from(iter);
14969
- }
14970
- function _unsupportedIterableToArray(o, minLen) {
14971
- if (!o)
14972
- return;
14973
- if (typeof o === 'string')
14974
- return _arrayLikeToArray(o, minLen);
14975
- var n = Object.prototype.toString.call(o).slice(8, -1);
14976
- if (n === 'Object' && o.constructor)
14977
- n = o.constructor.name;
14978
- if (n === 'Map' || n === 'Set')
14979
- return Array.from(o);
14980
- if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
14981
- return _arrayLikeToArray(o, minLen);
14982
- }
14983
- function _arrayLikeToArray(arr, len) {
14984
- if (len == null || len > arr.length)
14985
- len = arr.length;
14986
- for (var i = 0, arr2 = new Array(len); i < len; i++)
14987
- arr2[i] = arr[i];
14988
- return arr2;
14989
- }
14990
- function _nonIterableSpread() {
14991
- throw new TypeError('Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.');
14992
- }
14993
- var hasOwnProperty = Object.hasOwnProperty, setPrototypeOf = Object.setPrototypeOf, isFrozen = Object.isFrozen, getPrototypeOf = Object.getPrototypeOf, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
14994
- var freeze = Object.freeze, seal = Object.seal, create$7 = Object.create;
14995
- var _ref = typeof Reflect !== 'undefined' && Reflect, apply = _ref.apply, construct = _ref.construct;
15096
+ };
15097
+
15098
+ const {entries, setPrototypeOf, isFrozen, getPrototypeOf, getOwnPropertyDescriptor} = Object;
15099
+ let {freeze, seal, create: create$7} = Object;
15100
+ let {apply, construct} = typeof Reflect !== 'undefined' && Reflect;
14996
15101
  if (!apply) {
14997
15102
  apply = function apply(fun, thisValue, args) {
14998
15103
  return fun.apply(thisValue, args);
@@ -15010,19 +15115,20 @@
15010
15115
  }
15011
15116
  if (!construct) {
15012
15117
  construct = function construct(Func, args) {
15013
- return _construct(Func, _toConsumableArray(args));
15118
+ return new Func(...args);
15014
15119
  };
15015
15120
  }
15016
- var arrayForEach = unapply(Array.prototype.forEach);
15017
- var arrayPop = unapply(Array.prototype.pop);
15018
- var arrayPush = unapply(Array.prototype.push);
15019
- var stringToLowerCase = unapply(String.prototype.toLowerCase);
15020
- var stringMatch = unapply(String.prototype.match);
15021
- var stringReplace = unapply(String.prototype.replace);
15022
- var stringIndexOf = unapply(String.prototype.indexOf);
15023
- var stringTrim = unapply(String.prototype.trim);
15024
- var regExpTest = unapply(RegExp.prototype.test);
15025
- var typeErrorCreate = unconstruct(TypeError);
15121
+ const arrayForEach = unapply(Array.prototype.forEach);
15122
+ const arrayPop = unapply(Array.prototype.pop);
15123
+ const arrayPush = unapply(Array.prototype.push);
15124
+ const stringToLowerCase = unapply(String.prototype.toLowerCase);
15125
+ const stringToString = unapply(String.prototype.toString);
15126
+ const stringMatch = unapply(String.prototype.match);
15127
+ const stringReplace = unapply(String.prototype.replace);
15128
+ const stringIndexOf = unapply(String.prototype.indexOf);
15129
+ const stringTrim = unapply(String.prototype.trim);
15130
+ const regExpTest = unapply(RegExp.prototype.test);
15131
+ const typeErrorCreate = unconstruct(TypeError);
15026
15132
  function unapply(func) {
15027
15133
  return function (thisArg) {
15028
15134
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
@@ -15039,15 +15145,17 @@
15039
15145
  return construct(func, args);
15040
15146
  };
15041
15147
  }
15042
- function addToSet(set, array) {
15148
+ function addToSet(set, array, transformCaseFunc) {
15149
+ var _transformCaseFunc;
15150
+ transformCaseFunc = (_transformCaseFunc = transformCaseFunc) !== null && _transformCaseFunc !== void 0 ? _transformCaseFunc : stringToLowerCase;
15043
15151
  if (setPrototypeOf) {
15044
15152
  setPrototypeOf(set, null);
15045
15153
  }
15046
- var l = array.length;
15154
+ let l = array.length;
15047
15155
  while (l--) {
15048
- var element = array[l];
15156
+ let element = array[l];
15049
15157
  if (typeof element === 'string') {
15050
- var lcElement = stringToLowerCase(element);
15158
+ const lcElement = transformCaseFunc(element);
15051
15159
  if (lcElement !== element) {
15052
15160
  if (!isFrozen(array)) {
15053
15161
  array[l] = lcElement;
@@ -15060,18 +15168,15 @@
15060
15168
  return set;
15061
15169
  }
15062
15170
  function clone(object) {
15063
- var newObject = create$7(null);
15064
- var property;
15065
- for (property in object) {
15066
- if (apply(hasOwnProperty, object, [property])) {
15067
- newObject[property] = object[property];
15068
- }
15171
+ const newObject = create$7(null);
15172
+ for (const [property, value] of entries(object)) {
15173
+ newObject[property] = value;
15069
15174
  }
15070
15175
  return newObject;
15071
15176
  }
15072
15177
  function lookupGetter(object, prop) {
15073
15178
  while (object !== null) {
15074
- var desc = getOwnPropertyDescriptor(object, prop);
15179
+ const desc = getOwnPropertyDescriptor(object, prop);
15075
15180
  if (desc) {
15076
15181
  if (desc.get) {
15077
15182
  return unapply(desc.get);
@@ -15088,7 +15193,7 @@
15088
15193
  }
15089
15194
  return fallbackValue;
15090
15195
  }
15091
- var html$1 = freeze([
15196
+ const html$1 = freeze([
15092
15197
  'a',
15093
15198
  'abbr',
15094
15199
  'acronym',
@@ -15207,7 +15312,7 @@
15207
15312
  'video',
15208
15313
  'wbr'
15209
15314
  ]);
15210
- var svg$1 = freeze([
15315
+ const svg$1 = freeze([
15211
15316
  'svg',
15212
15317
  'a',
15213
15318
  'altglyph',
@@ -15252,7 +15357,7 @@
15252
15357
  'view',
15253
15358
  'vkern'
15254
15359
  ]);
15255
- var svgFilters = freeze([
15360
+ const svgFilters = freeze([
15256
15361
  'feBlend',
15257
15362
  'feColorMatrix',
15258
15363
  'feComponentTransfer',
@@ -15261,6 +15366,7 @@
15261
15366
  'feDiffuseLighting',
15262
15367
  'feDisplacementMap',
15263
15368
  'feDistantLight',
15369
+ 'feDropShadow',
15264
15370
  'feFlood',
15265
15371
  'feFuncA',
15266
15372
  'feFuncB',
@@ -15278,12 +15384,11 @@
15278
15384
  'feTile',
15279
15385
  'feTurbulence'
15280
15386
  ]);
15281
- var svgDisallowed = freeze([
15387
+ const svgDisallowed = freeze([
15282
15388
  'animate',
15283
15389
  'color-profile',
15284
15390
  'cursor',
15285
15391
  'discard',
15286
- 'fedropshadow',
15287
15392
  'font-face',
15288
15393
  'font-face-format',
15289
15394
  'font-face-name',
@@ -15303,7 +15408,7 @@
15303
15408
  'unknown',
15304
15409
  'use'
15305
15410
  ]);
15306
- var mathMl$1 = freeze([
15411
+ const mathMl$1 = freeze([
15307
15412
  'math',
15308
15413
  'menclose',
15309
15414
  'merror',
@@ -15332,9 +15437,10 @@
15332
15437
  'mtext',
15333
15438
  'mtr',
15334
15439
  'munder',
15335
- 'munderover'
15440
+ 'munderover',
15441
+ 'mprescripts'
15336
15442
  ]);
15337
- var mathMlDisallowed = freeze([
15443
+ const mathMlDisallowed = freeze([
15338
15444
  'maction',
15339
15445
  'maligngroup',
15340
15446
  'malignmark',
@@ -15351,8 +15457,8 @@
15351
15457
  'mprescripts',
15352
15458
  'none'
15353
15459
  ]);
15354
- var text = freeze(['#text']);
15355
- var html = freeze([
15460
+ const text = freeze(['#text']);
15461
+ const html = freeze([
15356
15462
  'accept',
15357
15463
  'action',
15358
15464
  'align',
@@ -15463,7 +15569,7 @@
15463
15569
  'xmlns',
15464
15570
  'slot'
15465
15571
  ]);
15466
- var svg = freeze([
15572
+ const svg = freeze([
15467
15573
  'accent-height',
15468
15574
  'accumulate',
15469
15575
  'additive',
@@ -15647,7 +15753,7 @@
15647
15753
  'z',
15648
15754
  'zoomandpan'
15649
15755
  ]);
15650
- var mathMl = freeze([
15756
+ const mathMl = freeze([
15651
15757
  'accent',
15652
15758
  'accentunder',
15653
15759
  'align',
@@ -15702,38 +15808,52 @@
15702
15808
  'width',
15703
15809
  'xmlns'
15704
15810
  ]);
15705
- var xml = freeze([
15811
+ const xml = freeze([
15706
15812
  'xlink:href',
15707
15813
  'xml:id',
15708
15814
  'xlink:title',
15709
15815
  'xml:space',
15710
15816
  'xmlns:xlink'
15711
15817
  ]);
15712
- var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
15713
- var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
15714
- var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
15715
- var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
15716
- var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
15717
- var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
15718
- var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
15719
- var DOCTYPE_NAME = seal(/^html$/i);
15720
- var getGlobal = function getGlobal() {
15721
- return typeof window === 'undefined' ? null : window;
15722
- };
15723
- var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
15724
- if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
15818
+ const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
15819
+ const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
15820
+ const TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
15821
+ const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
15822
+ const ARIA_ATTR = seal(/^aria-[\-\w]+$/);
15823
+ const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
15824
+ const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
15825
+ const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
15826
+ const DOCTYPE_NAME = seal(/^html$/i);
15827
+ var EXPRESSIONS = Object.freeze({
15828
+ __proto__: null,
15829
+ MUSTACHE_EXPR: MUSTACHE_EXPR,
15830
+ ERB_EXPR: ERB_EXPR,
15831
+ TMPLIT_EXPR: TMPLIT_EXPR,
15832
+ DATA_ATTR: DATA_ATTR,
15833
+ ARIA_ATTR: ARIA_ATTR,
15834
+ IS_ALLOWED_URI: IS_ALLOWED_URI,
15835
+ IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
15836
+ ATTR_WHITESPACE: ATTR_WHITESPACE,
15837
+ DOCTYPE_NAME: DOCTYPE_NAME
15838
+ });
15839
+ const getGlobal = () => typeof window === 'undefined' ? null : window;
15840
+ const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {
15841
+ if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
15725
15842
  return null;
15726
15843
  }
15727
- var suffix = null;
15728
- var ATTR_NAME = 'data-tt-policy-suffix';
15729
- if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
15730
- suffix = document.currentScript.getAttribute(ATTR_NAME);
15844
+ let suffix = null;
15845
+ const ATTR_NAME = 'data-tt-policy-suffix';
15846
+ if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
15847
+ suffix = purifyHostElement.getAttribute(ATTR_NAME);
15731
15848
  }
15732
- var policyName = 'dompurify' + (suffix ? '#' + suffix : '');
15849
+ const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
15733
15850
  try {
15734
15851
  return trustedTypes.createPolicy(policyName, {
15735
- createHTML: function createHTML(html) {
15852
+ createHTML(html) {
15736
15853
  return html;
15854
+ },
15855
+ createScriptURL(scriptUrl) {
15856
+ return scriptUrl;
15737
15857
  }
15738
15858
  });
15739
15859
  } catch (_) {
@@ -15742,48 +15862,53 @@
15742
15862
  }
15743
15863
  };
15744
15864
  function createDOMPurify() {
15745
- var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
15746
- var DOMPurify = function DOMPurify(root) {
15747
- return createDOMPurify(root);
15748
- };
15749
- DOMPurify.version = '2.3.8';
15865
+ let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
15866
+ const DOMPurify = root => createDOMPurify(root);
15867
+ DOMPurify.version = '3.0.5';
15750
15868
  DOMPurify.removed = [];
15751
15869
  if (!window || !window.document || window.document.nodeType !== 9) {
15752
15870
  DOMPurify.isSupported = false;
15753
15871
  return DOMPurify;
15754
15872
  }
15755
- var originalDocument = window.document;
15756
- var document = window.document;
15757
- var DocumentFragment = window.DocumentFragment, HTMLTemplateElement = window.HTMLTemplateElement, Node = window.Node, Element = window.Element, NodeFilter = window.NodeFilter, _window$NamedNodeMap = window.NamedNodeMap, NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap, HTMLFormElement = window.HTMLFormElement, DOMParser = window.DOMParser, trustedTypes = window.trustedTypes;
15758
- var ElementPrototype = Element.prototype;
15759
- var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
15760
- var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
15761
- var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
15762
- var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
15873
+ const originalDocument = window.document;
15874
+ const currentScript = originalDocument.currentScript;
15875
+ let {document} = window;
15876
+ const {DocumentFragment, HTMLTemplateElement, Node, Element, NodeFilter, NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap, HTMLFormElement, DOMParser, trustedTypes} = window;
15877
+ const ElementPrototype = Element.prototype;
15878
+ const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
15879
+ const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
15880
+ const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
15881
+ const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
15763
15882
  if (typeof HTMLTemplateElement === 'function') {
15764
- var template = document.createElement('template');
15883
+ const template = document.createElement('template');
15765
15884
  if (template.content && template.content.ownerDocument) {
15766
15885
  document = template.content.ownerDocument;
15767
15886
  }
15768
15887
  }
15769
- var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);
15770
- var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML('') : '';
15771
- var _document = document, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
15772
- var importNode = originalDocument.importNode;
15773
- var documentMode = {};
15774
- try {
15775
- documentMode = clone(document).documentMode ? document.documentMode : {};
15776
- } catch (_) {
15777
- }
15778
- var hooks = {};
15779
- DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
15780
- var MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE;
15781
- var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
15782
- var ALLOWED_TAGS = null;
15783
- var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
15784
- var ALLOWED_ATTR = null;
15785
- var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
15786
- var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
15888
+ let trustedTypesPolicy;
15889
+ let emptyHTML = '';
15890
+ const {implementation, createNodeIterator, createDocumentFragment, getElementsByTagName} = document;
15891
+ const {importNode} = originalDocument;
15892
+ let hooks = {};
15893
+ DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
15894
+ const {MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR, DATA_ATTR, ARIA_ATTR, IS_SCRIPT_OR_DATA, ATTR_WHITESPACE} = EXPRESSIONS;
15895
+ let {IS_ALLOWED_URI: IS_ALLOWED_URI$1} = EXPRESSIONS;
15896
+ let ALLOWED_TAGS = null;
15897
+ const DEFAULT_ALLOWED_TAGS = addToSet({}, [
15898
+ ...html$1,
15899
+ ...svg$1,
15900
+ ...svgFilters,
15901
+ ...mathMl$1,
15902
+ ...text
15903
+ ]);
15904
+ let ALLOWED_ATTR = null;
15905
+ const DEFAULT_ALLOWED_ATTR = addToSet({}, [
15906
+ ...html,
15907
+ ...svg,
15908
+ ...mathMl,
15909
+ ...xml
15910
+ ]);
15911
+ let CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
15787
15912
  tagNameCheck: {
15788
15913
  writable: true,
15789
15914
  configurable: false,
@@ -15803,24 +15928,27 @@
15803
15928
  value: false
15804
15929
  }
15805
15930
  }));
15806
- var FORBID_TAGS = null;
15807
- var FORBID_ATTR = null;
15808
- var ALLOW_ARIA_ATTR = true;
15809
- var ALLOW_DATA_ATTR = true;
15810
- var ALLOW_UNKNOWN_PROTOCOLS = false;
15811
- var SAFE_FOR_TEMPLATES = false;
15812
- var WHOLE_DOCUMENT = false;
15813
- var SET_CONFIG = false;
15814
- var FORCE_BODY = false;
15815
- var RETURN_DOM = false;
15816
- var RETURN_DOM_FRAGMENT = false;
15817
- var RETURN_TRUSTED_TYPE = false;
15818
- var SANITIZE_DOM = true;
15819
- var KEEP_CONTENT = true;
15820
- var IN_PLACE = false;
15821
- var USE_PROFILES = {};
15822
- var FORBID_CONTENTS = null;
15823
- var DEFAULT_FORBID_CONTENTS = addToSet({}, [
15931
+ let FORBID_TAGS = null;
15932
+ let FORBID_ATTR = null;
15933
+ let ALLOW_ARIA_ATTR = true;
15934
+ let ALLOW_DATA_ATTR = true;
15935
+ let ALLOW_UNKNOWN_PROTOCOLS = false;
15936
+ let ALLOW_SELF_CLOSE_IN_ATTR = true;
15937
+ let SAFE_FOR_TEMPLATES = false;
15938
+ let WHOLE_DOCUMENT = false;
15939
+ let SET_CONFIG = false;
15940
+ let FORCE_BODY = false;
15941
+ let RETURN_DOM = false;
15942
+ let RETURN_DOM_FRAGMENT = false;
15943
+ let RETURN_TRUSTED_TYPE = false;
15944
+ let SANITIZE_DOM = true;
15945
+ let SANITIZE_NAMED_PROPS = false;
15946
+ const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
15947
+ let KEEP_CONTENT = true;
15948
+ let IN_PLACE = false;
15949
+ let USE_PROFILES = {};
15950
+ let FORBID_CONTENTS = null;
15951
+ const DEFAULT_FORBID_CONTENTS = addToSet({}, [
15824
15952
  'annotation-xml',
15825
15953
  'audio',
15826
15954
  'colgroup',
@@ -15847,8 +15975,8 @@
15847
15975
  'video',
15848
15976
  'xmp'
15849
15977
  ]);
15850
- var DATA_URI_TAGS = null;
15851
- var DEFAULT_DATA_URI_TAGS = addToSet({}, [
15978
+ let DATA_URI_TAGS = null;
15979
+ const DEFAULT_DATA_URI_TAGS = addToSet({}, [
15852
15980
  'audio',
15853
15981
  'video',
15854
15982
  'img',
@@ -15856,8 +15984,8 @@
15856
15984
  'image',
15857
15985
  'track'
15858
15986
  ]);
15859
- var URI_SAFE_ATTRIBUTES = null;
15860
- var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
15987
+ let URI_SAFE_ATTRIBUTES = null;
15988
+ const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
15861
15989
  'alt',
15862
15990
  'class',
15863
15991
  'for',
@@ -15873,42 +16001,52 @@
15873
16001
  'style',
15874
16002
  'xmlns'
15875
16003
  ]);
15876
- var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
15877
- var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
15878
- var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
15879
- var NAMESPACE = HTML_NAMESPACE;
15880
- var IS_EMPTY_INPUT = false;
15881
- var PARSER_MEDIA_TYPE;
15882
- var SUPPORTED_PARSER_MEDIA_TYPES = [
16004
+ const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
16005
+ const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
16006
+ const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
16007
+ let NAMESPACE = HTML_NAMESPACE;
16008
+ let IS_EMPTY_INPUT = false;
16009
+ let ALLOWED_NAMESPACES = null;
16010
+ const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [
16011
+ MATHML_NAMESPACE,
16012
+ SVG_NAMESPACE,
16013
+ HTML_NAMESPACE
16014
+ ], stringToString);
16015
+ let PARSER_MEDIA_TYPE;
16016
+ const SUPPORTED_PARSER_MEDIA_TYPES = [
15883
16017
  'application/xhtml+xml',
15884
16018
  'text/html'
15885
16019
  ];
15886
- var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
15887
- var transformCaseFunc;
15888
- var CONFIG = null;
15889
- var formElement = document.createElement('form');
15890
- var isRegexOrFunction = function isRegexOrFunction(testValue) {
16020
+ const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
16021
+ let transformCaseFunc;
16022
+ let CONFIG = null;
16023
+ const formElement = document.createElement('form');
16024
+ const isRegexOrFunction = function isRegexOrFunction(testValue) {
15891
16025
  return testValue instanceof RegExp || testValue instanceof Function;
15892
16026
  };
15893
- var _parseConfig = function _parseConfig(cfg) {
16027
+ const _parseConfig = function _parseConfig(cfg) {
15894
16028
  if (CONFIG && CONFIG === cfg) {
15895
16029
  return;
15896
16030
  }
15897
- if (!cfg || _typeof(cfg) !== 'object') {
16031
+ if (!cfg || typeof cfg !== 'object') {
15898
16032
  cfg = {};
15899
16033
  }
15900
16034
  cfg = clone(cfg);
15901
- ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
15902
- ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
15903
- URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;
15904
- DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;
15905
- FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS) : DEFAULT_FORBID_CONTENTS;
15906
- FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
15907
- FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
16035
+ PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
16036
+ transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
16037
+ ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
16038
+ ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
16039
+ ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
16040
+ URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
16041
+ DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
16042
+ FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
16043
+ FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
16044
+ FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
15908
16045
  USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
15909
16046
  ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
15910
16047
  ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
15911
16048
  ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
16049
+ ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
15912
16050
  SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
15913
16051
  WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
15914
16052
  RETURN_DOM = cfg.RETURN_DOM || false;
@@ -15916,10 +16054,12 @@
15916
16054
  RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
15917
16055
  FORCE_BODY = cfg.FORCE_BODY || false;
15918
16056
  SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
16057
+ SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
15919
16058
  KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
15920
16059
  IN_PLACE = cfg.IN_PLACE || false;
15921
- IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
16060
+ IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
15922
16061
  NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
16062
+ CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
15923
16063
  if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
15924
16064
  CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
15925
16065
  }
@@ -15929,10 +16069,6 @@
15929
16069
  if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
15930
16070
  CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
15931
16071
  }
15932
- PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
15933
- transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? function (x) {
15934
- return x;
15935
- } : stringToLowerCase;
15936
16072
  if (SAFE_FOR_TEMPLATES) {
15937
16073
  ALLOW_DATA_ATTR = false;
15938
16074
  }
@@ -15940,7 +16076,7 @@
15940
16076
  RETURN_DOM = true;
15941
16077
  }
15942
16078
  if (USE_PROFILES) {
15943
- ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
16079
+ ALLOWED_TAGS = addToSet({}, [...text]);
15944
16080
  ALLOWED_ATTR = [];
15945
16081
  if (USE_PROFILES.html === true) {
15946
16082
  addToSet(ALLOWED_TAGS, html$1);
@@ -15966,22 +16102,22 @@
15966
16102
  if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
15967
16103
  ALLOWED_TAGS = clone(ALLOWED_TAGS);
15968
16104
  }
15969
- addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
16105
+ addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
15970
16106
  }
15971
16107
  if (cfg.ADD_ATTR) {
15972
16108
  if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
15973
16109
  ALLOWED_ATTR = clone(ALLOWED_ATTR);
15974
16110
  }
15975
- addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
16111
+ addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
15976
16112
  }
15977
16113
  if (cfg.ADD_URI_SAFE_ATTR) {
15978
- addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
16114
+ addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
15979
16115
  }
15980
16116
  if (cfg.FORBID_CONTENTS) {
15981
16117
  if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
15982
16118
  FORBID_CONTENTS = clone(FORBID_CONTENTS);
15983
16119
  }
15984
- addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
16120
+ addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
15985
16121
  }
15986
16122
  if (KEEP_CONTENT) {
15987
16123
  ALLOWED_TAGS['#text'] = true;
@@ -15997,46 +16133,66 @@
15997
16133
  addToSet(ALLOWED_TAGS, ['tbody']);
15998
16134
  delete FORBID_TAGS.tbody;
15999
16135
  }
16136
+ if (cfg.TRUSTED_TYPES_POLICY) {
16137
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {
16138
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
16139
+ }
16140
+ if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {
16141
+ throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
16142
+ }
16143
+ trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
16144
+ emptyHTML = trustedTypesPolicy.createHTML('');
16145
+ } else {
16146
+ if (trustedTypesPolicy === undefined) {
16147
+ trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
16148
+ }
16149
+ if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
16150
+ emptyHTML = trustedTypesPolicy.createHTML('');
16151
+ }
16152
+ }
16000
16153
  if (freeze) {
16001
16154
  freeze(cfg);
16002
16155
  }
16003
16156
  CONFIG = cfg;
16004
16157
  };
16005
- var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
16158
+ const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
16006
16159
  'mi',
16007
16160
  'mo',
16008
16161
  'mn',
16009
16162
  'ms',
16010
16163
  'mtext'
16011
16164
  ]);
16012
- var HTML_INTEGRATION_POINTS = addToSet({}, [
16165
+ const HTML_INTEGRATION_POINTS = addToSet({}, [
16013
16166
  'foreignobject',
16014
16167
  'desc',
16015
16168
  'title',
16016
16169
  'annotation-xml'
16017
16170
  ]);
16018
- var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
16171
+ const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
16019
16172
  'title',
16020
16173
  'style',
16021
16174
  'font',
16022
16175
  'a',
16023
16176
  'script'
16024
16177
  ]);
16025
- var ALL_SVG_TAGS = addToSet({}, svg$1);
16178
+ const ALL_SVG_TAGS = addToSet({}, svg$1);
16026
16179
  addToSet(ALL_SVG_TAGS, svgFilters);
16027
16180
  addToSet(ALL_SVG_TAGS, svgDisallowed);
16028
- var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
16181
+ const ALL_MATHML_TAGS = addToSet({}, mathMl$1);
16029
16182
  addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
16030
- var _checkValidNamespace = function _checkValidNamespace(element) {
16031
- var parent = getParentNode(element);
16183
+ const _checkValidNamespace = function _checkValidNamespace(element) {
16184
+ let parent = getParentNode(element);
16032
16185
  if (!parent || !parent.tagName) {
16033
16186
  parent = {
16034
- namespaceURI: HTML_NAMESPACE,
16187
+ namespaceURI: NAMESPACE,
16035
16188
  tagName: 'template'
16036
16189
  };
16037
16190
  }
16038
- var tagName = stringToLowerCase(element.tagName);
16039
- var parentTagName = stringToLowerCase(parent.tagName);
16191
+ const tagName = stringToLowerCase(element.tagName);
16192
+ const parentTagName = stringToLowerCase(parent.tagName);
16193
+ if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
16194
+ return false;
16195
+ }
16040
16196
  if (element.namespaceURI === SVG_NAMESPACE) {
16041
16197
  if (parent.namespaceURI === HTML_NAMESPACE) {
16042
16198
  return tagName === 'svg';
@@ -16064,21 +16220,20 @@
16064
16220
  }
16065
16221
  return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
16066
16222
  }
16223
+ if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
16224
+ return true;
16225
+ }
16067
16226
  return false;
16068
16227
  };
16069
- var _forceRemove = function _forceRemove(node) {
16228
+ const _forceRemove = function _forceRemove(node) {
16070
16229
  arrayPush(DOMPurify.removed, { element: node });
16071
16230
  try {
16072
16231
  node.parentNode.removeChild(node);
16073
16232
  } catch (_) {
16074
- try {
16075
- node.outerHTML = emptyHTML;
16076
- } catch (_) {
16077
- node.remove();
16078
- }
16233
+ node.remove();
16079
16234
  }
16080
16235
  };
16081
- var _removeAttribute = function _removeAttribute(name, node) {
16236
+ const _removeAttribute = function _removeAttribute(name, node) {
16082
16237
  try {
16083
16238
  arrayPush(DOMPurify.removed, {
16084
16239
  attribute: node.getAttributeNode(name),
@@ -16105,19 +16260,19 @@
16105
16260
  }
16106
16261
  }
16107
16262
  };
16108
- var _initDocument = function _initDocument(dirty) {
16109
- var doc;
16110
- var leadingWhitespace;
16263
+ const _initDocument = function _initDocument(dirty) {
16264
+ let doc;
16265
+ let leadingWhitespace;
16111
16266
  if (FORCE_BODY) {
16112
16267
  dirty = '<remove></remove>' + dirty;
16113
16268
  } else {
16114
- var matches = stringMatch(dirty, /^[\r\n\t ]+/);
16269
+ const matches = stringMatch(dirty, /^[\r\n\t ]+/);
16115
16270
  leadingWhitespace = matches && matches[0];
16116
16271
  }
16117
- if (PARSER_MEDIA_TYPE === 'application/xhtml+xml') {
16272
+ if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
16118
16273
  dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
16119
16274
  }
16120
- var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
16275
+ const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
16121
16276
  if (NAMESPACE === HTML_NAMESPACE) {
16122
16277
  try {
16123
16278
  doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
@@ -16127,11 +16282,11 @@
16127
16282
  if (!doc || !doc.documentElement) {
16128
16283
  doc = implementation.createDocument(NAMESPACE, 'template', null);
16129
16284
  try {
16130
- doc.documentElement.innerHTML = IS_EMPTY_INPUT ? '' : dirtyPayload;
16285
+ doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
16131
16286
  } catch (_) {
16132
16287
  }
16133
16288
  }
16134
- var body = doc.body || doc.documentElement;
16289
+ const body = doc.body || doc.documentElement;
16135
16290
  if (dirty && leadingWhitespace) {
16136
16291
  body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
16137
16292
  }
@@ -16140,47 +16295,39 @@
16140
16295
  }
16141
16296
  return WHOLE_DOCUMENT ? doc.documentElement : body;
16142
16297
  };
16143
- var _createIterator = function _createIterator(root) {
16298
+ const _createIterator = function _createIterator(root) {
16144
16299
  return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
16145
16300
  };
16146
- var _isClobbered = function _isClobbered(elm) {
16147
- return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function');
16301
+ const _isClobbered = function _isClobbered(elm) {
16302
+ return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
16148
16303
  };
16149
- var _isNode = function _isNode(object) {
16150
- return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
16304
+ const _isNode = function _isNode(object) {
16305
+ return typeof Node === 'object' ? object instanceof Node : object && typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
16151
16306
  };
16152
- var _executeHook = function _executeHook(entryPoint, currentNode, data) {
16307
+ const _executeHook = function _executeHook(entryPoint, currentNode, data) {
16153
16308
  if (!hooks[entryPoint]) {
16154
16309
  return;
16155
16310
  }
16156
- arrayForEach(hooks[entryPoint], function (hook) {
16311
+ arrayForEach(hooks[entryPoint], hook => {
16157
16312
  hook.call(DOMPurify, currentNode, data, CONFIG);
16158
16313
  });
16159
16314
  };
16160
- var _sanitizeElements = function _sanitizeElements(currentNode) {
16161
- var content;
16315
+ const _sanitizeElements = function _sanitizeElements(currentNode) {
16316
+ let content;
16162
16317
  _executeHook('beforeSanitizeElements', currentNode, null);
16163
16318
  if (_isClobbered(currentNode)) {
16164
16319
  _forceRemove(currentNode);
16165
16320
  return true;
16166
16321
  }
16167
- if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
16168
- _forceRemove(currentNode);
16169
- return true;
16170
- }
16171
- var tagName = transformCaseFunc(currentNode.nodeName);
16322
+ const tagName = transformCaseFunc(currentNode.nodeName);
16172
16323
  _executeHook('uponSanitizeElement', currentNode, {
16173
- tagName: tagName,
16324
+ tagName,
16174
16325
  allowedTags: ALLOWED_TAGS
16175
16326
  });
16176
16327
  if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
16177
16328
  _forceRemove(currentNode);
16178
16329
  return true;
16179
16330
  }
16180
- if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
16181
- _forceRemove(currentNode);
16182
- return true;
16183
- }
16184
16331
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
16185
16332
  if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
16186
16333
  if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
@@ -16189,11 +16336,11 @@
16189
16336
  return false;
16190
16337
  }
16191
16338
  if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
16192
- var parentNode = getParentNode(currentNode) || currentNode.parentNode;
16193
- var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
16339
+ const parentNode = getParentNode(currentNode) || currentNode.parentNode;
16340
+ const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
16194
16341
  if (childNodes && parentNode) {
16195
- var childCount = childNodes.length;
16196
- for (var i = childCount - 1; i >= 0; --i) {
16342
+ const childCount = childNodes.length;
16343
+ for (let i = childCount - 1; i >= 0; --i) {
16197
16344
  parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
16198
16345
  }
16199
16346
  }
@@ -16205,14 +16352,15 @@
16205
16352
  _forceRemove(currentNode);
16206
16353
  return true;
16207
16354
  }
16208
- if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)) {
16355
+ if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
16209
16356
  _forceRemove(currentNode);
16210
16357
  return true;
16211
16358
  }
16212
16359
  if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
16213
16360
  content = currentNode.textContent;
16214
- content = stringReplace(content, MUSTACHE_EXPR$1, ' ');
16215
- content = stringReplace(content, ERB_EXPR$1, ' ');
16361
+ content = stringReplace(content, MUSTACHE_EXPR, ' ');
16362
+ content = stringReplace(content, ERB_EXPR, ' ');
16363
+ content = stringReplace(content, TMPLIT_EXPR, ' ');
16216
16364
  if (currentNode.textContent !== content) {
16217
16365
  arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
16218
16366
  currentNode.textContent = content;
@@ -16221,41 +16369,40 @@
16221
16369
  _executeHook('afterSanitizeElements', currentNode, null);
16222
16370
  return false;
16223
16371
  };
16224
- var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
16372
+ const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
16225
16373
  if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
16226
16374
  return false;
16227
16375
  }
16228
- if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName));
16229
- else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
16376
+ if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName));
16377
+ else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName));
16230
16378
  else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
16231
16379
  if (_basicCustomElementTest(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)) || 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)));
16232
16380
  else {
16233
16381
  return false;
16234
16382
  }
16235
16383
  } else if (URI_SAFE_ATTRIBUTES[lcName]);
16236
- else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
16384
+ else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, '')));
16237
16385
  else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
16238
- else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
16239
- else if (!value);
16240
- else {
16386
+ else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, '')));
16387
+ else if (value) {
16241
16388
  return false;
16242
- }
16389
+ } else ;
16243
16390
  return true;
16244
16391
  };
16245
- var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
16392
+ const _basicCustomElementTest = function _basicCustomElementTest(tagName) {
16246
16393
  return tagName.indexOf('-') > 0;
16247
16394
  };
16248
- var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
16249
- var attr;
16250
- var value;
16251
- var lcName;
16252
- var l;
16395
+ const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
16396
+ let attr;
16397
+ let value;
16398
+ let lcName;
16399
+ let l;
16253
16400
  _executeHook('beforeSanitizeAttributes', currentNode, null);
16254
- var attributes = currentNode.attributes;
16401
+ const {attributes} = currentNode;
16255
16402
  if (!attributes) {
16256
16403
  return;
16257
16404
  }
16258
- var hookEvent = {
16405
+ const hookEvent = {
16259
16406
  attrName: '',
16260
16407
  attrValue: '',
16261
16408
  keepAttr: true,
@@ -16264,10 +16411,10 @@
16264
16411
  l = attributes.length;
16265
16412
  while (l--) {
16266
16413
  attr = attributes[l];
16267
- var _attr = attr, name = _attr.name, namespaceURI = _attr.namespaceURI;
16414
+ const {name, namespaceURI} = attr;
16268
16415
  value = name === 'value' ? attr.value : stringTrim(attr.value);
16416
+ const initValue = value;
16269
16417
  lcName = transformCaseFunc(name);
16270
- var initValue = value;
16271
16418
  hookEvent.attrName = lcName;
16272
16419
  hookEvent.attrValue = value;
16273
16420
  hookEvent.keepAttr = true;
@@ -16281,19 +16428,39 @@
16281
16428
  _removeAttribute(name, currentNode);
16282
16429
  continue;
16283
16430
  }
16284
- if (regExpTest(/\/>/i, value)) {
16431
+ if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
16285
16432
  _removeAttribute(name, currentNode);
16286
16433
  continue;
16287
16434
  }
16288
16435
  if (SAFE_FOR_TEMPLATES) {
16289
- value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
16290
- value = stringReplace(value, ERB_EXPR$1, ' ');
16436
+ value = stringReplace(value, MUSTACHE_EXPR, ' ');
16437
+ value = stringReplace(value, ERB_EXPR, ' ');
16438
+ value = stringReplace(value, TMPLIT_EXPR, ' ');
16291
16439
  }
16292
- var lcTag = transformCaseFunc(currentNode.nodeName);
16440
+ const lcTag = transformCaseFunc(currentNode.nodeName);
16293
16441
  if (!_isValidAttribute(lcTag, lcName, value)) {
16294
16442
  _removeAttribute(name, currentNode);
16295
16443
  continue;
16296
16444
  }
16445
+ if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
16446
+ _removeAttribute(name, currentNode);
16447
+ value = SANITIZE_NAMED_PROPS_PREFIX + value;
16448
+ }
16449
+ if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
16450
+ if (namespaceURI);
16451
+ else {
16452
+ switch (trustedTypes.getAttributeType(lcTag, lcName)) {
16453
+ case 'TrustedHTML': {
16454
+ value = trustedTypesPolicy.createHTML(value);
16455
+ break;
16456
+ }
16457
+ case 'TrustedScriptURL': {
16458
+ value = trustedTypesPolicy.createScriptURL(value);
16459
+ break;
16460
+ }
16461
+ }
16462
+ }
16463
+ }
16297
16464
  if (value !== initValue) {
16298
16465
  try {
16299
16466
  if (namespaceURI) {
@@ -16308,9 +16475,9 @@
16308
16475
  }
16309
16476
  _executeHook('afterSanitizeAttributes', currentNode, null);
16310
16477
  };
16311
- var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
16312
- var shadowNode;
16313
- var shadowIterator = _createIterator(fragment);
16478
+ const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
16479
+ let shadowNode;
16480
+ const shadowIterator = _createIterator(fragment);
16314
16481
  _executeHook('beforeSanitizeShadowDOM', fragment, null);
16315
16482
  while (shadowNode = shadowIterator.nextNode()) {
16316
16483
  _executeHook('uponSanitizeShadowNode', shadowNode, null);
@@ -16324,35 +16491,27 @@
16324
16491
  }
16325
16492
  _executeHook('afterSanitizeShadowDOM', fragment, null);
16326
16493
  };
16327
- DOMPurify.sanitize = function (dirty, cfg) {
16328
- var body;
16329
- var importedNode;
16330
- var currentNode;
16331
- var oldNode;
16332
- var returnNode;
16494
+ DOMPurify.sanitize = function (dirty) {
16495
+ let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
16496
+ let body;
16497
+ let importedNode;
16498
+ let currentNode;
16499
+ let returnNode;
16333
16500
  IS_EMPTY_INPUT = !dirty;
16334
16501
  if (IS_EMPTY_INPUT) {
16335
16502
  dirty = '<!-->';
16336
16503
  }
16337
16504
  if (typeof dirty !== 'string' && !_isNode(dirty)) {
16338
- if (typeof dirty.toString !== 'function') {
16339
- throw typeErrorCreate('toString is not a function');
16340
- } else {
16505
+ if (typeof dirty.toString === 'function') {
16341
16506
  dirty = dirty.toString();
16342
16507
  if (typeof dirty !== 'string') {
16343
16508
  throw typeErrorCreate('dirty is not a string, aborting');
16344
16509
  }
16510
+ } else {
16511
+ throw typeErrorCreate('toString is not a function');
16345
16512
  }
16346
16513
  }
16347
16514
  if (!DOMPurify.isSupported) {
16348
- if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
16349
- if (typeof dirty === 'string') {
16350
- return window.toStaticHTML(dirty);
16351
- }
16352
- if (_isNode(dirty)) {
16353
- return window.toStaticHTML(dirty.outerHTML);
16354
- }
16355
- }
16356
16515
  return dirty;
16357
16516
  }
16358
16517
  if (!SET_CONFIG) {
@@ -16364,7 +16523,7 @@
16364
16523
  }
16365
16524
  if (IN_PLACE) {
16366
16525
  if (dirty.nodeName) {
16367
- var tagName = transformCaseFunc(dirty.nodeName);
16526
+ const tagName = transformCaseFunc(dirty.nodeName);
16368
16527
  if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
16369
16528
  throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
16370
16529
  }
@@ -16391,11 +16550,8 @@
16391
16550
  if (body && FORCE_BODY) {
16392
16551
  _forceRemove(body.firstChild);
16393
16552
  }
16394
- var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
16553
+ const nodeIterator = _createIterator(IN_PLACE ? dirty : body);
16395
16554
  while (currentNode = nodeIterator.nextNode()) {
16396
- if (currentNode.nodeType === 3 && currentNode === oldNode) {
16397
- continue;
16398
- }
16399
16555
  if (_sanitizeElements(currentNode)) {
16400
16556
  continue;
16401
16557
  }
@@ -16403,9 +16559,7 @@
16403
16559
  _sanitizeShadowDOM(currentNode.content);
16404
16560
  }
16405
16561
  _sanitizeAttributes(currentNode);
16406
- oldNode = currentNode;
16407
16562
  }
16408
- oldNode = null;
16409
16563
  if (IN_PLACE) {
16410
16564
  return dirty;
16411
16565
  }
@@ -16418,18 +16572,19 @@
16418
16572
  } else {
16419
16573
  returnNode = body;
16420
16574
  }
16421
- if (ALLOWED_ATTR.shadowroot) {
16575
+ if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
16422
16576
  returnNode = importNode.call(originalDocument, returnNode, true);
16423
16577
  }
16424
16578
  return returnNode;
16425
16579
  }
16426
- var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
16580
+ let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
16427
16581
  if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
16428
16582
  serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
16429
16583
  }
16430
16584
  if (SAFE_FOR_TEMPLATES) {
16431
- serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
16432
- serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
16585
+ serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR, ' ');
16586
+ serializedHTML = stringReplace(serializedHTML, ERB_EXPR, ' ');
16587
+ serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR, ' ');
16433
16588
  }
16434
16589
  return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
16435
16590
  };
@@ -16445,8 +16600,8 @@
16445
16600
  if (!CONFIG) {
16446
16601
  _parseConfig({});
16447
16602
  }
16448
- var lcTag = transformCaseFunc(tag);
16449
- var lcName = transformCaseFunc(attr);
16603
+ const lcTag = transformCaseFunc(tag);
16604
+ const lcName = transformCaseFunc(attr);
16450
16605
  return _isValidAttribute(lcTag, lcName, value);
16451
16606
  };
16452
16607
  DOMPurify.addHook = function (entryPoint, hookFunction) {
@@ -16782,7 +16937,7 @@
16782
16937
  const filteredUrlAttrs = Tools.makeMap('src,href,data,background,action,formaction,poster,xlink:href');
16783
16938
  const internalElementAttr = 'data-mce-type';
16784
16939
  let uid = 0;
16785
- const processNode = (node, settings, schema, evt) => {
16940
+ const processNode = (node, settings, schema, scope, evt) => {
16786
16941
  var _a, _b, _c, _d;
16787
16942
  const validate = settings.validate;
16788
16943
  const specialElements = schema.getSpecialElements();
@@ -16790,6 +16945,12 @@
16790
16945
  node.nodeValue = ' ' + node.nodeValue;
16791
16946
  }
16792
16947
  const lcTagName = (_b = evt === null || evt === void 0 ? void 0 : evt.tagName) !== null && _b !== void 0 ? _b : node.nodeName.toLowerCase();
16948
+ if (scope !== 'html' && schema.isValid(scope)) {
16949
+ if (isNonNullable(evt)) {
16950
+ evt.allowedTags[lcTagName] = true;
16951
+ }
16952
+ return;
16953
+ }
16793
16954
  if (node.nodeType !== ELEMENT || lcTagName === 'body') {
16794
16955
  return;
16795
16956
  }
@@ -16839,42 +17000,50 @@
16839
17000
  }
16840
17001
  }
16841
17002
  };
16842
- const shouldKeepAttribute = (settings, schema, tagName, attrName, attrValue) => !(attrName in filteredUrlAttrs && isInvalidUri(settings, attrValue, tagName)) && (!settings.validate || schema.isValid(tagName, attrName) || startsWith(attrName, 'data-') || startsWith(attrName, 'aria-'));
17003
+ const processAttr = (ele, settings, schema, scope, evt) => {
17004
+ const tagName = ele.tagName.toLowerCase();
17005
+ const {attrName, attrValue} = evt;
17006
+ evt.keepAttr = shouldKeepAttribute(settings, schema, scope, tagName, attrName, attrValue);
17007
+ if (evt.keepAttr) {
17008
+ evt.allowedAttributes[attrName] = true;
17009
+ if (isBooleanAttribute(attrName, schema)) {
17010
+ evt.attrValue = attrName;
17011
+ }
17012
+ if (settings.allow_svg_data_urls && startsWith(attrValue, 'data:image/svg+xml')) {
17013
+ evt.forceKeepAttr = true;
17014
+ }
17015
+ } else if (isRequiredAttributeOfInternalElement(ele, attrName)) {
17016
+ evt.forceKeepAttr = true;
17017
+ }
17018
+ };
17019
+ const shouldKeepAttribute = (settings, schema, scope, tagName, attrName, attrValue) => {
17020
+ if (scope !== 'html' && !isNonHtmlElementRootName(tagName)) {
17021
+ return true;
17022
+ }
17023
+ return !(attrName in filteredUrlAttrs && isInvalidUri(settings, attrValue, tagName)) && (!settings.validate || schema.isValid(tagName, attrName) || startsWith(attrName, 'data-') || startsWith(attrName, 'aria-'));
17024
+ };
16843
17025
  const isRequiredAttributeOfInternalElement = (ele, attrName) => ele.hasAttribute(internalElementAttr) && (attrName === 'id' || attrName === 'class' || attrName === 'style');
16844
17026
  const isBooleanAttribute = (attrName, schema) => attrName in schema.getBoolAttrs();
16845
- const filterAttributes = (ele, settings, schema) => {
17027
+ const filterAttributes = (ele, settings, schema, scope) => {
16846
17028
  const {attributes} = ele;
16847
17029
  for (let i = attributes.length - 1; i >= 0; i--) {
16848
17030
  const attr = attributes[i];
16849
17031
  const attrName = attr.name;
16850
17032
  const attrValue = attr.value;
16851
- if (!shouldKeepAttribute(settings, schema, ele.tagName.toLowerCase(), attrName, attrValue) && !isRequiredAttributeOfInternalElement(ele, attrName)) {
17033
+ if (!shouldKeepAttribute(settings, schema, scope, ele.tagName.toLowerCase(), attrName, attrValue) && !isRequiredAttributeOfInternalElement(ele, attrName)) {
16852
17034
  ele.removeAttribute(attrName);
16853
17035
  } else if (isBooleanAttribute(attrName, schema)) {
16854
17036
  ele.setAttribute(attrName, attrName);
16855
17037
  }
16856
17038
  }
16857
17039
  };
16858
- const setupPurify = (settings, schema) => {
17040
+ const setupPurify = (settings, schema, namespaceTracker) => {
16859
17041
  const purify$1 = purify();
16860
17042
  purify$1.addHook('uponSanitizeElement', (ele, evt) => {
16861
- processNode(ele, settings, schema, evt);
17043
+ processNode(ele, settings, schema, namespaceTracker.track(ele), evt);
16862
17044
  });
16863
17045
  purify$1.addHook('uponSanitizeAttribute', (ele, evt) => {
16864
- const tagName = ele.tagName.toLowerCase();
16865
- const {attrName, attrValue} = evt;
16866
- evt.keepAttr = shouldKeepAttribute(settings, schema, tagName, attrName, attrValue);
16867
- if (evt.keepAttr) {
16868
- evt.allowedAttributes[attrName] = true;
16869
- if (isBooleanAttribute(attrName, schema)) {
16870
- evt.attrValue = attrName;
16871
- }
16872
- if (settings.allow_svg_data_urls && startsWith(attrValue, 'data:image/svg+xml')) {
16873
- evt.forceKeepAttr = true;
16874
- }
16875
- } else if (isRequiredAttributeOfInternalElement(ele, attrName)) {
16876
- evt.forceKeepAttr = true;
16877
- }
17046
+ processAttr(ele, settings, schema, namespaceTracker.current(), evt);
16878
17047
  });
16879
17048
  return purify$1;
16880
17049
  };
@@ -16898,29 +17067,67 @@
16898
17067
  }
16899
17068
  return config;
16900
17069
  };
17070
+ const sanitizeNamespaceElement = ele => {
17071
+ const xlinkAttrs = [
17072
+ 'type',
17073
+ 'href',
17074
+ 'role',
17075
+ 'arcrole',
17076
+ 'title',
17077
+ 'show',
17078
+ 'actuate',
17079
+ 'label',
17080
+ 'from',
17081
+ 'to'
17082
+ ].map(name => `xlink:${ name }`);
17083
+ const config = {
17084
+ IN_PLACE: true,
17085
+ USE_PROFILES: {
17086
+ html: true,
17087
+ svg: true,
17088
+ svgFilters: true
17089
+ },
17090
+ ALLOWED_ATTR: xlinkAttrs
17091
+ };
17092
+ purify().sanitize(ele, config);
17093
+ return ele.innerHTML;
17094
+ };
16901
17095
  const getSanitizer = (settings, schema) => {
17096
+ const namespaceTracker = createNamespaceTracker();
16902
17097
  if (settings.sanitize) {
16903
- const purify = setupPurify(settings, schema);
16904
- return (body, mimeType) => {
17098
+ const purify = setupPurify(settings, schema, namespaceTracker);
17099
+ const sanitizeHtmlElement = (body, mimeType) => {
16905
17100
  purify.sanitize(body, getPurifyConfig(settings, mimeType));
16906
17101
  purify.removed = [];
17102
+ namespaceTracker.reset();
17103
+ };
17104
+ return {
17105
+ sanitizeHtmlElement,
17106
+ sanitizeNamespaceElement
16907
17107
  };
16908
17108
  } else {
16909
- return (body, _) => {
17109
+ const sanitizeHtmlElement = (body, _mimeType) => {
16910
17110
  const nodeIterator = document.createNodeIterator(body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT);
16911
17111
  let node;
16912
17112
  while (node = nodeIterator.nextNode()) {
16913
- processNode(node, settings, schema);
17113
+ const currentScope = namespaceTracker.track(node);
17114
+ processNode(node, settings, schema, currentScope);
16914
17115
  if (isElement$6(node)) {
16915
- filterAttributes(node, settings, schema);
17116
+ filterAttributes(node, settings, schema, currentScope);
16916
17117
  }
16917
17118
  }
17119
+ namespaceTracker.reset();
17120
+ };
17121
+ const sanitizeNamespaceElement = noop;
17122
+ return {
17123
+ sanitizeHtmlElement,
17124
+ sanitizeNamespaceElement
16918
17125
  };
16919
17126
  }
16920
17127
  };
16921
17128
 
16922
17129
  const makeMap = Tools.makeMap, extend$1 = Tools.extend;
16923
- const transferChildren = (parent, nativeParent, specialElements) => {
17130
+ const transferChildren = (parent, nativeParent, specialElements, nsSanitizer) => {
16924
17131
  const parentName = parent.name;
16925
17132
  const isSpecial = parentName in specialElements && parentName !== 'title' && parentName !== 'textarea';
16926
17133
  const childNodes = nativeParent.childNodes;
@@ -16933,6 +17140,10 @@
16933
17140
  const attr = attributes[ai];
16934
17141
  child.attr(attr.name, attr.value);
16935
17142
  }
17143
+ if (isNonHtmlElementRootName(child.name)) {
17144
+ nsSanitizer(nativeChild);
17145
+ child.value = nativeChild.innerHTML;
17146
+ }
16936
17147
  } else if (isText$a(nativeChild)) {
16937
17148
  child.value = nativeChild.data;
16938
17149
  if (isSpecial) {
@@ -16941,7 +17152,9 @@
16941
17152
  } else if (isComment(nativeChild) || isCData(nativeChild) || isPi(nativeChild)) {
16942
17153
  child.value = nativeChild.data;
16943
17154
  }
16944
- transferChildren(child, nativeChild, specialElements);
17155
+ if (!isNonHtmlElementRootName(child.name)) {
17156
+ transferChildren(child, nativeChild, specialElements, nsSanitizer);
17157
+ }
16945
17158
  parent.append(child);
16946
17159
  }
16947
17160
  };
@@ -16992,7 +17205,7 @@
16992
17205
  }
16993
17206
  return false;
16994
17207
  };
16995
- const isBlock = node => node.name in blockElements || isTransparentAstBlock(schema, node);
17208
+ const isBlock = node => node.name in blockElements || isTransparentAstBlock(schema, node) || isNonHtmlElementRootName(node.name) && node.parent === root;
16996
17209
  const isAtEdgeOfBlock = (node, start) => {
16997
17210
  const neighbour = start ? node.prev : node.next;
16998
17211
  if (isNonNullable(neighbour) || isNullable(node.parent)) {
@@ -17075,14 +17288,14 @@
17075
17288
  ...settings
17076
17289
  };
17077
17290
  const parser = new DOMParser();
17078
- const sanitize = getSanitizer(defaultedSettings, schema);
17291
+ const sanitizer = getSanitizer(defaultedSettings, schema);
17079
17292
  const parseAndSanitizeWithContext = (html, rootName, format = 'html') => {
17080
17293
  const mimeType = format === 'xhtml' ? 'application/xhtml+xml' : 'text/html';
17081
17294
  const isSpecialRoot = has$2(schema.getSpecialElements(), rootName.toLowerCase());
17082
17295
  const content = isSpecialRoot ? `<${ rootName }>${ html }</${ rootName }>` : html;
17083
17296
  const wrappedHtml = format === 'xhtml' ? `<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>${ content }</body></html>` : `<body>${ content }</body>`;
17084
17297
  const body = parser.parseFromString(wrappedHtml, mimeType).body;
17085
- sanitize(body, mimeType);
17298
+ sanitizer.sanitizeHtmlElement(body, mimeType);
17086
17299
  return isSpecialRoot ? body.firstChild : body;
17087
17300
  };
17088
17301
  const addNodeFilter = nodeFilterRegistry.addFilter;
@@ -17098,7 +17311,7 @@
17098
17311
  };
17099
17312
  const isWrappableNode = (blockElements, node) => {
17100
17313
  const isInternalElement = isString(node.attr(internalElementAttr));
17101
- const isInlineElement = node.type === 1 && (!has$2(blockElements, node.name) && !isTransparentAstBlock(schema, node));
17314
+ const isInlineElement = node.type === 1 && (!has$2(blockElements, node.name) && !isTransparentAstBlock(schema, node)) && !isNonHtmlElementRootName(node.name);
17102
17315
  return node.type === 3 || isInlineElement && !isInternalElement;
17103
17316
  };
17104
17317
  const addRootBlocks = (rootNode, rootBlockName) => {
@@ -17148,7 +17361,7 @@
17148
17361
  const element = parseAndSanitizeWithContext(html, rootName, args.format);
17149
17362
  updateChildren(schema, element);
17150
17363
  const rootNode = new AstNode(rootName, 11);
17151
- transferChildren(rootNode, element, schema.getSpecialElements());
17364
+ transferChildren(rootNode, element, schema.getSpecialElements(), sanitizer.sanitizeNamespaceElement);
17152
17365
  element.innerHTML = '';
17153
17366
  const [whitespacePre, whitespacePost] = whitespaceCleaner(rootNode, schema, defaultedSettings, args);
17154
17367
  const invalidChildren = [];
@@ -17203,7 +17416,7 @@
17203
17416
  };
17204
17417
 
17205
17418
  const serializeContent = content => isTreeNode(content) ? HtmlSerializer({ validate: false }).serialize(content) : content;
17206
- const withSerializedContent = (content, fireEvent, sanitize) => {
17419
+ const withSerializedContent = (content, fireEvent, parserSettings) => {
17207
17420
  const serializedContent = serializeContent(content);
17208
17421
  const eventArgs = fireEvent(serializedContent);
17209
17422
  if (eventArgs.isDefaultPrevented()) {
@@ -17213,7 +17426,7 @@
17213
17426
  const rootNode = DomParser({
17214
17427
  validate: false,
17215
17428
  forced_root_block: false,
17216
- sanitize
17429
+ ...parserSettings
17217
17430
  }).parse(eventArgs.content, { context: content.name });
17218
17431
  return {
17219
17432
  ...eventArgs,
@@ -17251,7 +17464,10 @@
17251
17464
  const processedEventArgs = withSerializedContent(content, content => fireGetContent(editor, {
17252
17465
  ...args,
17253
17466
  content
17254
- }), shouldSanitizeXss(editor));
17467
+ }), {
17468
+ sanitize: shouldSanitizeXss(editor),
17469
+ sandbox_iframes: shouldSandboxIframes(editor)
17470
+ });
17255
17471
  return processedEventArgs.content;
17256
17472
  }
17257
17473
  };
@@ -17262,7 +17478,10 @@
17262
17478
  const processedEventArgs = withSerializedContent(args.content, content => fireBeforeSetContent(editor, {
17263
17479
  ...args,
17264
17480
  content
17265
- }), shouldSanitizeXss(editor));
17481
+ }), {
17482
+ sanitize: shouldSanitizeXss(editor),
17483
+ sandbox_iframes: shouldSandboxIframes(editor)
17484
+ });
17266
17485
  if (processedEventArgs.isDefaultPrevented()) {
17267
17486
  fireSetContent(editor, processedEventArgs);
17268
17487
  return Result.error(undefined);
@@ -17421,16 +17640,16 @@
17421
17640
  return isList(commonAnchorContainer) ? [commonAnchorContainer] : [];
17422
17641
  }
17423
17642
  };
17424
- const getWrapElements = (rootNode, rng) => {
17643
+ const getWrapElements = (rootNode, rng, schema) => {
17425
17644
  const commonAnchorContainer = SugarElement.fromDom(rng.commonAncestorContainer);
17426
17645
  const parents = parentsAndSelf(commonAnchorContainer, rootNode);
17427
- const wrapElements = filter$5(parents, isWrapElement);
17646
+ const wrapElements = filter$5(parents, el => schema.isWrapper(name(el)));
17428
17647
  const listWrappers = getFullySelectedListWrappers(parents, rng);
17429
17648
  const allWrappers = wrapElements.concat(listWrappers.length ? listWrappers : directListWrappers(commonAnchorContainer));
17430
17649
  return map$3(allWrappers, shallow$1);
17431
17650
  };
17432
17651
  const emptyFragment = () => fromElements([]);
17433
- const getFragmentFromRange = (rootNode, rng) => wrap(SugarElement.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng));
17652
+ const getFragmentFromRange = (rootNode, rng, schema) => wrap(SugarElement.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng, schema));
17434
17653
  const getParentTable = (rootElm, cell) => ancestor$3(cell, 'table', curry(eq, rootElm));
17435
17654
  const getTableFragment = (rootNode, selectedTableCells) => getParentTable(rootNode, selectedTableCells[0]).bind(tableElm => {
17436
17655
  const firstCell = selectedTableCells[0];
@@ -17438,10 +17657,10 @@
17438
17657
  const fullTableModel = fromDom(tableElm);
17439
17658
  return subsection(fullTableModel, firstCell, lastCell).map(sectionedTableModel => fromElements([toDom(sectionedTableModel)]));
17440
17659
  }).getOrThunk(emptyFragment);
17441
- const getSelectionFragment = (rootNode, ranges) => ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0]);
17442
- const read$3 = (rootNode, ranges) => {
17660
+ const getSelectionFragment = (rootNode, ranges, schema) => ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0], schema);
17661
+ const read$3 = (rootNode, ranges, schema) => {
17443
17662
  const selectedCells = getCellsFromElementOrRanges(ranges, rootNode);
17444
- return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges);
17663
+ return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges, schema);
17445
17664
  };
17446
17665
 
17447
17666
  const isCollapsibleWhitespace = (text, index) => index >= 0 && index < text.length && isWhiteSpace(text.charAt(index));
@@ -17483,7 +17702,7 @@
17483
17702
  const rng = editor.selection.getRng(), tmpElm = editor.dom.create('body');
17484
17703
  const sel = editor.selection.getSel();
17485
17704
  const ranges = processRanges(editor, getRanges$1(sel));
17486
- const fragment = args.contextual ? read$3(SugarElement.fromDom(editor.getBody()), ranges).dom : rng.cloneContents();
17705
+ const fragment = args.contextual ? read$3(SugarElement.fromDom(editor.getBody()), ranges, editor.schema).dom : rng.cloneContents();
17487
17706
  if (fragment) {
17488
17707
  tmpElm.appendChild(fragment);
17489
17708
  }
@@ -18066,7 +18285,7 @@
18066
18285
  };
18067
18286
  const isRtc = editor => has$2(editor.plugins, 'rtc');
18068
18287
  const getRtcSetup = editor => get$a(editor.plugins, 'rtc').bind(rtcPlugin => Optional.from(rtcPlugin.setup));
18069
- const setup$s = editor => {
18288
+ const setup$t = editor => {
18070
18289
  const editorCast = editor;
18071
18290
  return getRtcSetup(editor).fold(() => {
18072
18291
  editorCast.rtcInstance = makePlainAdaptor(editor);
@@ -18147,47 +18366,47 @@
18147
18366
  }
18148
18367
  };
18149
18368
  const walkPastBookmark = (node, start) => node.filter(elm => BookmarkManager.isBookmarkNode(elm.dom)).bind(start ? nextSibling : prevSibling);
18150
- const merge$1 = (outer, inner, rng, start) => {
18369
+ const merge$1 = (outer, inner, rng, start, schema) => {
18151
18370
  const outerElm = outer.dom;
18152
18371
  const innerElm = inner.dom;
18153
18372
  const oldLength = start ? outerElm.length : innerElm.length;
18154
18373
  if (start) {
18155
- mergeTextNodes(outerElm, innerElm, false, !start);
18374
+ mergeTextNodes(outerElm, innerElm, schema, false, !start);
18156
18375
  rng.setStart(innerElm, oldLength);
18157
18376
  } else {
18158
- mergeTextNodes(innerElm, outerElm, false, !start);
18377
+ mergeTextNodes(innerElm, outerElm, schema, false, !start);
18159
18378
  rng.setEnd(innerElm, oldLength);
18160
18379
  }
18161
18380
  };
18162
- const normalizeTextIfRequired = (inner, start) => {
18381
+ const normalizeTextIfRequired = (inner, start, schema) => {
18163
18382
  parent(inner).each(root => {
18164
18383
  const text = inner.dom;
18165
- if (start && needsToBeNbspLeft(root, CaretPosition(text, 0))) {
18166
- normalizeWhitespaceAfter(text, 0);
18167
- } else if (!start && needsToBeNbspRight(root, CaretPosition(text, text.length))) {
18168
- normalizeWhitespaceBefore(text, text.length);
18384
+ if (start && needsToBeNbspLeft(root, CaretPosition(text, 0), schema)) {
18385
+ normalizeWhitespaceAfter(text, 0, schema);
18386
+ } else if (!start && needsToBeNbspRight(root, CaretPosition(text, text.length), schema)) {
18387
+ normalizeWhitespaceBefore(text, text.length, schema);
18169
18388
  }
18170
18389
  });
18171
18390
  };
18172
- const mergeAndNormalizeText = (outerNode, innerNode, rng, start) => {
18391
+ const mergeAndNormalizeText = (outerNode, innerNode, rng, start, schema) => {
18173
18392
  outerNode.bind(outer => {
18174
18393
  const normalizer = start ? normalizeWhitespaceBefore : normalizeWhitespaceAfter;
18175
- normalizer(outer.dom, start ? outer.dom.length : 0);
18176
- return innerNode.filter(isText$b).map(inner => merge$1(outer, inner, rng, start));
18394
+ normalizer(outer.dom, start ? outer.dom.length : 0, schema);
18395
+ return innerNode.filter(isText$b).map(inner => merge$1(outer, inner, rng, start, schema));
18177
18396
  }).orThunk(() => {
18178
18397
  const innerTextNode = walkPastBookmark(innerNode, start).or(innerNode).filter(isText$b);
18179
- return innerTextNode.map(inner => normalizeTextIfRequired(inner, start));
18398
+ return innerTextNode.map(inner => normalizeTextIfRequired(inner, start, schema));
18180
18399
  });
18181
18400
  };
18182
- const rngSetContent = (rng, fragment) => {
18401
+ const rngSetContent = (rng, fragment, schema) => {
18183
18402
  const firstChild = Optional.from(fragment.firstChild).map(SugarElement.fromDom);
18184
18403
  const lastChild = Optional.from(fragment.lastChild).map(SugarElement.fromDom);
18185
18404
  rng.deleteContents();
18186
18405
  rng.insertNode(fragment);
18187
18406
  const prevText = firstChild.bind(prevSibling).filter(isText$b).bind(removeEmpty);
18188
18407
  const nextText = lastChild.bind(nextSibling).filter(isText$b).bind(removeEmpty);
18189
- mergeAndNormalizeText(prevText, firstChild, rng, true);
18190
- mergeAndNormalizeText(nextText, lastChild, rng, false);
18408
+ mergeAndNormalizeText(prevText, firstChild, rng, true, schema);
18409
+ mergeAndNormalizeText(nextText, lastChild, rng, false, schema);
18191
18410
  rng.collapse(false);
18192
18411
  };
18193
18412
  const setupArgs$2 = (args, content) => ({
@@ -18217,7 +18436,7 @@
18217
18436
  preProcessSetContent(editor, defaultedArgs).each(updatedArgs => {
18218
18437
  const cleanedContent = cleanContent(editor, updatedArgs);
18219
18438
  const rng = editor.selection.getRng();
18220
- rngSetContent(rng, rng.createContextualFragment(cleanedContent));
18439
+ rngSetContent(rng, rng.createContextualFragment(cleanedContent), editor.schema);
18221
18440
  editor.selection.setRng(rng);
18222
18441
  scrollRangeIntoView(editor, rng);
18223
18442
  postProcessSetContent(editor, cleanedContent, updatedArgs);
@@ -18348,10 +18567,8 @@
18348
18567
  const fakeSelectedElements = editor.getBody().querySelectorAll('[data-mce-selected="1"]');
18349
18568
  if (fakeSelectedElements.length > 0) {
18350
18569
  return forall(fakeSelectedElements, el => dom.isEditable(el.parentElement));
18351
- } else if (rng.startContainer === rng.endContainer) {
18352
- return dom.isEditable(rng.startContainer);
18353
18570
  } else {
18354
- return dom.isEditable(rng.startContainer) && dom.isEditable(rng.endContainer);
18571
+ return isEditableRange(dom, rng);
18355
18572
  }
18356
18573
  };
18357
18574
  const collapse = toStart => {
@@ -19136,7 +19353,9 @@
19136
19353
  const notification = getImplementation().open(spec, () => {
19137
19354
  closeNotification(notification);
19138
19355
  reposition();
19139
- getTopNotification().fold(() => editor.focus(), top => focus$1(SugarElement.fromDom(top.getEl())));
19356
+ if (hasEditorOrUiFocus(editor)) {
19357
+ getTopNotification().fold(() => editor.focus(), top => focus$1(SugarElement.fromDom(top.getEl())));
19358
+ }
19140
19359
  });
19141
19360
  addNotification(notification);
19142
19361
  reposition();
@@ -19335,6 +19554,8 @@
19335
19554
  };
19336
19555
 
19337
19556
  const isContentCssSkinName = url => /^[a-z0-9\-]+$/i.test(url);
19557
+ const toContentSkinResourceName = url => 'content/' + url + '/content.css';
19558
+ const isBundledCssSkinName = url => tinymce.Resource.has(toContentSkinResourceName(url));
19338
19559
  const getContentCssUrls = editor => {
19339
19560
  return transformToUrls(editor, getContentCss(editor));
19340
19561
  };
@@ -19346,7 +19567,9 @@
19346
19567
  const suffix = editor.editorManager.suffix;
19347
19568
  const contentCssFile = `content${ suffix }.css`;
19348
19569
  return map$3(cssLinks, url => {
19349
- if (isContentCssSkinName(url) && !editor.inline) {
19570
+ if (isBundledCssSkinName(url)) {
19571
+ return url;
19572
+ } else if (isContentCssSkinName(url) && !editor.inline) {
19350
19573
  return `${ skinUrl }/${ url }/${ contentCssFile }`;
19351
19574
  } else {
19352
19575
  return editor.documentBaseURI.toAbsolute(url);
@@ -20553,7 +20776,7 @@
20553
20776
  return previewCss;
20554
20777
  };
20555
20778
 
20556
- const setup$r = editor => {
20779
+ const setup$s = editor => {
20557
20780
  editor.addShortcut('meta+b', '', 'Bold');
20558
20781
  editor.addShortcut('meta+i', '', 'Italic');
20559
20782
  editor.addShortcut('meta+u', '', 'Underline');
@@ -20584,10 +20807,10 @@
20584
20807
  const Formatter = editor => {
20585
20808
  const formats = FormatRegistry(editor);
20586
20809
  const formatChangeState = Cell({});
20587
- setup$r(editor);
20588
- setup$u(editor);
20810
+ setup$s(editor);
20811
+ setup$v(editor);
20589
20812
  if (!isRtc(editor)) {
20590
- setup$t(formatChangeState, editor);
20813
+ setup$u(formatChangeState, editor);
20591
20814
  }
20592
20815
  return {
20593
20816
  get: formats.get,
@@ -20830,7 +21053,7 @@
20830
21053
  return false;
20831
21054
  }
20832
21055
  };
20833
- const setup$q = editor => {
21056
+ const setup$r = editor => {
20834
21057
  var _a;
20835
21058
  const dom = editor.dom;
20836
21059
  const rootBlock = getForcedRootBlock(editor);
@@ -20907,12 +21130,12 @@
20907
21130
  };
20908
21131
  const read$1 = (rootNode, forward, rng) => rng.collapsed ? readFromRange(rootNode, forward, rng) : Optional.none();
20909
21132
 
20910
- const getChildrenUntilBlockBoundary = block => {
21133
+ const getChildrenUntilBlockBoundary = (block, schema) => {
20911
21134
  const children = children$1(block);
20912
- return findIndex$2(children, isBlock$2).fold(constant(children), index => children.slice(0, index));
21135
+ return findIndex$2(children, el => schema.isBlock(name(el))).fold(constant(children), index => children.slice(0, index));
20913
21136
  };
20914
- const extractChildren = block => {
20915
- const children = getChildrenUntilBlockBoundary(block);
21137
+ const extractChildren = (block, schema) => {
21138
+ const children = getChildrenUntilBlockBoundary(block, schema);
20916
21139
  each$e(children, remove$5);
20917
21140
  return children;
20918
21141
  };
@@ -20921,7 +21144,7 @@
20921
21144
  return find$2(parents.reverse(), element => isEmpty$2(element)).each(remove$5);
20922
21145
  };
20923
21146
  const isEmptyBefore = el => filter$5(prevSiblings(el), el => !isEmpty$2(el)).length === 0;
20924
- const nestedBlockMerge = (rootNode, fromBlock, toBlock, insertionPoint) => {
21147
+ const nestedBlockMerge = (rootNode, fromBlock, toBlock, schema, insertionPoint) => {
20925
21148
  if (isEmpty$2(toBlock)) {
20926
21149
  fillWithPaddingBr(toBlock);
20927
21150
  return firstPositionIn(toBlock.dom);
@@ -20930,17 +21153,18 @@
20930
21153
  before$3(insertionPoint, SugarElement.fromTag('br'));
20931
21154
  }
20932
21155
  const position = prevPosition(toBlock.dom, CaretPosition.before(insertionPoint.dom));
20933
- each$e(extractChildren(fromBlock), child => {
21156
+ each$e(extractChildren(fromBlock, schema), child => {
20934
21157
  before$3(insertionPoint, child);
20935
21158
  });
20936
21159
  removeEmptyRoot(rootNode, fromBlock);
20937
21160
  return position;
20938
21161
  };
20939
- const sidelongBlockMerge = (rootNode, fromBlock, toBlock) => {
21162
+ const isInline = (schema, node) => schema.isInline(name(node));
21163
+ const sidelongBlockMerge = (rootNode, fromBlock, toBlock, schema) => {
20940
21164
  if (isEmpty$2(toBlock)) {
20941
21165
  if (isEmpty$2(fromBlock)) {
20942
21166
  const getInlineToBlockDescendants = el => {
20943
- const helper = (node, elements) => firstChild(node).fold(() => elements, child => isInline$1(child) ? helper(child, elements.concat(shallow$1(child))) : elements);
21167
+ const helper = (node, elements) => firstChild(node).fold(() => elements, child => isInline(schema, child) ? helper(child, elements.concat(shallow$1(child))) : elements);
20944
21168
  return helper(el, []);
20945
21169
  };
20946
21170
  const newFromBlockDescendants = foldr(getInlineToBlockDescendants(toBlock), (element, descendant) => {
@@ -20954,7 +21178,7 @@
20954
21178
  return firstPositionIn(fromBlock.dom);
20955
21179
  }
20956
21180
  const position = lastPositionIn(toBlock.dom);
20957
- each$e(extractChildren(fromBlock), child => {
21181
+ each$e(extractChildren(fromBlock, schema), child => {
20958
21182
  append$1(toBlock, child);
20959
21183
  });
20960
21184
  removeEmptyRoot(rootNode, fromBlock);
@@ -20968,30 +21192,30 @@
20968
21192
  const trimBr = (first, block) => {
20969
21193
  positionIn(first, block.dom).bind(position => Optional.from(position.getNode())).map(SugarElement.fromDom).filter(isBr$5).each(remove$5);
20970
21194
  };
20971
- const mergeBlockInto = (rootNode, fromBlock, toBlock) => {
21195
+ const mergeBlockInto = (rootNode, fromBlock, toBlock, schema) => {
20972
21196
  trimBr(true, fromBlock);
20973
21197
  trimBr(false, toBlock);
20974
- return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock), curry(nestedBlockMerge, rootNode, fromBlock, toBlock));
21198
+ return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock, schema), curry(nestedBlockMerge, rootNode, fromBlock, toBlock, schema));
20975
21199
  };
20976
- const mergeBlocks = (rootNode, forward, block1, block2) => forward ? mergeBlockInto(rootNode, block2, block1) : mergeBlockInto(rootNode, block1, block2);
21200
+ const mergeBlocks = (rootNode, forward, block1, block2, schema) => forward ? mergeBlockInto(rootNode, block2, block1, schema) : mergeBlockInto(rootNode, block1, block2, schema);
20977
21201
 
20978
21202
  const backspaceDelete$9 = (editor, forward) => {
20979
21203
  const rootNode = SugarElement.fromDom(editor.getBody());
20980
21204
  const position = read$1(rootNode.dom, forward, editor.selection.getRng()).map(blockBoundary => () => {
20981
- mergeBlocks(rootNode, forward, blockBoundary.from.block, blockBoundary.to.block).each(pos => {
21205
+ mergeBlocks(rootNode, forward, blockBoundary.from.block, blockBoundary.to.block, editor.schema).each(pos => {
20982
21206
  editor.selection.setRng(pos.toRange());
20983
21207
  });
20984
21208
  });
20985
21209
  return position;
20986
21210
  };
20987
21211
 
20988
- const deleteRangeMergeBlocks = (rootNode, selection) => {
21212
+ const deleteRangeMergeBlocks = (rootNode, selection, schema) => {
20989
21213
  const rng = selection.getRng();
20990
21214
  return lift2(getParentBlock$2(rootNode, SugarElement.fromDom(rng.startContainer)), getParentBlock$2(rootNode, SugarElement.fromDom(rng.endContainer)), (block1, block2) => {
20991
21215
  if (!eq(block1, block2)) {
20992
21216
  return Optional.some(() => {
20993
21217
  rng.deleteContents();
20994
- mergeBlocks(rootNode, true, block1, block2).each(pos => {
21218
+ mergeBlocks(rootNode, true, block1, block2, schema).each(pos => {
20995
21219
  selection.setRng(pos.toRange());
20996
21220
  });
20997
21221
  });
@@ -21020,7 +21244,7 @@
21020
21244
  const deleteRange$2 = editor => {
21021
21245
  const rootNode = SugarElement.fromDom(editor.getBody());
21022
21246
  const rng = editor.selection.getRng();
21023
- return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection);
21247
+ return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection, editor.schema);
21024
21248
  };
21025
21249
  const backspaceDelete$8 = (editor, _forward) => editor.selection.isCollapsed() ? Optional.none() : deleteRange$2(editor);
21026
21250
 
@@ -21127,18 +21351,18 @@
21127
21351
  const caretLocation = forward ? 'after' : 'before';
21128
21352
  return isElement$6(elm) && elm.getAttribute('data-mce-caret') === caretLocation;
21129
21353
  };
21130
- const isDeleteFromCefDifferentBlocks = (root, forward, from, to) => {
21131
- const inSameBlock = elm => isInline$1(SugarElement.fromDom(elm)) && !isInSameBlock(from, to, root);
21354
+ const isDeleteFromCefDifferentBlocks = (root, forward, from, to, schema) => {
21355
+ const inSameBlock = elm => schema.isInline(elm.nodeName.toLowerCase()) && !isInSameBlock(from, to, root);
21132
21356
  return getRelativeCefElm(!forward, from).fold(() => getRelativeCefElm(forward, to).fold(never, inSameBlock), inSameBlock);
21133
21357
  };
21134
21358
  const deleteEmptyBlockOrMoveToCef = (root, forward, from, to) => {
21135
21359
  const toCefElm = to.getNode(!forward);
21136
21360
  return getParentBlock$2(SugarElement.fromDom(root), SugarElement.fromDom(from.getNode())).map(blockElm => isEmpty$2(blockElm) ? DeleteAction.remove(blockElm.dom) : DeleteAction.moveToElement(toCefElm)).orThunk(() => Optional.some(DeleteAction.moveToElement(toCefElm)));
21137
21361
  };
21138
- const findCefPosition = (root, forward, from) => fromPosition(forward, root, from).bind(to => {
21362
+ const findCefPosition = (root, forward, from, schema) => fromPosition(forward, root, from).bind(to => {
21139
21363
  if (isCompoundElement(to.getNode())) {
21140
21364
  return Optional.none();
21141
- } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to)) {
21365
+ } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to, schema)) {
21142
21366
  return Optional.none();
21143
21367
  } else if (forward && isContentEditableFalse$b(to.getNode())) {
21144
21368
  return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
@@ -21170,14 +21394,14 @@
21170
21394
  return Optional.some(DeleteAction.moveToPosition(to));
21171
21395
  }
21172
21396
  });
21173
- const getContentEditableAction = (root, forward, from) => {
21397
+ const getContentEditableAction = (root, forward, from, schema) => {
21174
21398
  if (isAtContentEditableBlockCaret(forward, from)) {
21175
- return getContentEditableBlockAction(forward, from.getNode(!forward)).orThunk(() => findCefPosition(root, forward, from));
21399
+ return getContentEditableBlockAction(forward, from.getNode(!forward)).orThunk(() => findCefPosition(root, forward, from, schema));
21176
21400
  } else {
21177
- return findCefPosition(root, forward, from).bind(deleteAction => skipMoveToActionFromInlineCefToContent(root, from, deleteAction));
21401
+ return findCefPosition(root, forward, from, schema).bind(deleteAction => skipMoveToActionFromInlineCefToContent(root, from, deleteAction));
21178
21402
  }
21179
21403
  };
21180
- const read = (root, forward, rng) => {
21404
+ const read = (root, forward, rng, schema) => {
21181
21405
  const normalizedRange = normalizeRange(forward ? 1 : -1, root, rng);
21182
21406
  const from = CaretPosition.fromRangeStart(normalizedRange);
21183
21407
  const rootElement = SugarElement.fromDom(root);
@@ -21185,12 +21409,12 @@
21185
21409
  return Optional.some(DeleteAction.remove(from.getNode(true)));
21186
21410
  } else if (forward && isBeforeContentEditableFalse(from)) {
21187
21411
  return Optional.some(DeleteAction.remove(from.getNode()));
21188
- } else if (!forward && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from)) {
21189
- return findPreviousBr(rootElement, from).map(br => DeleteAction.remove(br.getNode()));
21190
- } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr$1(rootElement, from)) {
21191
- return findNextBr(rootElement, from).map(br => DeleteAction.remove(br.getNode()));
21412
+ } else if (!forward && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from, schema)) {
21413
+ return findPreviousBr(rootElement, from, schema).map(br => DeleteAction.remove(br.getNode()));
21414
+ } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr$1(rootElement, from, schema)) {
21415
+ return findNextBr(rootElement, from, schema).map(br => DeleteAction.remove(br.getNode()));
21192
21416
  } else {
21193
- return getContentEditableAction(root, forward, from);
21417
+ return getContentEditableAction(root, forward, from, schema);
21194
21418
  }
21195
21419
  };
21196
21420
 
@@ -21211,7 +21435,7 @@
21211
21435
  const getAncestorCe = (editor, node) => Optional.from(getContentEditableRoot$1(editor.getBody(), node));
21212
21436
  const backspaceDeleteCaret = (editor, forward) => {
21213
21437
  const selectedNode = editor.selection.getNode();
21214
- return getAncestorCe(editor, selectedNode).filter(isContentEditableFalse$b).fold(() => read(editor.getBody(), forward, editor.selection.getRng()).map(deleteAction => () => deleteAction.fold(deleteElement$1(editor, forward), moveToElement(editor, forward), moveToPosition(editor))), () => Optional.some(noop));
21438
+ return getAncestorCe(editor, selectedNode).filter(isContentEditableFalse$b).fold(() => read(editor.getBody(), forward, editor.selection.getRng(), editor.schema).map(deleteAction => () => deleteAction.fold(deleteElement$1(editor, forward), moveToElement(editor, forward), moveToPosition(editor))), () => Optional.some(noop));
21215
21439
  };
21216
21440
  const deleteOffscreenSelection = rootElement => {
21217
21441
  each$e(descendants(rootElement, '.mce-offscreen-selection'), remove$5);
@@ -21973,8 +22197,8 @@
21973
22197
  return findIndex$2(parents, pred).fold(constant(parents), index => parents.slice(0, index));
21974
22198
  };
21975
22199
  const hasOnlyOneChild = elm => childNodesCount(elm) === 1;
21976
- const getParentInlinesUntilMultichildInline = editor => getParentsUntil(editor, elm => isBlock$2(elm) || hasMultipleChildren(elm));
21977
- const getParentInlines = editor => getParentsUntil(editor, isBlock$2);
22200
+ const getParentInlinesUntilMultichildInline = editor => getParentsUntil(editor, elm => editor.schema.isBlock(name(elm)) || hasMultipleChildren(elm));
22201
+ const getParentInlines = editor => getParentsUntil(editor, el => editor.schema.isBlock(name(el)));
21978
22202
  const getFormatNodes = (editor, parentInlines) => {
21979
22203
  const isFormatElement$1 = curry(isFormatElement, editor);
21980
22204
  return bind$3(parentInlines, elm => isFormatElement$1(elm) ? [elm.dom] : []);
@@ -22053,8 +22277,8 @@
22053
22277
  }
22054
22278
  };
22055
22279
  const backspaceDelete$3 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$1(editor, forward) : deleteRange$1(editor);
22056
- const hasAncestorInlineCaret = elm => ancestor$1(elm, node => isCaretNode(node.dom), isBlock$2);
22057
- const hasAncestorInlineCaretAtStart = editor => hasAncestorInlineCaret(SugarElement.fromDom(editor.selection.getStart()));
22280
+ const hasAncestorInlineCaret = (elm, schema) => ancestor$1(elm, node => isCaretNode(node.dom), el => schema.isBlock(name(el)));
22281
+ const hasAncestorInlineCaretAtStart = editor => hasAncestorInlineCaret(SugarElement.fromDom(editor.selection.getStart()), editor.schema);
22058
22282
  const requiresRefreshCaretOverride = editor => {
22059
22283
  const rng = editor.selection.getRng();
22060
22284
  return rng.collapsed && (rangeStartsAtTextContainer(rng) || editor.dom.isEmpty(rng.startContainer)) && !hasAncestorInlineCaretAtStart(editor);
@@ -22143,7 +22367,7 @@
22143
22367
  const rng = editor.selection.getRng();
22144
22368
  const pos = CaretPosition.fromRangeStart(rng);
22145
22369
  const block = dom.getParent(rng.startContainer, dom.isBlock);
22146
- if (block !== null && isAtStartOfBlock(SugarElement.fromDom(block), pos)) {
22370
+ if (block !== null && isAtStartOfBlock(SugarElement.fromDom(block), pos, editor.schema)) {
22147
22371
  return Optional.some(() => outdent(editor));
22148
22372
  }
22149
22373
  }
@@ -22165,15 +22389,21 @@
22165
22389
  const deleteCommand = (editor, caret) => {
22166
22390
  const result = findAction(editor, caret, false);
22167
22391
  result.fold(() => {
22168
- execNativeDeleteCommand(editor);
22169
- paddEmptyBody(editor);
22392
+ if (editor.selection.isEditable()) {
22393
+ execNativeDeleteCommand(editor);
22394
+ paddEmptyBody(editor);
22395
+ }
22170
22396
  }, call);
22171
22397
  };
22172
22398
  const forwardDeleteCommand = (editor, caret) => {
22173
22399
  const result = findAction(editor, caret, true);
22174
- result.fold(() => execNativeForwardDeleteCommand(editor), call);
22400
+ result.fold(() => {
22401
+ if (editor.selection.isEditable()) {
22402
+ execNativeForwardDeleteCommand(editor);
22403
+ }
22404
+ }, call);
22175
22405
  };
22176
- const setup$p = (editor, caret) => {
22406
+ const setup$q = (editor, caret) => {
22177
22407
  editor.addCommand('delete', () => {
22178
22408
  deleteCommand(editor, caret);
22179
22409
  });
@@ -22195,7 +22425,7 @@
22195
22425
  const distY = Math.abs(touch.clientY - data.y);
22196
22426
  return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
22197
22427
  };
22198
- const setup$o = editor => {
22428
+ const setup$p = editor => {
22199
22429
  const startData = value$2();
22200
22430
  const longpressFired = Cell(false);
22201
22431
  const debounceLongpress = last$1(e => {
@@ -22253,7 +22483,7 @@
22253
22483
  if (isText$a(node)) {
22254
22484
  return true;
22255
22485
  } else if (isElement$6(node)) {
22256
- return !isBlockElement(schema.getBlockElements(), node) && !isBookmarkNode$1(node) && !isTransparentBlock(schema, node);
22486
+ return !isBlockElement(schema.getBlockElements(), node) && !isBookmarkNode$1(node) && !isTransparentBlock(schema, node) && !isNonHtmlElementRoot(node);
22257
22487
  } else {
22258
22488
  return false;
22259
22489
  }
@@ -22267,8 +22497,8 @@
22267
22497
  if (isText$a(node)) {
22268
22498
  if (node.data.length === 0) {
22269
22499
  return true;
22270
- } else if (/^\s+$/.test(node.data) && (!node.nextSibling || isBlockElement(blockElements, node.nextSibling))) {
22271
- return true;
22500
+ } else if (/^\s+$/.test(node.data)) {
22501
+ return !node.nextSibling || isBlockElement(blockElements, node.nextSibling) || isNonHtmlElementRoot(node.nextSibling);
22272
22502
  }
22273
22503
  }
22274
22504
  return false;
@@ -22336,7 +22566,7 @@
22336
22566
  rng.setEndBefore(br.dom);
22337
22567
  return rng;
22338
22568
  };
22339
- const setup$n = editor => {
22569
+ const setup$o = editor => {
22340
22570
  editor.on('NodeChange', curry(addRootBlocks, editor));
22341
22571
  };
22342
22572
 
@@ -22370,7 +22600,7 @@
22370
22600
  }
22371
22601
  e.content = content;
22372
22602
  };
22373
- const setup$m = editor => {
22603
+ const setup$n = editor => {
22374
22604
  const contentEditableAttrName = 'contenteditable';
22375
22605
  const editClass = ' ' + Tools.trim(getEditableClass(editor)) + ' ';
22376
22606
  const nonEditClass = ' ' + Tools.trim(getNonEditableClass(editor)) + ' ';
@@ -22412,7 +22642,7 @@
22412
22642
  });
22413
22643
  };
22414
22644
 
22415
- const findBlockCaretContainer = editor => descendant(SugarElement.fromDom(editor.getBody()), '*[data-mce-caret]').map(elm => elm.dom).getOrNull();
22645
+ const findBlockCaretContainer = editor => descendant$1(SugarElement.fromDom(editor.getBody()), '*[data-mce-caret]').map(elm => elm.dom).getOrNull();
22416
22646
  const showBlockCaretContainer = (editor, blockCaretContainer) => {
22417
22647
  if (blockCaretContainer.hasAttribute('data-mce-caret')) {
22418
22648
  showCaretContainerBlock(blockCaretContainer);
@@ -22436,7 +22666,7 @@
22436
22666
  editor.undoManager.add();
22437
22667
  }
22438
22668
  };
22439
- const setup$l = editor => {
22669
+ const setup$m = editor => {
22440
22670
  editor.on('keyup compositionstart', curry(handleBlockContainer, editor));
22441
22671
  };
22442
22672
 
@@ -22520,15 +22750,15 @@
22520
22750
  });
22521
22751
 
22522
22752
  const isTarget = node => contains$2(['figcaption'], name(node));
22523
- const getClosestTargetBlock = (pos, root) => {
22753
+ const getClosestTargetBlock = (pos, root, schema) => {
22524
22754
  const isRoot = curry(eq, root);
22525
- return closest$4(SugarElement.fromDom(pos.container()), isBlock$2, isRoot).filter(isTarget);
22755
+ return closest$4(SugarElement.fromDom(pos.container()), el => schema.isBlock(name(el)), isRoot).filter(isTarget);
22526
22756
  };
22527
22757
  const isAtFirstOrLastLine = (root, forward, pos) => forward ? isAtLastLine(root.dom, pos) : isAtFirstLine(root.dom, pos);
22528
22758
  const moveCaretToNewEmptyLine = (editor, forward) => {
22529
22759
  const root = SugarElement.fromDom(editor.getBody());
22530
22760
  const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
22531
- return getClosestTargetBlock(pos, root).exists(() => {
22761
+ return getClosestTargetBlock(pos, root, editor.schema).exists(() => {
22532
22762
  if (isAtFirstOrLastLine(root, forward, pos)) {
22533
22763
  const insertFn = forward ? append$1 : prepend;
22534
22764
  const rng = insertEmptyLine(editor, root, insertFn);
@@ -22828,8 +23058,8 @@
22828
23058
  return tabForward(editor, isRoot, current);
22829
23059
  });
22830
23060
  };
22831
- const tabForward = (editor, isRoot, cell) => tabGo(editor, isRoot, next(cell, isEditable$3));
22832
- const tabBackward = (editor, isRoot, cell) => tabGo(editor, isRoot, prev(cell, isEditable$3));
23061
+ const tabForward = (editor, isRoot, cell) => tabGo(editor, isRoot, next(cell, isEditable$2));
23062
+ const tabBackward = (editor, isRoot, cell) => tabGo(editor, isRoot, prev(cell, isEditable$2));
22833
23063
  const handleTab = (editor, forward) => {
22834
23064
  const rootElements = [
22835
23065
  'table',
@@ -22966,7 +23196,7 @@
22966
23196
  evt.preventDefault();
22967
23197
  });
22968
23198
  };
22969
- const setup$k = (editor, caret) => {
23199
+ const setup$l = (editor, caret) => {
22970
23200
  editor.on('keydown', evt => {
22971
23201
  if (!evt.isDefaultPrevented()) {
22972
23202
  executeKeydownOverride$4(editor, caret, evt);
@@ -23597,7 +23827,7 @@
23597
23827
  });
23598
23828
  editor.on('remove', update.cancel);
23599
23829
  };
23600
- const setup$j = editor => {
23830
+ const setup$k = editor => {
23601
23831
  const activeAutocompleter = value$2();
23602
23832
  const uiActive = Cell(false);
23603
23833
  const isActive = activeAutocompleter.isSet;
@@ -23785,7 +24015,7 @@
23785
24015
  const node = selection.getNode();
23786
24016
  const rng = selection.getRng();
23787
24017
  const caretPos = CaretPosition.fromRangeStart(rng);
23788
- if (isSummary(node)) {
24018
+ if (isSummary$1(node)) {
23789
24019
  if (granularity === 'selection' && isEntireNodeSelected(rng, node) || willDeleteLastPositionInElement(forward, caretPos, node)) {
23790
24020
  emptyNodeContents(node);
23791
24021
  } else {
@@ -24040,7 +24270,7 @@
24040
24270
  }
24041
24271
  ]
24042
24272
  ], evt);
24043
- const setup$i = (editor, caret) => {
24273
+ const setup$j = (editor, caret) => {
24044
24274
  let isBackspaceKeydown = false;
24045
24275
  editor.on('keydown', evt => {
24046
24276
  isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
@@ -24181,7 +24411,7 @@
24181
24411
  applyAttributes(editor, node, forcedRootBlockAttrs);
24182
24412
  }
24183
24413
  };
24184
- const createNewBlock = (editor, container, parentBlock, editableRoot, keepStyles = true, name) => {
24414
+ const createNewBlock = (editor, container, parentBlock, editableRoot, keepStyles = true, name, styles) => {
24185
24415
  const dom = editor.dom;
24186
24416
  const schema = editor.schema;
24187
24417
  const newBlockName = getForcedRootBlock(editor);
@@ -24190,7 +24420,7 @@
24190
24420
  const textInlineElements = schema.getTextInlineElements();
24191
24421
  let block;
24192
24422
  if (name || parentBlockName === 'TABLE' || parentBlockName === 'HR') {
24193
- block = dom.create(name || newBlockName);
24423
+ block = dom.create(name || newBlockName, styles || {});
24194
24424
  } else {
24195
24425
  block = parentBlock.cloneNode(false);
24196
24426
  }
@@ -24282,6 +24512,7 @@
24282
24512
  }
24283
24513
  return node === parentBlock;
24284
24514
  };
24515
+ const getStyles = elm => foldl(mapToArray(getAllRaw(SugarElement.fromDom(elm)), (style, styleName) => `${ styleName }: ${ style };`), (acc, s) => acc + s, '');
24285
24516
  const insert$4 = (editor, createNewBlock, containerBlock, parentBlock, newBlockName) => {
24286
24517
  const dom = editor.dom;
24287
24518
  const rng = editor.selection.getRng();
@@ -24292,7 +24523,8 @@
24292
24523
  if (isNestedList(containerBlock)) {
24293
24524
  newBlockName = 'LI';
24294
24525
  }
24295
- let newBlock = createNewBlock(newBlockName);
24526
+ const parentBlockStyles = isListItem(parentBlock) ? getStyles(parentBlock) : undefined;
24527
+ let newBlock = isListItem(parentBlock) && parentBlockStyles ? createNewBlock(newBlockName, { style: getStyles(parentBlock) }) : createNewBlock(newBlockName);
24296
24528
  if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) {
24297
24529
  if (hasParent(containerBlock, 'LI')) {
24298
24530
  const containerBlockParent = getContainerBlock(containerBlock);
@@ -24324,8 +24556,13 @@
24324
24556
  tmpRng.setEndAfter(containerBlock);
24325
24557
  const fragment = tmpRng.extractContents();
24326
24558
  if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) {
24559
+ const previousChildren = filter$5(map$3(newBlock.children, SugarElement.fromDom), not(isTag('br')));
24327
24560
  newBlock = fragment.firstChild;
24328
24561
  dom.insertAfter(fragment, containerBlock);
24562
+ each$e(previousChildren, child => prepend(SugarElement.fromDom(newBlock), child));
24563
+ if (parentBlockStyles) {
24564
+ newBlock.setAttribute('style', parentBlockStyles);
24565
+ }
24329
24566
  } else {
24330
24567
  dom.insertAfter(fragment, containerBlock);
24331
24568
  dom.insertAfter(newBlock, containerBlock);
@@ -24476,10 +24713,10 @@
24476
24713
  const newBlockName = getForcedRootBlock(editor);
24477
24714
  const start = SugarElement.fromDom(rng.startContainer);
24478
24715
  const child = child$1(start, rng.startOffset);
24479
- const isCef = child.exists(element => isHTMLElement(element) && !isEditable$3(element));
24716
+ const isCef = child.exists(element => isHTMLElement$1(element) && !isEditable$2(element));
24480
24717
  const collapsedAndCef = rng.collapsed && isCef;
24481
- const createNewBlock$1 = name => {
24482
- return createNewBlock(editor, container, parentBlock, editableRoot, shouldKeepStyles(editor), name);
24718
+ const createNewBlock$1 = (name, styles) => {
24719
+ return createNewBlock(editor, container, parentBlock, editableRoot, shouldKeepStyles(editor), name, styles);
24483
24720
  };
24484
24721
  const isCaretAtStartOrEndOfBlock = start => {
24485
24722
  const normalizedOffset = normalizeZwspOffset(start, container, offset);
@@ -24812,7 +25049,7 @@
24812
25049
  const rng = editor.selection.getRng();
24813
25050
  const start = SugarElement.fromDom(rng.startContainer);
24814
25051
  const child = child$1(start, rng.startOffset);
24815
- const isCefOpt = child.map(element => isHTMLElement(element) && !isEditable$3(element));
25052
+ const isCefOpt = child.map(element => isHTMLElement$1(element) && !isEditable$2(element));
24816
25053
  return rng.collapsed && isCefOpt.getOr(true);
24817
25054
  };
24818
25055
  const match = (predicates, action) => {
@@ -24924,7 +25161,7 @@
24924
25161
  return false;
24925
25162
  }
24926
25163
  };
24927
- const setup$h = editor => {
25164
+ const setup$i = editor => {
24928
25165
  let iOSSafariKeydownBookmark = Optional.none();
24929
25166
  const iOSSafariKeydownOverride = editor => {
24930
25167
  iOSSafariKeydownBookmark = Optional.some(editor.selection.getBookmark());
@@ -24997,7 +25234,7 @@
24997
25234
  evt.preventDefault();
24998
25235
  });
24999
25236
  };
25000
- const setup$g = (editor, caret) => {
25237
+ const setup$h = (editor, caret) => {
25001
25238
  editor.on('keydown', evt => {
25002
25239
  if (!evt.isDefaultPrevented()) {
25003
25240
  executeKeydownOverride$2(editor, caret, evt);
@@ -25005,7 +25242,7 @@
25005
25242
  });
25006
25243
  };
25007
25244
 
25008
- const setup$f = editor => {
25245
+ const setup$g = editor => {
25009
25246
  editor.on('input', e => {
25010
25247
  if (!e.isComposing) {
25011
25248
  normalizeNbspsInEditor(editor);
@@ -25036,7 +25273,7 @@
25036
25273
  }
25037
25274
  blocked.set(block);
25038
25275
  };
25039
- const setup$e = (editor, caret) => {
25276
+ const setup$f = (editor, caret) => {
25040
25277
  if (platform.os.isMacOS()) {
25041
25278
  return;
25042
25279
  }
@@ -25057,6 +25294,14 @@
25057
25294
  });
25058
25295
  };
25059
25296
 
25297
+ const setup$e = editor => {
25298
+ editor.on('beforeinput', e => {
25299
+ if (!editor.selection.isEditable() || exists(e.getTargetRanges(), rng => !isEditableRange(editor.dom, rng))) {
25300
+ e.preventDefault();
25301
+ }
25302
+ });
25303
+ };
25304
+
25060
25305
  const insertTextAtPosition = (text, pos) => {
25061
25306
  const container = pos.container();
25062
25307
  const offset = pos.offset();
@@ -25078,9 +25323,9 @@
25078
25323
  const insertNbspAtPosition = curry(insertTextAtPosition, nbsp);
25079
25324
  const insertSpaceAtPosition = curry(insertTextAtPosition, ' ');
25080
25325
 
25081
- const insertSpaceOrNbspAtPosition = (root, pos) => needsToHaveNbsp(root, pos) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25326
+ const insertSpaceOrNbspAtPosition = (root, pos, schema) => needsToHaveNbsp(root, pos, schema) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25082
25327
  const locationToCaretPosition = root => location => location.fold(element => prevPosition(root.dom, CaretPosition.before(element)), element => firstPositionIn(element), element => lastPositionIn(element), element => nextPosition(root.dom, CaretPosition.after(element)));
25083
- const insertInlineBoundarySpaceOrNbsp = (root, pos) => checkPos => needsToHaveNbsp(root, checkPos) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25328
+ const insertInlineBoundarySpaceOrNbsp = (root, pos, schema) => checkPos => needsToHaveNbsp(root, checkPos, schema) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25084
25329
  const setSelection = editor => pos => {
25085
25330
  editor.selection.setRng(pos.toRange());
25086
25331
  editor.nodeChanged();
@@ -25092,7 +25337,7 @@
25092
25337
  if (editor.selection.isCollapsed()) {
25093
25338
  const isInlineTarget$1 = curry(isInlineTarget, editor);
25094
25339
  const caretPosition = CaretPosition.fromRangeStart(editor.selection.getRng());
25095
- return readLocation(isInlineTarget$1, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).map(checkPos => () => insertInlineBoundarySpaceOrNbsp(root, pos)(checkPos).each(setSelection(editor)));
25340
+ return readLocation(isInlineTarget$1, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).map(checkPos => () => insertInlineBoundarySpaceOrNbsp(root, pos, editor.schema)(checkPos).each(setSelection(editor)));
25096
25341
  } else {
25097
25342
  return Optional.none();
25098
25343
  }
@@ -25104,7 +25349,7 @@
25104
25349
  editor.getDoc().execCommand('Delete');
25105
25350
  }
25106
25351
  const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
25107
- insertSpaceOrNbspAtPosition(root, pos).each(setSelection(editor));
25352
+ insertSpaceOrNbspAtPosition(root, pos, editor.schema).each(setSelection(editor));
25108
25353
  };
25109
25354
  return someIf(Env.browser.isFirefox() && editor.selection.isEditable() && isInsideSummary(editor.dom, editor.selection.getRng().startContainer), insertSpaceThunk);
25110
25355
  };
@@ -25168,20 +25413,21 @@
25168
25413
 
25169
25414
  const setup$b = editor => {
25170
25415
  editor.addShortcut('Meta+P', '', 'mcePrint');
25171
- setup$j(editor);
25416
+ setup$k(editor);
25172
25417
  if (isRtc(editor)) {
25173
25418
  return Cell(null);
25174
25419
  } else {
25175
25420
  const caret = setupSelectedState(editor);
25176
- setup$l(editor);
25177
- setup$k(editor, caret);
25178
- setup$i(editor, caret);
25179
- setup$h(editor);
25421
+ setup$e(editor);
25422
+ setup$m(editor);
25423
+ setup$l(editor, caret);
25424
+ setup$j(editor, caret);
25425
+ setup$i(editor);
25180
25426
  setup$d(editor);
25181
- setup$f(editor);
25427
+ setup$g(editor);
25182
25428
  setup$c(editor);
25183
- setup$g(editor, caret);
25184
- setup$e(editor, caret);
25429
+ setup$h(editor, caret);
25430
+ setup$f(editor, caret);
25185
25431
  return caret;
25186
25432
  }
25187
25433
  };
@@ -25666,7 +25912,10 @@
25666
25912
  };
25667
25913
 
25668
25914
  const preProcess = (editor, html) => {
25669
- const parser = DomParser({ sanitize: shouldSanitizeXss(editor) }, editor.schema);
25915
+ const parser = DomParser({
25916
+ sanitize: shouldSanitizeXss(editor),
25917
+ sandbox_iframes: shouldSandboxIframes(editor)
25918
+ }, editor.schema);
25670
25919
  parser.addNodeFilter('meta', nodes => {
25671
25920
  Tools.each(nodes, node => {
25672
25921
  node.remove();
@@ -26028,7 +26277,7 @@
26028
26277
  const isTableSelection = editor => !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody());
26029
26278
  const hasSelectedContent = editor => !editor.selection.isCollapsed() || isTableSelection(editor);
26030
26279
  const cut = editor => evt => {
26031
- if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) {
26280
+ if (!evt.isDefaultPrevented() && hasSelectedContent(editor) && editor.selection.isEditable()) {
26032
26281
  setClipboardData(evt, getData(editor), fallback(editor), () => {
26033
26282
  if (Env.browser.isChromium() || Env.browser.isFirefox()) {
26034
26283
  const rng = editor.selection.getRng();
@@ -26280,7 +26529,7 @@
26280
26529
  const isContentEditableFalse$2 = elm => isContentEditableFalse$b(elm.dom);
26281
26530
  const isContentEditableTrue = elm => isContentEditableTrue$3(elm.dom);
26282
26531
  const isRoot = rootNode => elm => eq(SugarElement.fromDom(rootNode), elm);
26283
- const getClosestScope = (node, rootNode) => closest$4(SugarElement.fromDom(node), elm => isContentEditableTrue(elm) || isBlock$2(elm), isRoot(rootNode)).getOr(SugarElement.fromDom(rootNode)).dom;
26532
+ const getClosestScope = (node, rootNode, schema) => closest$4(SugarElement.fromDom(node), elm => isContentEditableTrue(elm) || schema.isBlock(name(elm)), isRoot(rootNode)).getOr(SugarElement.fromDom(rootNode)).dom;
26284
26533
  const getClosestCef = (node, rootNode) => closest$4(SugarElement.fromDom(node), isContentEditableFalse$2, isRoot(rootNode));
26285
26534
  const findEdgeCaretCandidate = (startNode, scope, forward) => {
26286
26535
  const walker = new DomTreeWalker(startNode, scope);
@@ -26293,10 +26542,10 @@
26293
26542
  }
26294
26543
  return result;
26295
26544
  };
26296
- const findClosestBlockRange = (startRng, rootNode) => {
26545
+ const findClosestBlockRange = (startRng, rootNode, schema) => {
26297
26546
  const startPos = CaretPosition.fromRangeStart(startRng);
26298
26547
  const clickNode = startPos.getNode();
26299
- const scope = getClosestScope(clickNode, rootNode);
26548
+ const scope = getClosestScope(clickNode, rootNode, schema);
26300
26549
  const startNode = findEdgeCaretCandidate(clickNode, scope, false);
26301
26550
  const endNode = findEdgeCaretCandidate(clickNode, scope, true);
26302
26551
  const rng = document.createRange();
@@ -26317,7 +26566,7 @@
26317
26566
  return rng;
26318
26567
  };
26319
26568
  const onTripleClickSelect = editor => {
26320
- const rng = findClosestBlockRange(editor.selection.getRng(), editor.getBody());
26569
+ const rng = findClosestBlockRange(editor.selection.getRng(), editor.getBody(), editor.schema);
26321
26570
  editor.selection.setRng(normalize(rng));
26322
26571
  };
26323
26572
  const setup$5 = editor => {
@@ -26978,7 +27227,7 @@
26978
27227
  e.preventDefault();
26979
27228
  const range = showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false);
26980
27229
  setRange(range);
26981
- if (isElement$6(closestContentEditable)) {
27230
+ if (isHTMLElement(closestContentEditable)) {
26982
27231
  closestContentEditable.focus();
26983
27232
  } else {
26984
27233
  editor.getBody().focus();
@@ -27060,7 +27309,7 @@
27060
27309
  const setupOffscreenSelection = (node, targetClone) => {
27061
27310
  const body = SugarElement.fromDom(editor.getBody());
27062
27311
  const doc = editor.getDoc();
27063
- const realSelectionContainer = descendant(body, '#' + realSelectionId).getOrThunk(() => {
27312
+ const realSelectionContainer = descendant$1(body, '#' + realSelectionId).getOrThunk(() => {
27064
27313
  const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc);
27065
27314
  set$3(newContainer, 'id', realSelectionId);
27066
27315
  append$1(body, newContainer);
@@ -27165,7 +27414,7 @@
27165
27414
  if (selectedElement) {
27166
27415
  selectedElement.removeAttribute(elementSelectionAttr);
27167
27416
  }
27168
- descendant(SugarElement.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$5);
27417
+ descendant$1(SugarElement.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$5);
27169
27418
  selectedElement = null;
27170
27419
  };
27171
27420
  const destroy = () => {
@@ -27616,7 +27865,7 @@
27616
27865
  editor.undoManager.extra(() => {
27617
27866
  editor.execCommand('mceInsertNewLine');
27618
27867
  }, () => {
27619
- editor.insertContent(zeroWidth);
27868
+ insert$5(editor);
27620
27869
  applyMatches(editor, inlineMatches);
27621
27870
  applyMatches$1(editor, blockMatches);
27622
27871
  const range = editor.selection.getRng();
@@ -27741,17 +27990,12 @@
27741
27990
  const allSelection = serializeRng(allRng);
27742
27991
  return selection === allSelection;
27743
27992
  };
27744
- const hasPreservedEmptyElements = elm => {
27745
- const scope = SugarElement.fromDom(elm);
27746
- const isEditableHost = elm => parentElement(elm).exists(elm => !isEditable$3(elm));
27747
- return exists(descendants(scope, '[contenteditable="true"]'), isEditableHost);
27748
- };
27749
27993
  editor.on('keydown', e => {
27750
27994
  const keyCode = e.keyCode;
27751
27995
  if (!isDefaultPrevented(e) && (keyCode === DELETE || keyCode === BACKSPACE) && editor.selection.isEditable()) {
27752
27996
  const isCollapsed = editor.selection.isCollapsed();
27753
27997
  const body = editor.getBody();
27754
- if (isCollapsed && (!dom.isEmpty(body) || hasPreservedEmptyElements(body))) {
27998
+ if (isCollapsed && !isEmpty$2(SugarElement.fromDom(body))) {
27755
27999
  return;
27756
28000
  }
27757
28001
  if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
@@ -27829,7 +28073,7 @@
27829
28073
  const visualAidsAnchorClass = getVisualAidsAnchorClass(editor);
27830
28074
  editor.on('click', e => {
27831
28075
  const target = e.target;
27832
- if (/^(IMG|HR)$/.test(target.nodeName) && dom.isEditable(target.parentNode)) {
28076
+ if (/^(IMG|HR)$/.test(target.nodeName) && dom.isEditable(target)) {
27833
28077
  e.preventDefault();
27834
28078
  editor.selection.select(target);
27835
28079
  editor.nodeChanged();
@@ -28139,6 +28383,7 @@
28139
28383
  allow_html_in_named_anchor: getOption('allow_html_in_named_anchor'),
28140
28384
  allow_script_urls: getOption('allow_script_urls'),
28141
28385
  allow_unsafe_link_target: getOption('allow_unsafe_link_target'),
28386
+ convert_unsafe_embeds: getOption('convert_unsafe_embeds'),
28142
28387
  convert_fonts_to_spans: getOption('convert_fonts_to_spans'),
28143
28388
  fix_list_elements: getOption('fix_list_elements'),
28144
28389
  font_size_legacy_values: getOption('font_size_legacy_values'),
@@ -28147,6 +28392,7 @@
28147
28392
  preserve_cdata: getOption('preserve_cdata'),
28148
28393
  inline_styles: getOption('inline_styles'),
28149
28394
  root_name: getRootName(editor),
28395
+ sandbox_iframes: getOption('sandbox_iframes'),
28150
28396
  sanitize: getOption('xss_sanitization'),
28151
28397
  validate: true,
28152
28398
  blob_cache: blobCache,
@@ -28293,7 +28539,21 @@
28293
28539
  };
28294
28540
  const getStyleSheetLoader$1 = editor => editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader;
28295
28541
  const makeStylesheetLoadingPromises = (editor, css, framedFonts) => {
28296
- const promises = [getStyleSheetLoader$1(editor).loadAll(css)];
28542
+ const {
28543
+ pass: bundledCss,
28544
+ fail: normalCss
28545
+ } = partition$2(css, name => tinymce.Resource.has(toContentSkinResourceName(name)));
28546
+ const bundledPromises = bundledCss.map(url => {
28547
+ const css = tinymce.Resource.get(toContentSkinResourceName(url));
28548
+ if (isString(css)) {
28549
+ return Promise.resolve(getStyleSheetLoader$1(editor).loadRawCss(url, css));
28550
+ }
28551
+ return Promise.resolve();
28552
+ });
28553
+ const promises = [
28554
+ ...bundledPromises,
28555
+ getStyleSheetLoader$1(editor).loadAll(normalCss)
28556
+ ];
28297
28557
  if (editor.inline) {
28298
28558
  return promises;
28299
28559
  } else {
@@ -28424,7 +28684,8 @@
28424
28684
  referrerPolicy: getReferrerPolicy(editor),
28425
28685
  onSetAttrib: e => {
28426
28686
  editor.dispatch('SetAttrib', e);
28427
- }
28687
+ },
28688
+ force_hex_color: shouldForceHexColor(editor)
28428
28689
  });
28429
28690
  editor.parser = createParser(editor);
28430
28691
  editor.serializer = DomSerializer(mkSerializerSettings(editor), editor);
@@ -28434,19 +28695,19 @@
28434
28695
  editor.undoManager = UndoManager(editor);
28435
28696
  editor._nodeChangeDispatcher = new NodeChange(editor);
28436
28697
  editor._selectionOverrides = SelectionOverrides(editor);
28437
- setup$o(editor);
28698
+ setup$p(editor);
28438
28699
  setup$6(editor);
28439
- setup$m(editor);
28700
+ setup$n(editor);
28440
28701
  if (!isRtc(editor)) {
28441
28702
  setup$5(editor);
28442
28703
  setup$1(editor);
28443
28704
  }
28444
28705
  const caret = setup$b(editor);
28445
- setup$p(editor, caret);
28446
- setup$n(editor);
28447
- setup$q(editor);
28706
+ setup$q(editor, caret);
28707
+ setup$o(editor);
28708
+ setup$r(editor);
28448
28709
  setup$7(editor);
28449
- const setupRtcThunk = setup$s(editor);
28710
+ const setupRtcThunk = setup$t(editor);
28450
28711
  preInit(editor);
28451
28712
  setupRtcThunk.fold(() => {
28452
28713
  const cancelProgress = startProgress(editor);
@@ -28806,7 +29067,7 @@
28806
29067
  setAll$1(element, snapshot);
28807
29068
  });
28808
29069
  editor.ui.styleSheetLoader = getStyleSheetLoader(element, editor);
28809
- if (!isInline(editor)) {
29070
+ if (!isInline$1(editor)) {
28810
29071
  editor.orgVisibility = editor.getElement().style.visibility;
28811
29072
  editor.getElement().style.visibility = 'hidden';
28812
29073
  } else {
@@ -29043,14 +29304,14 @@
29043
29304
  });
29044
29305
  };
29045
29306
 
29046
- const trimOrPadLeftRight = (dom, rng, html) => {
29307
+ const trimOrPadLeftRight = (dom, rng, html, schema) => {
29047
29308
  const root = SugarElement.fromDom(dom.getRoot());
29048
- if (needsToBeNbspLeft(root, CaretPosition.fromRangeStart(rng))) {
29309
+ if (needsToBeNbspLeft(root, CaretPosition.fromRangeStart(rng), schema)) {
29049
29310
  html = html.replace(/^ /, '&nbsp;');
29050
29311
  } else {
29051
29312
  html = html.replace(/^&nbsp;/, ' ');
29052
29313
  }
29053
- if (needsToBeNbspRight(root, CaretPosition.fromRangeEnd(rng))) {
29314
+ if (needsToBeNbspRight(root, CaretPosition.fromRangeEnd(rng), schema)) {
29054
29315
  html = html.replace(/(&nbsp;| )(<br( \/)>)?$/, '&nbsp;');
29055
29316
  } else {
29056
29317
  html = html.replace(/&nbsp;(<br( \/)?>)?$/, ' ');
@@ -29078,7 +29339,7 @@
29078
29339
  const selection = editor.selection;
29079
29340
  const dom = editor.dom;
29080
29341
  if (/^ | $/.test(value)) {
29081
- return trimOrPadLeftRight(dom, selection.getRng(), value);
29342
+ return trimOrPadLeftRight(dom, selection.getRng(), value, editor.schema);
29082
29343
  } else {
29083
29344
  return value;
29084
29345
  }
@@ -30504,7 +30765,7 @@
30504
30765
  this.setDirty(false);
30505
30766
  this.documentBaseURI = new URI(getDocumentBaseUrl(self), { base_uri: this.baseUri });
30506
30767
  this.baseURI = this.baseUri;
30507
- this.inline = isInline(self);
30768
+ this.inline = isInline$1(self);
30508
30769
  this.hasVisual = isVisualAidsEnabled(self);
30509
30770
  this.shortcuts = new Shortcuts(this);
30510
30771
  this.editorCommands = new EditorCommands(this);
@@ -30785,6 +31046,10 @@
30785
31046
  if (!getOption('convert_urls') || elm === 'link' || isObject(elm) && elm.nodeName === 'LINK' || url.indexOf('file:') === 0 || url.length === 0) {
30786
31047
  return url;
30787
31048
  }
31049
+ const urlObject = new URI(url);
31050
+ if (urlObject.protocol !== 'http' && urlObject.protocol !== 'https' && urlObject.protocol !== '') {
31051
+ return url;
31052
+ }
30788
31053
  if (getOption('relative_urls')) {
30789
31054
  return self.documentBaseURI.toRelative(url);
30790
31055
  }
@@ -30875,8 +31140,8 @@
30875
31140
  documentBaseURL: null,
30876
31141
  suffix: null,
30877
31142
  majorVersion: '6',
30878
- minorVersion: '7.2',
30879
- releaseDate: '2023-10-25',
31143
+ minorVersion: '8.1',
31144
+ releaseDate: '2023-11-29',
30880
31145
  i18n: I18n,
30881
31146
  activeEditor: null,
30882
31147
  focusedEditor: null,
@@ -30923,7 +31188,7 @@
30923
31188
  self.documentBaseURL = documentBaseURL;
30924
31189
  self.baseURI = new URI(self.baseURL);
30925
31190
  self.suffix = suffix;
30926
- setup$v(self);
31191
+ setup$w(self);
30927
31192
  },
30928
31193
  overrideDefaults(defaultOptions) {
30929
31194
  const baseUrl = defaultOptions.base_url;
@@ -31317,6 +31582,7 @@
31317
31582
  const create$1 = () => {
31318
31583
  const tasks = {};
31319
31584
  const resultFns = {};
31585
+ const resources = {};
31320
31586
  const load = (id, url) => {
31321
31587
  const loadErrMsg = `Script at URL "${ url }" failed to load`;
31322
31588
  const runErrMsg = `Script at URL "${ url }" did not call \`tinymce.Resource.add('${ id }', data)\` within 1 second`;
@@ -31338,13 +31604,20 @@
31338
31604
  delete resultFns[id];
31339
31605
  }
31340
31606
  tasks[id] = Promise.resolve(data);
31607
+ resources[id] = data;
31608
+ };
31609
+ const has = id => {
31610
+ return id in resources;
31341
31611
  };
31342
31612
  const unload = id => {
31343
31613
  delete tasks[id];
31344
31614
  };
31615
+ const get = id => resources[id];
31345
31616
  return {
31346
31617
  load,
31347
31618
  add,
31619
+ has,
31620
+ get,
31348
31621
  unload
31349
31622
  };
31350
31623
  };
@@ -31466,7 +31739,7 @@
31466
31739
  explode: Tools.explode,
31467
31740
  _addCacheSuffix: Tools._addCacheSuffix
31468
31741
  };
31469
- const tinymce = Tools.extend(EditorManager, publicApi);
31742
+ const tinymce$1 = Tools.extend(EditorManager, publicApi);
31470
31743
 
31471
31744
  const exportToModuleLoaders = tinymce => {
31472
31745
  if (typeof module === 'object') {
@@ -31480,7 +31753,7 @@
31480
31753
  window.tinymce = tinymce;
31481
31754
  window.tinyMCE = tinymce;
31482
31755
  };
31483
- exportToWindowGlobal(tinymce);
31484
- exportToModuleLoaders(tinymce);
31756
+ exportToWindowGlobal(tinymce$1);
31757
+ exportToModuleLoaders(tinymce$1);
31485
31758
 
31486
31759
  })();