tinymce-rails 7.5.1 → 7.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/source/tinymce/tinymce.js +1803 -1597
  3. data/lib/tinymce/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/tinymce/icons/default/icons.js +1 -1
  5. data/vendor/assets/javascripts/tinymce/models/dom/model.js +2 -2
  6. data/vendor/assets/javascripts/tinymce/plugins/accordion/plugin.js +1 -1
  7. data/vendor/assets/javascripts/tinymce/plugins/advlist/plugin.js +2 -2
  8. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.js +1 -1
  9. data/vendor/assets/javascripts/tinymce/plugins/autolink/plugin.js +1 -1
  10. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.js +1 -1
  11. data/vendor/assets/javascripts/tinymce/plugins/autosave/plugin.js +1 -1
  12. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.js +1 -1
  13. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.js +1 -1
  14. data/vendor/assets/javascripts/tinymce/plugins/codesample/plugin.js +1 -1
  15. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.js +1 -1
  16. data/vendor/assets/javascripts/tinymce/plugins/emoticons/plugin.js +1 -1
  17. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.js +1 -1
  18. data/vendor/assets/javascripts/tinymce/plugins/help/plugin.js +2 -2
  19. data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +1 -1
  20. data/vendor/assets/javascripts/tinymce/plugins/importcss/plugin.js +1 -1
  21. data/vendor/assets/javascripts/tinymce/plugins/insertdatetime/plugin.js +1 -1
  22. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.js +1 -1
  23. data/vendor/assets/javascripts/tinymce/plugins/lists/plugin.js +1 -1
  24. data/vendor/assets/javascripts/tinymce/plugins/media/plugin.js +1 -1
  25. data/vendor/assets/javascripts/tinymce/plugins/nonbreaking/plugin.js +1 -1
  26. data/vendor/assets/javascripts/tinymce/plugins/pagebreak/plugin.js +1 -1
  27. data/vendor/assets/javascripts/tinymce/plugins/preview/plugin.js +1 -1
  28. data/vendor/assets/javascripts/tinymce/plugins/quickbars/plugin.js +2 -2
  29. data/vendor/assets/javascripts/tinymce/plugins/save/plugin.js +1 -1
  30. data/vendor/assets/javascripts/tinymce/plugins/searchreplace/plugin.js +1 -1
  31. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
  32. data/vendor/assets/javascripts/tinymce/plugins/visualblocks/plugin.js +1 -1
  33. data/vendor/assets/javascripts/tinymce/plugins/visualchars/plugin.js +1 -1
  34. data/vendor/assets/javascripts/tinymce/plugins/wordcount/plugin.js +1 -1
  35. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.css +1 -1
  36. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.css +1 -1
  37. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.js +1 -1
  38. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.min.css +1 -1
  39. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.js +1 -1
  40. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.min.css +1 -1
  41. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.css +1 -1
  42. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.js +1 -1
  43. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.min.css +1 -1
  44. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.shadowdom.js +1 -1
  45. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.css +1 -1
  46. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.css +1 -1
  47. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.js +1 -1
  48. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.min.css +1 -1
  49. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.js +1 -1
  50. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.min.css +1 -1
  51. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.css +1 -1
  52. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.js +1 -1
  53. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.min.css +1 -1
  54. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.shadowdom.js +1 -1
  55. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.css +1 -1
  56. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.css +1 -1
  57. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.js +1 -1
  58. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.min.css +1 -1
  59. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.js +1 -1
  60. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.min.css +1 -1
  61. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.css +1 -1
  62. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.js +1 -1
  63. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.min.css +1 -1
  64. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.css +1 -1
  65. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.css +1 -1
  66. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.js +1 -1
  67. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css +1 -1
  68. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.js +1 -1
  69. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.min.css +1 -1
  70. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.css +1 -1
  71. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.js +1 -1
  72. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.min.css +1 -1
  73. data/vendor/assets/javascripts/tinymce/themes/silver/theme.js +68 -68
  74. data/vendor/assets/javascripts/tinymce/tinymce.d.ts +51 -15
  75. data/vendor/assets/javascripts/tinymce/tinymce.js +57 -57
  76. metadata +5 -5
@@ -1,5 +1,5 @@
1
1
  /**
2
- * TinyMCE version 7.5.1 (TBD)
2
+ * TinyMCE version 7.6.0 (2024-12-11)
3
3
  */
4
4
 
5
5
  (function () {
@@ -1178,7 +1178,7 @@
1178
1178
  throw new Error('Attribute value was not simple');
1179
1179
  }
1180
1180
  };
1181
- const set$3 = (element, key, value) => {
1181
+ const set$4 = (element, key, value) => {
1182
1182
  rawSet(element.dom, key, value);
1183
1183
  };
1184
1184
  const setAll$1 = (element, attrs) => {
@@ -1215,13 +1215,13 @@
1215
1215
  const add$4 = (element, attr, id) => {
1216
1216
  const old = read$4(element, attr);
1217
1217
  const nu = old.concat([id]);
1218
- set$3(element, attr, nu.join(' '));
1218
+ set$4(element, attr, nu.join(' '));
1219
1219
  return true;
1220
1220
  };
1221
1221
  const remove$8 = (element, attr, id) => {
1222
1222
  const nu = filter$5(read$4(element, attr), v => v !== id);
1223
1223
  if (nu.length > 0) {
1224
- set$3(element, attr, nu.join(' '));
1224
+ set$4(element, attr, nu.join(' '));
1225
1225
  } else {
1226
1226
  remove$9(element, attr);
1227
1227
  }
@@ -1508,6 +1508,9 @@
1508
1508
  }
1509
1509
  };
1510
1510
  const getRaw$1 = element => element.dom.contentEditable;
1511
+ const set$3 = (element, editable) => {
1512
+ element.dom.contentEditable = editable ? 'true' : 'false';
1513
+ };
1511
1514
 
1512
1515
  const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
1513
1516
 
@@ -2426,16 +2429,16 @@
2426
2429
  id: state.id
2427
2430
  });
2428
2431
  if (settings.contentCssCors) {
2429
- set$3(linkElem, 'crossOrigin', 'anonymous');
2432
+ set$4(linkElem, 'crossOrigin', 'anonymous');
2430
2433
  }
2431
2434
  if (settings.referrerPolicy) {
2432
- set$3(linkElem, 'referrerpolicy', settings.referrerPolicy);
2435
+ set$4(linkElem, 'referrerpolicy', settings.referrerPolicy);
2433
2436
  }
2434
2437
  link = linkElem.dom;
2435
2438
  link.onload = passed;
2436
2439
  link.onerror = failed;
2437
2440
  addStyle(linkElem);
2438
- set$3(linkElem, 'href', urlWithSuffix);
2441
+ set$4(linkElem, 'href', urlWithSuffix);
2439
2442
  });
2440
2443
  const loadRawCss = (key, css) => {
2441
2444
  const state = getOrCreateState(key);
@@ -2443,9 +2446,10 @@
2443
2446
  state.count++;
2444
2447
  const styleElem = SugarElement.fromTag('style', doc.dom);
2445
2448
  setAll$1(styleElem, {
2446
- rel: 'stylesheet',
2447
- type: 'text/css',
2448
- id: state.id
2449
+ 'rel': 'stylesheet',
2450
+ 'type': 'text/css',
2451
+ 'id': state.id,
2452
+ 'data-mce-key': key
2449
2453
  });
2450
2454
  styleElem.dom.innerHTML = css;
2451
2455
  addStyle(styleElem);
@@ -4148,7 +4152,7 @@
4148
4152
  if (isNullable(value) || value === '') {
4149
4153
  remove$9(elm, name);
4150
4154
  } else {
4151
- set$3(elm, name, value);
4155
+ set$4(elm, name, value);
4152
4156
  }
4153
4157
  };
4154
4158
  const camelCaseToHyphens = name => name.replace(/[A-Z]/g, v => '-' + v.toLowerCase());
@@ -5356,7 +5360,7 @@
5356
5360
  const toggleActiveAttr = (uid, state) => {
5357
5361
  each$e(findMarkers(editor, uid), elem => {
5358
5362
  if (state) {
5359
- set$3(elem, dataAnnotationActive(), 'true');
5363
+ set$4(elem, dataAnnotationActive(), 'true');
5360
5364
  } else {
5361
5365
  remove$9(elem, dataAnnotationActive());
5362
5366
  }
@@ -5655,7 +5659,7 @@
5655
5659
  };
5656
5660
  const createPaddingBr = () => {
5657
5661
  const br = SugarElement.fromTag('br');
5658
- set$3(br, 'data-mce-bogus', '1');
5662
+ set$4(br, 'data-mce-bogus', '1');
5659
5663
  return br;
5660
5664
  };
5661
5665
  const fillWithPaddingBr = elm => {
@@ -6826,6 +6830,90 @@
6826
6830
  };
6827
6831
  };
6828
6832
 
6833
+ const firePreProcess = (editor, args) => editor.dispatch('PreProcess', args);
6834
+ const firePostProcess = (editor, args) => editor.dispatch('PostProcess', args);
6835
+ const fireRemove = editor => {
6836
+ editor.dispatch('remove');
6837
+ };
6838
+ const fireDetach = editor => {
6839
+ editor.dispatch('detach');
6840
+ };
6841
+ const fireSwitchMode = (editor, mode) => {
6842
+ editor.dispatch('SwitchMode', { mode });
6843
+ };
6844
+ const fireObjectResizeStart = (editor, target, width, height, origin) => {
6845
+ editor.dispatch('ObjectResizeStart', {
6846
+ target,
6847
+ width,
6848
+ height,
6849
+ origin
6850
+ });
6851
+ };
6852
+ const fireObjectResized = (editor, target, width, height, origin) => {
6853
+ editor.dispatch('ObjectResized', {
6854
+ target,
6855
+ width,
6856
+ height,
6857
+ origin
6858
+ });
6859
+ };
6860
+ const firePreInit = editor => {
6861
+ editor.dispatch('PreInit');
6862
+ };
6863
+ const firePostRender = editor => {
6864
+ editor.dispatch('PostRender');
6865
+ };
6866
+ const fireInit = editor => {
6867
+ editor.dispatch('Init');
6868
+ };
6869
+ const firePlaceholderToggle = (editor, state) => {
6870
+ editor.dispatch('PlaceholderToggle', { state });
6871
+ };
6872
+ const fireError = (editor, errorType, error) => {
6873
+ editor.dispatch(errorType, error);
6874
+ };
6875
+ const fireFormatApply = (editor, format, node, vars) => {
6876
+ editor.dispatch('FormatApply', {
6877
+ format,
6878
+ node,
6879
+ vars
6880
+ });
6881
+ };
6882
+ const fireFormatRemove = (editor, format, node, vars) => {
6883
+ editor.dispatch('FormatRemove', {
6884
+ format,
6885
+ node,
6886
+ vars
6887
+ });
6888
+ };
6889
+ const fireBeforeSetContent = (editor, args) => editor.dispatch('BeforeSetContent', args);
6890
+ const fireSetContent = (editor, args) => editor.dispatch('SetContent', args);
6891
+ const fireBeforeGetContent = (editor, args) => editor.dispatch('BeforeGetContent', args);
6892
+ const fireGetContent = (editor, args) => editor.dispatch('GetContent', args);
6893
+ const fireAutocompleterStart = (editor, args) => {
6894
+ editor.dispatch('AutocompleterStart', args);
6895
+ };
6896
+ const fireAutocompleterUpdate = (editor, args) => {
6897
+ editor.dispatch('AutocompleterUpdate', args);
6898
+ };
6899
+ const fireAutocompleterUpdateActiveRange = (editor, args) => {
6900
+ editor.dispatch('AutocompleterUpdateActiveRange', args);
6901
+ };
6902
+ const fireAutocompleterEnd = editor => {
6903
+ editor.dispatch('AutocompleterEnd');
6904
+ };
6905
+ const firePastePreProcess = (editor, html, internal) => editor.dispatch('PastePreProcess', {
6906
+ content: html,
6907
+ internal
6908
+ });
6909
+ const firePastePostProcess = (editor, node, internal) => editor.dispatch('PastePostProcess', {
6910
+ node,
6911
+ internal
6912
+ });
6913
+ const firePastePlainTextToggle = (editor, state) => editor.dispatch('PastePlainTextToggle', { state });
6914
+ const fireEditableRootStateChange = (editor, state) => editor.dispatch('EditableRootStateChange', { state });
6915
+ const fireDisabledStateChange = (editor, state) => editor.dispatch('DisabledStateChange', { state });
6916
+
6829
6917
  const deviceDetection$1 = detect$1().deviceType;
6830
6918
  const isTouch = deviceDetection$1.isTouch();
6831
6919
  const DOM$a = DOMUtils.DOM;
@@ -7219,6 +7307,26 @@
7219
7307
  processor: 'boolean',
7220
7308
  default: false
7221
7309
  });
7310
+ registerOption('disabled', {
7311
+ processor: value => {
7312
+ if (isBoolean(value)) {
7313
+ if (editor.initialized && isDisabled$1(editor) !== value) {
7314
+ Promise.resolve().then(() => {
7315
+ fireDisabledStateChange(editor, value);
7316
+ });
7317
+ }
7318
+ return {
7319
+ valid: true,
7320
+ value
7321
+ };
7322
+ }
7323
+ return {
7324
+ valid: false,
7325
+ message: 'The value must be a boolean.'
7326
+ };
7327
+ },
7328
+ default: false
7329
+ });
7222
7330
  registerOption('readonly', {
7223
7331
  processor: 'boolean',
7224
7332
  default: false
@@ -7738,6 +7846,7 @@
7738
7846
  const shouldConvertUnsafeEmbeds = option('convert_unsafe_embeds');
7739
7847
  const getLicenseKey = option('license_key');
7740
7848
  const getApiKey = option('api_key');
7849
+ const isDisabled$1 = option('disabled');
7741
7850
 
7742
7851
  const isElement$3 = isElement$6;
7743
7852
  const isText$5 = isText$b;
@@ -9303,18 +9412,18 @@
9303
9412
  const applyAnnotation = (elem, masterUId, data, annotationName, decorate, directAnnotation) => {
9304
9413
  const {uid = masterUId, ...otherData} = data;
9305
9414
  add$2(elem, annotation());
9306
- set$3(elem, `${ dataAnnotationId() }`, uid);
9307
- set$3(elem, `${ dataAnnotation() }`, annotationName);
9415
+ set$4(elem, `${ dataAnnotationId() }`, uid);
9416
+ set$4(elem, `${ dataAnnotation() }`, annotationName);
9308
9417
  const {attributes = {}, classes = []} = decorate(uid, otherData);
9309
9418
  setAll$1(elem, attributes);
9310
9419
  add(elem, classes);
9311
9420
  if (directAnnotation) {
9312
9421
  if (classes.length > 0) {
9313
- set$3(elem, `${ dataAnnotationClasses() }`, classes.join(','));
9422
+ set$4(elem, `${ dataAnnotationClasses() }`, classes.join(','));
9314
9423
  }
9315
9424
  const attributeNames = keys(attributes);
9316
9425
  if (attributeNames.length > 0) {
9317
- set$3(elem, `${ dataAnnotationAttributes() }`, attributeNames.join(','));
9426
+ set$4(elem, `${ dataAnnotationAttributes() }`, attributeNames.join(','));
9318
9427
  }
9319
9428
  }
9320
9429
  };
@@ -9470,1563 +9579,1480 @@
9470
9579
  }
9471
9580
  };
9472
9581
 
9473
- const firePreProcess = (editor, args) => editor.dispatch('PreProcess', args);
9474
- const firePostProcess = (editor, args) => editor.dispatch('PostProcess', args);
9475
- const fireRemove = editor => {
9476
- editor.dispatch('remove');
9477
- };
9478
- const fireDetach = editor => {
9479
- editor.dispatch('detach');
9582
+ const getDocument = () => SugarElement.fromDom(document);
9583
+
9584
+ const focus$1 = (element, preventScroll = false) => element.dom.focus({ preventScroll });
9585
+ const hasFocus$1 = element => {
9586
+ const root = getRootNode(element).dom;
9587
+ return element.dom === root.activeElement;
9480
9588
  };
9481
- const fireSwitchMode = (editor, mode) => {
9482
- editor.dispatch('SwitchMode', { mode });
9589
+ const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
9590
+ const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
9591
+
9592
+ const create$9 = (start, soffset, finish, foffset) => ({
9593
+ start,
9594
+ soffset,
9595
+ finish,
9596
+ foffset
9597
+ });
9598
+ const SimRange = { create: create$9 };
9599
+
9600
+ const adt$3 = Adt.generate([
9601
+ { before: ['element'] },
9602
+ {
9603
+ on: [
9604
+ 'element',
9605
+ 'offset'
9606
+ ]
9607
+ },
9608
+ { after: ['element'] }
9609
+ ]);
9610
+ const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
9611
+ const getStart$2 = situ => situ.fold(identity, identity, identity);
9612
+ const before$1 = adt$3.before;
9613
+ const on = adt$3.on;
9614
+ const after$1 = adt$3.after;
9615
+ const Situ = {
9616
+ before: before$1,
9617
+ on,
9618
+ after: after$1,
9619
+ cata,
9620
+ getStart: getStart$2
9483
9621
  };
9484
- const fireObjectResizeStart = (editor, target, width, height, origin) => {
9485
- editor.dispatch('ObjectResizeStart', {
9486
- target,
9487
- width,
9488
- height,
9489
- origin
9490
- });
9622
+
9623
+ const adt$2 = Adt.generate([
9624
+ { domRange: ['rng'] },
9625
+ {
9626
+ relative: [
9627
+ 'startSitu',
9628
+ 'finishSitu'
9629
+ ]
9630
+ },
9631
+ {
9632
+ exact: [
9633
+ 'start',
9634
+ 'soffset',
9635
+ 'finish',
9636
+ 'foffset'
9637
+ ]
9638
+ }
9639
+ ]);
9640
+ const exactFromRange = simRange => adt$2.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
9641
+ const getStart$1 = selection => selection.match({
9642
+ domRange: rng => SugarElement.fromDom(rng.startContainer),
9643
+ relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
9644
+ exact: (start, _soffset, _finish, _foffset) => start
9645
+ });
9646
+ const domRange = adt$2.domRange;
9647
+ const relative = adt$2.relative;
9648
+ const exact = adt$2.exact;
9649
+ const getWin = selection => {
9650
+ const start = getStart$1(selection);
9651
+ return defaultView(start);
9491
9652
  };
9492
- const fireObjectResized = (editor, target, width, height, origin) => {
9493
- editor.dispatch('ObjectResized', {
9494
- target,
9495
- width,
9496
- height,
9497
- origin
9498
- });
9653
+ const range = SimRange.create;
9654
+ const SimSelection = {
9655
+ domRange,
9656
+ relative,
9657
+ exact,
9658
+ exactFromRange,
9659
+ getWin,
9660
+ range
9499
9661
  };
9500
- const firePreInit = editor => {
9501
- editor.dispatch('PreInit');
9662
+
9663
+ const clamp$1 = (offset, element) => {
9664
+ const max = isText$c(element) ? get$3(element).length : children$1(element).length + 1;
9665
+ if (offset > max) {
9666
+ return max;
9667
+ } else if (offset < 0) {
9668
+ return 0;
9669
+ }
9670
+ return offset;
9502
9671
  };
9503
- const firePostRender = editor => {
9504
- editor.dispatch('PostRender');
9672
+ const normalizeRng = rng => SimSelection.range(rng.start, clamp$1(rng.soffset, rng.start), rng.finish, clamp$1(rng.foffset, rng.finish));
9673
+ const isOrContains = (root, elm) => !isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm));
9674
+ const isRngInRoot = root => rng => isOrContains(root, rng.start) && isOrContains(root, rng.finish);
9675
+ const shouldStore = editor => editor.inline || Env.browser.isFirefox();
9676
+ const nativeRangeToSelectionRange = r => SimSelection.range(SugarElement.fromDom(r.startContainer), r.startOffset, SugarElement.fromDom(r.endContainer), r.endOffset);
9677
+ const readRange = win => {
9678
+ const selection = win.getSelection();
9679
+ const rng = !selection || selection.rangeCount === 0 ? Optional.none() : Optional.from(selection.getRangeAt(0));
9680
+ return rng.map(nativeRangeToSelectionRange);
9505
9681
  };
9506
- const fireInit = editor => {
9507
- editor.dispatch('Init');
9682
+ const getBookmark$1 = root => {
9683
+ const win = defaultView(root);
9684
+ return readRange(win.dom).filter(isRngInRoot(root));
9508
9685
  };
9509
- const firePlaceholderToggle = (editor, state) => {
9510
- editor.dispatch('PlaceholderToggle', { state });
9686
+ const validate = (root, bookmark) => Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
9687
+ const bookmarkToNativeRng = bookmark => {
9688
+ const rng = document.createRange();
9689
+ try {
9690
+ rng.setStart(bookmark.start.dom, bookmark.soffset);
9691
+ rng.setEnd(bookmark.finish.dom, bookmark.foffset);
9692
+ return Optional.some(rng);
9693
+ } catch (_) {
9694
+ return Optional.none();
9695
+ }
9511
9696
  };
9512
- const fireError = (editor, errorType, error) => {
9513
- editor.dispatch(errorType, error);
9697
+ const store = editor => {
9698
+ const newBookmark = shouldStore(editor) ? getBookmark$1(SugarElement.fromDom(editor.getBody())) : Optional.none();
9699
+ editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
9514
9700
  };
9515
- const fireFormatApply = (editor, format, node, vars) => {
9516
- editor.dispatch('FormatApply', {
9517
- format,
9518
- node,
9519
- vars
9520
- });
9701
+ const getRng = editor => {
9702
+ const bookmark = editor.bookmark ? editor.bookmark : Optional.none();
9703
+ return bookmark.bind(x => validate(SugarElement.fromDom(editor.getBody()), x)).bind(bookmarkToNativeRng);
9521
9704
  };
9522
- const fireFormatRemove = (editor, format, node, vars) => {
9523
- editor.dispatch('FormatRemove', {
9524
- format,
9525
- node,
9526
- vars
9527
- });
9705
+ const restore = editor => {
9706
+ getRng(editor).each(rng => editor.selection.setRng(rng));
9528
9707
  };
9529
- const fireBeforeSetContent = (editor, args) => editor.dispatch('BeforeSetContent', args);
9530
- const fireSetContent = (editor, args) => editor.dispatch('SetContent', args);
9531
- const fireBeforeGetContent = (editor, args) => editor.dispatch('BeforeGetContent', args);
9532
- const fireGetContent = (editor, args) => editor.dispatch('GetContent', args);
9533
- const fireAutocompleterStart = (editor, args) => {
9534
- editor.dispatch('AutocompleterStart', args);
9535
- };
9536
- const fireAutocompleterUpdate = (editor, args) => {
9537
- editor.dispatch('AutocompleterUpdate', args);
9708
+
9709
+ const isEditorUIElement$1 = elm => {
9710
+ const className = elm.className.toString();
9711
+ return className.indexOf('tox-') !== -1 || className.indexOf('mce-') !== -1;
9538
9712
  };
9539
- const fireAutocompleterUpdateActiveRange = (editor, args) => {
9540
- editor.dispatch('AutocompleterUpdateActiveRange', args);
9713
+ const FocusManager = { isEditorUIElement: isEditorUIElement$1 };
9714
+
9715
+ const wrappedSetTimeout = (callback, time) => {
9716
+ if (!isNumber(time)) {
9717
+ time = 0;
9718
+ }
9719
+ return setTimeout(callback, time);
9541
9720
  };
9542
- const fireAutocompleterEnd = editor => {
9543
- editor.dispatch('AutocompleterEnd');
9721
+ const wrappedSetInterval = (callback, time) => {
9722
+ if (!isNumber(time)) {
9723
+ time = 0;
9724
+ }
9725
+ return setInterval(callback, time);
9544
9726
  };
9545
- const firePastePreProcess = (editor, html, internal) => editor.dispatch('PastePreProcess', {
9546
- content: html,
9547
- internal
9548
- });
9549
- const firePastePostProcess = (editor, node, internal) => editor.dispatch('PastePostProcess', {
9550
- node,
9551
- internal
9552
- });
9553
- const firePastePlainTextToggle = (editor, state) => editor.dispatch('PastePlainTextToggle', { state });
9554
- const fireEditableRootStateChange = (editor, state) => editor.dispatch('EditableRootStateChange', { state });
9555
-
9556
- const VK = {
9557
- BACKSPACE: 8,
9558
- DELETE: 46,
9559
- DOWN: 40,
9560
- ENTER: 13,
9561
- ESC: 27,
9562
- LEFT: 37,
9563
- RIGHT: 39,
9564
- SPACEBAR: 32,
9565
- TAB: 9,
9566
- UP: 38,
9567
- PAGE_UP: 33,
9568
- PAGE_DOWN: 34,
9569
- END: 35,
9570
- HOME: 36,
9571
- modifierPressed: e => {
9572
- return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e);
9727
+ const Delay = {
9728
+ setEditorTimeout: (editor, callback, time) => {
9729
+ return wrappedSetTimeout(() => {
9730
+ if (!editor.removed) {
9731
+ callback();
9732
+ }
9733
+ }, time);
9573
9734
  },
9574
- metaKeyPressed: e => {
9575
- return Env.os.isMacOS() || Env.os.isiOS() ? e.metaKey : e.ctrlKey && !e.altKey;
9735
+ setEditorInterval: (editor, callback, time) => {
9736
+ const timer = wrappedSetInterval(() => {
9737
+ if (!editor.removed) {
9738
+ callback();
9739
+ } else {
9740
+ clearInterval(timer);
9741
+ }
9742
+ }, time);
9743
+ return timer;
9576
9744
  }
9577
9745
  };
9578
9746
 
9579
- const elementSelectionAttr = 'data-mce-selected';
9580
- const controlElmSelector = 'table,img,figure.image,hr,video,span.mce-preview-object,details';
9581
- const abs = Math.abs;
9582
- const round$1 = Math.round;
9583
- const resizeHandles = {
9584
- nw: [
9585
- 0,
9586
- 0,
9587
- -1,
9588
- -1
9589
- ],
9590
- ne: [
9591
- 1,
9592
- 0,
9593
- 1,
9594
- -1
9595
- ],
9596
- se: [
9597
- 1,
9598
- 1,
9599
- 1,
9600
- 1
9601
- ],
9602
- sw: [
9603
- 0,
9604
- 1,
9605
- -1,
9606
- 1
9607
- ]
9747
+ const isManualNodeChange = e => {
9748
+ return e.type === 'nodechange' && e.selectionChange;
9608
9749
  };
9609
- const isTouchEvent = evt => evt.type === 'longpress' || evt.type.indexOf('touch') === 0;
9610
- const ControlSelection = (selection, editor) => {
9611
- const dom = editor.dom;
9612
- const editableDoc = editor.getDoc();
9613
- const rootDocument = document;
9614
- const rootElement = editor.getBody();
9615
- let selectedElm, selectedElmGhost, resizeHelper, selectedHandle, resizeBackdrop;
9616
- let startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
9617
- let width;
9618
- let height;
9619
- let startScrollWidth;
9620
- let startScrollHeight;
9621
- const isImage = elm => isNonNullable(elm) && (isImg(elm) || dom.is(elm, 'figure.image'));
9622
- const isMedia = elm => isMedia$2(elm) || dom.hasClass(elm, 'mce-preview-object');
9623
- const isEventOnImageOutsideRange = (evt, range) => {
9624
- if (isTouchEvent(evt)) {
9625
- const touch = evt.touches[0];
9626
- return isImage(evt.target) && !isXYWithinRange(touch.clientX, touch.clientY, range);
9627
- } else {
9628
- return isImage(evt.target) && !isXYWithinRange(evt.clientX, evt.clientY, range);
9629
- }
9630
- };
9631
- const contextMenuSelectImage = evt => {
9632
- const target = evt.target;
9633
- if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) {
9634
- editor.selection.select(target);
9635
- }
9636
- };
9637
- const getResizeTargets = elm => {
9638
- if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
9639
- return [
9640
- elm,
9641
- elm.firstElementChild
9642
- ];
9643
- } else if (dom.is(elm, 'figure.image')) {
9644
- return [elm.querySelector('img')];
9645
- } else {
9646
- return [elm];
9647
- }
9750
+ const registerPageMouseUp = (editor, throttledStore) => {
9751
+ const mouseUpPage = () => {
9752
+ throttledStore.throttle();
9648
9753
  };
9649
- const isResizable = elm => {
9650
- const selector = getObjectResizing(editor);
9651
- if (!selector || editor.mode.isReadOnly()) {
9652
- return false;
9653
- }
9654
- if (elm.getAttribute('data-mce-resize') === 'false') {
9655
- return false;
9754
+ DOMUtils.DOM.bind(document, 'mouseup', mouseUpPage);
9755
+ editor.on('remove', () => {
9756
+ DOMUtils.DOM.unbind(document, 'mouseup', mouseUpPage);
9757
+ });
9758
+ };
9759
+ const registerMouseUp = (editor, throttledStore) => {
9760
+ editor.on('mouseup touchend', _e => {
9761
+ throttledStore.throttle();
9762
+ });
9763
+ };
9764
+ const registerEditorEvents = (editor, throttledStore) => {
9765
+ registerMouseUp(editor, throttledStore);
9766
+ editor.on('keyup NodeChange AfterSetSelectionRange', e => {
9767
+ if (!isManualNodeChange(e)) {
9768
+ store(editor);
9656
9769
  }
9657
- if (elm === editor.getBody()) {
9658
- return false;
9770
+ });
9771
+ };
9772
+ const register$6 = editor => {
9773
+ const throttledStore = first$1(() => {
9774
+ store(editor);
9775
+ }, 0);
9776
+ editor.on('init', () => {
9777
+ if (editor.inline) {
9778
+ registerPageMouseUp(editor, throttledStore);
9659
9779
  }
9660
- if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
9661
- return is$1(SugarElement.fromDom(elm.firstElementChild), selector);
9662
- } else {
9663
- return is$1(SugarElement.fromDom(elm), selector);
9780
+ registerEditorEvents(editor, throttledStore);
9781
+ });
9782
+ editor.on('remove', () => {
9783
+ throttledStore.cancel();
9784
+ });
9785
+ };
9786
+
9787
+ let documentFocusInHandler;
9788
+ const DOM$9 = DOMUtils.DOM;
9789
+ const isEditorUIElement = elm => {
9790
+ return isElement$6(elm) && FocusManager.isEditorUIElement(elm);
9791
+ };
9792
+ const isEditorContentAreaElement = elm => {
9793
+ const classList = elm.classList;
9794
+ if (classList !== undefined) {
9795
+ return classList.contains('tox-edit-area') || classList.contains('tox-edit-area__iframe') || classList.contains('mce-content-body');
9796
+ } else {
9797
+ return false;
9798
+ }
9799
+ };
9800
+ const isUIElement = (editor, elm) => {
9801
+ const customSelector = getCustomUiSelector(editor);
9802
+ const parent = DOM$9.getParent(elm, elm => {
9803
+ return isEditorUIElement(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false);
9804
+ });
9805
+ return parent !== null;
9806
+ };
9807
+ const getActiveElement = editor => {
9808
+ try {
9809
+ const root = getRootNode(SugarElement.fromDom(editor.getElement()));
9810
+ return active$1(root).fold(() => document.body, x => x.dom);
9811
+ } catch (ex) {
9812
+ return document.body;
9813
+ }
9814
+ };
9815
+ const registerEvents$1 = (editorManager, e) => {
9816
+ const editor = e.editor;
9817
+ register$6(editor);
9818
+ const toggleContentAreaOnFocus = (editor, fn) => {
9819
+ if (shouldHighlightOnFocus(editor) && editor.inline !== true) {
9820
+ const contentArea = SugarElement.fromDom(editor.getContainer());
9821
+ fn(contentArea, 'tox-edit-focus');
9664
9822
  }
9665
9823
  };
9666
- const createGhostElement = (dom, elm) => {
9667
- if (isMedia(elm)) {
9668
- return dom.create('img', { src: Env.transparentSrc });
9669
- } else if (isTable$2(elm)) {
9670
- const isNorth = startsWith(selectedHandle.name, 'n');
9671
- const rowSelect = isNorth ? head : last$2;
9672
- const tableElm = elm.cloneNode(true);
9673
- rowSelect(dom.select('tr', tableElm)).each(tr => {
9674
- const cells = dom.select('td,th', tr);
9675
- dom.setStyle(tr, 'height', null);
9676
- each$e(cells, cell => dom.setStyle(cell, 'height', null));
9677
- });
9678
- return tableElm;
9679
- } else {
9680
- return elm.cloneNode(true);
9824
+ editor.on('focusin', () => {
9825
+ const focusedEditor = editorManager.focusedEditor;
9826
+ if (isEditorContentAreaElement(getActiveElement(editor))) {
9827
+ toggleContentAreaOnFocus(editor, add$2);
9681
9828
  }
9682
- };
9683
- const setSizeProp = (element, name, value) => {
9684
- if (isNonNullable(value)) {
9685
- const targets = getResizeTargets(element);
9686
- each$e(targets, target => {
9687
- if (target.style[name] || !editor.schema.isValid(target.nodeName.toLowerCase(), name)) {
9688
- dom.setStyle(target, name, value);
9689
- } else {
9690
- dom.setAttrib(target, name, '' + value);
9691
- }
9692
- });
9693
- }
9694
- };
9695
- const setGhostElmSize = (ghostElm, width, height) => {
9696
- setSizeProp(ghostElm, 'width', width);
9697
- setSizeProp(ghostElm, 'height', height);
9698
- };
9699
- const resizeGhostElement = e => {
9700
- let deltaX, deltaY, proportional;
9701
- let resizeHelperX, resizeHelperY;
9702
- deltaX = e.screenX - startX;
9703
- deltaY = e.screenY - startY;
9704
- width = deltaX * selectedHandle[2] + startW;
9705
- height = deltaY * selectedHandle[3] + startH;
9706
- width = width < 5 ? 5 : width;
9707
- height = height < 5 ? 5 : height;
9708
- if ((isImage(selectedElm) || isMedia(selectedElm)) && getResizeImgProportional(editor) !== false) {
9709
- proportional = !VK.modifierPressed(e);
9710
- } else {
9711
- proportional = VK.modifierPressed(e);
9712
- }
9713
- if (proportional) {
9714
- if (abs(deltaX) > abs(deltaY)) {
9715
- height = round$1(width * ratio);
9716
- width = round$1(height / ratio);
9717
- } else {
9718
- width = round$1(height / ratio);
9719
- height = round$1(width * ratio);
9720
- }
9721
- }
9722
- setGhostElmSize(selectedElmGhost, width, height);
9723
- resizeHelperX = selectedHandle.startPos.x + deltaX;
9724
- resizeHelperY = selectedHandle.startPos.y + deltaY;
9725
- resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
9726
- resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
9727
- dom.setStyles(resizeHelper, {
9728
- left: resizeHelperX,
9729
- top: resizeHelperY,
9730
- display: 'block'
9731
- });
9732
- resizeHelper.innerHTML = width + ' &times; ' + height;
9733
- if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
9734
- dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
9735
- }
9736
- if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
9737
- dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
9738
- }
9739
- deltaX = rootElement.scrollWidth - startScrollWidth;
9740
- deltaY = rootElement.scrollHeight - startScrollHeight;
9741
- if (deltaX + deltaY !== 0) {
9742
- dom.setStyles(resizeHelper, {
9743
- left: resizeHelperX - deltaX,
9744
- top: resizeHelperY - deltaY
9745
- });
9746
- }
9747
- if (!resizeStarted) {
9748
- fireObjectResizeStart(editor, selectedElm, startW, startH, 'corner-' + selectedHandle.name);
9749
- resizeStarted = true;
9750
- }
9751
- };
9752
- const endGhostResize = () => {
9753
- const wasResizeStarted = resizeStarted;
9754
- resizeStarted = false;
9755
- if (wasResizeStarted) {
9756
- setSizeProp(selectedElm, 'width', width);
9757
- setSizeProp(selectedElm, 'height', height);
9758
- }
9759
- dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
9760
- dom.unbind(editableDoc, 'mouseup', endGhostResize);
9761
- if (rootDocument !== editableDoc) {
9762
- dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
9763
- dom.unbind(rootDocument, 'mouseup', endGhostResize);
9764
- }
9765
- dom.remove(selectedElmGhost);
9766
- dom.remove(resizeHelper);
9767
- dom.remove(resizeBackdrop);
9768
- showResizeRect(selectedElm);
9769
- if (wasResizeStarted) {
9770
- fireObjectResized(editor, selectedElm, width, height, 'corner-' + selectedHandle.name);
9771
- dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
9772
- }
9773
- editor.nodeChanged();
9774
- };
9775
- const showResizeRect = targetElm => {
9776
- unbindResizeHandleEvents();
9777
- const position = dom.getPos(targetElm, rootElement);
9778
- const selectedElmX = position.x;
9779
- const selectedElmY = position.y;
9780
- const rect = targetElm.getBoundingClientRect();
9781
- const targetWidth = rect.width || rect.right - rect.left;
9782
- const targetHeight = rect.height || rect.bottom - rect.top;
9783
- if (selectedElm !== targetElm) {
9784
- hideResizeRect();
9785
- selectedElm = targetElm;
9786
- width = height = 0;
9787
- }
9788
- const e = editor.dispatch('ObjectSelected', { target: targetElm });
9789
- if (isResizable(targetElm) && !e.isDefaultPrevented()) {
9790
- each$d(resizeHandles, (handle, name) => {
9791
- const startDrag = e => {
9792
- const target = getResizeTargets(selectedElm)[0];
9793
- startX = e.screenX;
9794
- startY = e.screenY;
9795
- startW = target.clientWidth;
9796
- startH = target.clientHeight;
9797
- ratio = startH / startW;
9798
- selectedHandle = handle;
9799
- selectedHandle.name = name;
9800
- selectedHandle.startPos = {
9801
- x: targetWidth * handle[0] + selectedElmX,
9802
- y: targetHeight * handle[1] + selectedElmY
9803
- };
9804
- startScrollWidth = rootElement.scrollWidth;
9805
- startScrollHeight = rootElement.scrollHeight;
9806
- resizeBackdrop = dom.add(rootElement, 'div', {
9807
- 'class': 'mce-resize-backdrop',
9808
- 'data-mce-bogus': 'all'
9809
- });
9810
- dom.setStyles(resizeBackdrop, {
9811
- position: 'fixed',
9812
- left: '0',
9813
- top: '0',
9814
- width: '100%',
9815
- height: '100%'
9816
- });
9817
- selectedElmGhost = createGhostElement(dom, selectedElm);
9818
- dom.addClass(selectedElmGhost, 'mce-clonedresizable');
9819
- dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
9820
- selectedElmGhost.contentEditable = 'false';
9821
- dom.setStyles(selectedElmGhost, {
9822
- left: selectedElmX,
9823
- top: selectedElmY,
9824
- margin: 0
9825
- });
9826
- setGhostElmSize(selectedElmGhost, targetWidth, targetHeight);
9827
- selectedElmGhost.removeAttribute(elementSelectionAttr);
9828
- rootElement.appendChild(selectedElmGhost);
9829
- dom.bind(editableDoc, 'mousemove', resizeGhostElement);
9830
- dom.bind(editableDoc, 'mouseup', endGhostResize);
9831
- if (rootDocument !== editableDoc) {
9832
- dom.bind(rootDocument, 'mousemove', resizeGhostElement);
9833
- dom.bind(rootDocument, 'mouseup', endGhostResize);
9834
- }
9835
- resizeHelper = dom.add(rootElement, 'div', {
9836
- 'class': 'mce-resize-helper',
9837
- 'data-mce-bogus': 'all'
9838
- }, startW + ' &times; ' + startH);
9839
- };
9840
- let handleElm = dom.get('mceResizeHandle' + name);
9841
- if (handleElm) {
9842
- dom.remove(handleElm);
9843
- }
9844
- handleElm = dom.add(rootElement, 'div', {
9845
- 'id': 'mceResizeHandle' + name,
9846
- 'data-mce-bogus': 'all',
9847
- 'class': 'mce-resizehandle',
9848
- 'unselectable': true,
9849
- 'style': 'cursor:' + name + '-resize; margin:0; padding:0'
9850
- });
9851
- dom.bind(handleElm, 'mousedown', e => {
9852
- e.stopImmediatePropagation();
9853
- e.preventDefault();
9854
- startDrag(e);
9855
- });
9856
- handle.elm = handleElm;
9857
- dom.setStyles(handleElm, {
9858
- left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2,
9859
- top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2
9860
- });
9861
- });
9862
- } else {
9863
- hideResizeRect(false);
9864
- }
9865
- };
9866
- const throttledShowResizeRect = first$1(showResizeRect, 0);
9867
- const hideResizeRect = (removeSelected = true) => {
9868
- throttledShowResizeRect.cancel();
9869
- unbindResizeHandleEvents();
9870
- if (selectedElm && removeSelected) {
9871
- selectedElm.removeAttribute(elementSelectionAttr);
9872
- }
9873
- each$d(resizeHandles, (value, name) => {
9874
- const handleElm = dom.get('mceResizeHandle' + name);
9875
- if (handleElm) {
9876
- dom.unbind(handleElm);
9877
- dom.remove(handleElm);
9878
- }
9879
- });
9880
- };
9881
- const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent);
9882
- const updateResizeRect = e => {
9883
- if (resizeStarted || editor.removed || editor.composing) {
9884
- return;
9885
- }
9886
- const targetElm = e.type === 'mousedown' ? e.target : selection.getNode();
9887
- 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();
9888
- const selectedValue = isNonNullable(controlElm) ? dom.getAttrib(controlElm, elementSelectionAttr, '1') : '1';
9889
- each$e(dom.select(`img[${ elementSelectionAttr }],hr[${ elementSelectionAttr }]`), img => {
9890
- img.removeAttribute(elementSelectionAttr);
9891
- });
9892
- if (isNonNullable(controlElm) && isChildOrEqual(controlElm, rootElement) && editor.hasFocus()) {
9893
- disableGeckoResize();
9894
- const startElm = selection.getStart(true);
9895
- if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
9896
- dom.setAttrib(controlElm, elementSelectionAttr, selectedValue);
9897
- throttledShowResizeRect.throttle(controlElm);
9898
- return;
9899
- }
9900
- }
9901
- hideResizeRect();
9902
- };
9903
- const unbindResizeHandleEvents = () => {
9904
- each$d(resizeHandles, handle => {
9905
- if (handle.elm) {
9906
- dom.unbind(handle.elm);
9907
- delete handle.elm;
9908
- }
9909
- });
9910
- };
9911
- const disableGeckoResize = () => {
9912
- try {
9913
- editor.getDoc().execCommand('enableObjectResizing', false, 'false');
9914
- } catch (ex) {
9915
- }
9916
- };
9917
- editor.on('init', () => {
9918
- disableGeckoResize();
9919
- editor.on('NodeChange ResizeEditor ResizeWindow ResizeContent drop', updateResizeRect);
9920
- editor.on('keyup compositionend', e => {
9921
- if (selectedElm && selectedElm.nodeName === 'TABLE') {
9922
- updateResizeRect(e);
9923
- }
9924
- });
9925
- editor.on('hide blur', hideResizeRect);
9926
- editor.on('contextmenu longpress', contextMenuSelectImage, true);
9927
- });
9928
- editor.on('remove', unbindResizeHandleEvents);
9929
- const destroy = () => {
9930
- throttledShowResizeRect.cancel();
9931
- selectedElm = selectedElmGhost = resizeBackdrop = null;
9932
- };
9933
- return {
9934
- isResizable,
9935
- showResizeRect,
9936
- hideResizeRect,
9937
- updateResizeRect,
9938
- destroy
9939
- };
9940
- };
9941
-
9942
- const setStart = (rng, situ) => {
9943
- situ.fold(e => {
9944
- rng.setStartBefore(e.dom);
9945
- }, (e, o) => {
9946
- rng.setStart(e.dom, o);
9947
- }, e => {
9948
- rng.setStartAfter(e.dom);
9949
- });
9950
- };
9951
- const setFinish = (rng, situ) => {
9952
- situ.fold(e => {
9953
- rng.setEndBefore(e.dom);
9954
- }, (e, o) => {
9955
- rng.setEnd(e.dom, o);
9956
- }, e => {
9957
- rng.setEndAfter(e.dom);
9958
- });
9959
- };
9960
- const relativeToNative = (win, startSitu, finishSitu) => {
9961
- const range = win.document.createRange();
9962
- setStart(range, startSitu);
9963
- setFinish(range, finishSitu);
9964
- return range;
9965
- };
9966
- const exactToNative = (win, start, soffset, finish, foffset) => {
9967
- const rng = win.document.createRange();
9968
- rng.setStart(start.dom, soffset);
9969
- rng.setEnd(finish.dom, foffset);
9970
- return rng;
9971
- };
9972
-
9973
- const adt$3 = Adt.generate([
9974
- {
9975
- ltr: [
9976
- 'start',
9977
- 'soffset',
9978
- 'finish',
9979
- 'foffset'
9980
- ]
9981
- },
9982
- {
9983
- rtl: [
9984
- 'start',
9985
- 'soffset',
9986
- 'finish',
9987
- 'foffset'
9988
- ]
9989
- }
9990
- ]);
9991
- const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
9992
- const getRanges = (win, selection) => selection.match({
9993
- domRange: rng => {
9994
- return {
9995
- ltr: constant(rng),
9996
- rtl: Optional.none
9997
- };
9998
- },
9999
- relative: (startSitu, finishSitu) => {
10000
- return {
10001
- ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
10002
- rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
10003
- };
10004
- },
10005
- exact: (start, soffset, finish, foffset) => {
10006
- return {
10007
- ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
10008
- rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
10009
- };
10010
- }
10011
- });
10012
- const doDiagnose = (win, ranges) => {
10013
- const rng = ranges.ltr();
10014
- if (rng.collapsed) {
10015
- const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
10016
- return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng));
10017
- } else {
10018
- return fromRange(win, adt$3.ltr, rng);
10019
- }
10020
- };
10021
- const diagnose = (win, selection) => {
10022
- const ranges = getRanges(win, selection);
10023
- return doDiagnose(win, ranges);
10024
- };
10025
- adt$3.ltr;
10026
- adt$3.rtl;
10027
-
10028
- const create$9 = (start, soffset, finish, foffset) => ({
10029
- start,
10030
- soffset,
10031
- finish,
10032
- foffset
10033
- });
10034
- const SimRange = { create: create$9 };
10035
-
10036
- const caretPositionFromPoint = (doc, x, y) => {
10037
- var _a;
10038
- return Optional.from((_a = doc.caretPositionFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y)).bind(pos => {
10039
- if (pos.offsetNode === null) {
10040
- return Optional.none();
9829
+ if (focusedEditor !== editor) {
9830
+ if (focusedEditor) {
9831
+ focusedEditor.dispatch('blur', { focusedEditor: editor });
9832
+ }
9833
+ editorManager.setActive(editor);
9834
+ editorManager.focusedEditor = editor;
9835
+ editor.dispatch('focus', { blurredEditor: focusedEditor });
9836
+ editor.focus(true);
10041
9837
  }
10042
- const r = doc.createRange();
10043
- r.setStart(pos.offsetNode, pos.offset);
10044
- r.collapse();
10045
- return Optional.some(r);
10046
9838
  });
10047
- };
10048
- const caretRangeFromPoint = (doc, x, y) => {
10049
- var _a;
10050
- return Optional.from((_a = doc.caretRangeFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y));
10051
- };
10052
- const availableSearch = (doc, x, y) => {
10053
- if (doc.caretPositionFromPoint) {
10054
- return caretPositionFromPoint(doc, x, y);
10055
- } else if (doc.caretRangeFromPoint) {
10056
- return caretRangeFromPoint(doc, x, y);
10057
- } else {
10058
- return Optional.none();
9839
+ editor.on('focusout', () => {
9840
+ Delay.setEditorTimeout(editor, () => {
9841
+ const focusedEditor = editorManager.focusedEditor;
9842
+ if (!isEditorContentAreaElement(getActiveElement(editor)) || focusedEditor !== editor) {
9843
+ toggleContentAreaOnFocus(editor, remove$6);
9844
+ }
9845
+ if (!isUIElement(editor, getActiveElement(editor)) && focusedEditor === editor) {
9846
+ editor.dispatch('blur', { focusedEditor: null });
9847
+ editorManager.focusedEditor = null;
9848
+ }
9849
+ });
9850
+ });
9851
+ if (!documentFocusInHandler) {
9852
+ documentFocusInHandler = e => {
9853
+ const activeEditor = editorManager.activeEditor;
9854
+ if (activeEditor) {
9855
+ getOriginalEventTarget(e).each(target => {
9856
+ const elem = target;
9857
+ if (elem.ownerDocument === document) {
9858
+ if (elem !== document.body && !isUIElement(activeEditor, elem) && editorManager.focusedEditor === activeEditor) {
9859
+ activeEditor.dispatch('blur', { focusedEditor: null });
9860
+ editorManager.focusedEditor = null;
9861
+ }
9862
+ }
9863
+ });
9864
+ }
9865
+ };
9866
+ DOM$9.bind(document, 'focusin', documentFocusInHandler);
10059
9867
  }
10060
9868
  };
10061
- const fromPoint$1 = (win, x, y) => {
10062
- const doc = win.document;
10063
- return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
10064
- };
10065
-
10066
- const adt$2 = Adt.generate([
10067
- { before: ['element'] },
10068
- {
10069
- on: [
10070
- 'element',
10071
- 'offset'
10072
- ]
10073
- },
10074
- { after: ['element'] }
10075
- ]);
10076
- const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
10077
- const getStart$2 = situ => situ.fold(identity, identity, identity);
10078
- const before$1 = adt$2.before;
10079
- const on = adt$2.on;
10080
- const after$1 = adt$2.after;
10081
- const Situ = {
10082
- before: before$1,
10083
- on,
10084
- after: after$1,
10085
- cata,
10086
- getStart: getStart$2
10087
- };
10088
-
10089
- const adt$1 = Adt.generate([
10090
- { domRange: ['rng'] },
10091
- {
10092
- relative: [
10093
- 'startSitu',
10094
- 'finishSitu'
10095
- ]
10096
- },
10097
- {
10098
- exact: [
10099
- 'start',
10100
- 'soffset',
10101
- 'finish',
10102
- 'foffset'
10103
- ]
9869
+ const unregisterDocumentEvents = (editorManager, e) => {
9870
+ if (editorManager.focusedEditor === e.editor) {
9871
+ editorManager.focusedEditor = null;
9872
+ }
9873
+ if (!editorManager.activeEditor && documentFocusInHandler) {
9874
+ DOM$9.unbind(document, 'focusin', documentFocusInHandler);
9875
+ documentFocusInHandler = null;
10104
9876
  }
10105
- ]);
10106
- const exactFromRange = simRange => adt$1.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
10107
- const getStart$1 = selection => selection.match({
10108
- domRange: rng => SugarElement.fromDom(rng.startContainer),
10109
- relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
10110
- exact: (start, _soffset, _finish, _foffset) => start
10111
- });
10112
- const domRange = adt$1.domRange;
10113
- const relative = adt$1.relative;
10114
- const exact = adt$1.exact;
10115
- const getWin = selection => {
10116
- const start = getStart$1(selection);
10117
- return defaultView(start);
10118
9877
  };
10119
- const range = SimRange.create;
10120
- const SimSelection = {
10121
- domRange,
10122
- relative,
10123
- exact,
10124
- exactFromRange,
10125
- getWin,
10126
- range
9878
+ const setup$w = editorManager => {
9879
+ editorManager.on('AddEditor', curry(registerEvents$1, editorManager));
9880
+ editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
10127
9881
  };
10128
9882
 
10129
- const beforeSpecial = (element, offset) => {
10130
- const name$1 = name(element);
10131
- if ('input' === name$1) {
10132
- return Situ.after(element);
10133
- } else if (!contains$2([
10134
- 'br',
10135
- 'img'
10136
- ], name$1)) {
10137
- return Situ.on(element, offset);
9883
+ const getContentEditableHost = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'true');
9884
+ const hasContentEditableFalseParent$1 = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'false') !== null;
9885
+ const getCollapsedNode = rng => rng.collapsed ? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(SugarElement.fromDom) : Optional.none();
9886
+ const getFocusInElement = (root, rng) => getCollapsedNode(rng).bind(node => {
9887
+ if (isTableSection(node)) {
9888
+ return Optional.some(node);
9889
+ } else if (!contains(root, node)) {
9890
+ return Optional.some(root);
10138
9891
  } else {
10139
- return offset === 0 ? Situ.before(element) : Situ.after(element);
9892
+ return Optional.none();
10140
9893
  }
10141
- };
10142
- const preprocessRelative = (startSitu, finishSitu) => {
10143
- const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
10144
- const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
10145
- return SimSelection.relative(start, finish);
10146
- };
10147
- const preprocessExact = (start, soffset, finish, foffset) => {
10148
- const startSitu = beforeSpecial(start, soffset);
10149
- const finishSitu = beforeSpecial(finish, foffset);
10150
- return SimSelection.relative(startSitu, finishSitu);
10151
- };
10152
- const preprocess = selection => selection.match({
10153
- domRange: rng => {
10154
- const start = SugarElement.fromDom(rng.startContainer);
10155
- const finish = SugarElement.fromDom(rng.endContainer);
10156
- return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
10157
- },
10158
- relative: preprocessRelative,
10159
- exact: preprocessExact
10160
9894
  });
10161
-
10162
- const fromElements = (elements, scope) => {
10163
- const doc = scope || document;
10164
- const fragment = doc.createDocumentFragment();
10165
- each$e(elements, element => {
10166
- fragment.appendChild(element.dom);
10167
- });
10168
- return SugarElement.fromDom(fragment);
10169
- };
10170
-
10171
- const toNative = selection => {
10172
- const win = SimSelection.getWin(selection).dom;
10173
- const getDomRange = (start, soffset, finish, foffset) => exactToNative(win, start, soffset, finish, foffset);
10174
- const filtered = preprocess(selection);
10175
- return diagnose(win, filtered).match({
10176
- ltr: getDomRange,
10177
- rtl: getDomRange
10178
- });
10179
- };
10180
- const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
10181
-
10182
- const fromPoint = (clientX, clientY, doc) => {
10183
- const win = defaultView(SugarElement.fromDom(doc));
10184
- return getAtPoint(win.dom, clientX, clientY).map(simRange => {
10185
- const rng = doc.createRange();
10186
- rng.setStart(simRange.start.dom, simRange.soffset);
10187
- rng.setEnd(simRange.finish.dom, simRange.foffset);
10188
- return rng;
10189
- }).getOrUndefined();
10190
- };
10191
-
10192
- const isEq$4 = (rng1, rng2) => {
10193
- return isNonNullable(rng1) && isNonNullable(rng2) && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset);
10194
- };
10195
-
10196
- const findParent = (node, rootNode, predicate) => {
10197
- let currentNode = node;
10198
- while (currentNode && currentNode !== rootNode) {
10199
- if (predicate(currentNode)) {
10200
- return currentNode;
10201
- }
10202
- currentNode = currentNode.parentNode;
10203
- }
10204
- return null;
10205
- };
10206
- const hasParent$1 = (node, rootNode, predicate) => findParent(node, rootNode, predicate) !== null;
10207
- const hasParentWithName = (node, rootNode, name) => hasParent$1(node, rootNode, node => node.nodeName === name);
10208
- const isCeFalseCaretContainer = (node, rootNode) => isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode);
10209
- const hasBrBeforeAfter = (dom, node, left) => {
10210
- const parentNode = node.parentNode;
10211
- if (parentNode) {
10212
- const walker = new DomTreeWalker(node, dom.getParent(parentNode, dom.isBlock) || dom.getRoot());
10213
- let currentNode;
10214
- while (currentNode = walker[left ? 'prev' : 'next']()) {
10215
- if (isBr$6(currentNode)) {
10216
- return true;
10217
- }
10218
- }
10219
- }
10220
- return false;
10221
- };
10222
- const isPrevNode = (node, name) => {
10223
- var _a;
10224
- return ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.nodeName) === name;
9895
+ const normalizeSelection = (editor, rng) => {
9896
+ getFocusInElement(SugarElement.fromDom(editor.getBody()), rng).bind(elm => {
9897
+ return firstPositionIn(elm.dom);
9898
+ }).fold(() => {
9899
+ editor.selection.normalize();
9900
+ }, caretPos => editor.selection.setRng(caretPos.toRange()));
10225
9901
  };
10226
- const hasContentEditableFalseParent$1 = (root, node) => {
10227
- let currentNode = node;
10228
- while (currentNode && currentNode !== root) {
10229
- if (isContentEditableFalse$b(currentNode)) {
10230
- return true;
9902
+ const focusBody = body => {
9903
+ if (body.setActive) {
9904
+ try {
9905
+ body.setActive();
9906
+ } catch (ex) {
9907
+ body.focus();
10231
9908
  }
10232
- currentNode = currentNode.parentNode;
10233
- }
10234
- return false;
10235
- };
10236
- const findTextNodeRelative = (dom, isAfterNode, collapsed, left, startNode) => {
10237
- const body = dom.getRoot();
10238
- const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10239
- const parentNode = startNode.parentNode;
10240
- let lastInlineElement;
10241
- let node;
10242
- if (!parentNode) {
10243
- return Optional.none();
9909
+ } else {
9910
+ body.focus();
10244
9911
  }
10245
- const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body;
10246
- if (left && isBr$6(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) {
10247
- return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode)));
9912
+ };
9913
+ const hasElementFocus = elm => hasFocus$1(elm) || search(elm).isSome();
9914
+ const hasIframeFocus = editor => isNonNullable(editor.iframeElement) && hasFocus$1(SugarElement.fromDom(editor.iframeElement));
9915
+ const hasInlineFocus = editor => {
9916
+ const rawBody = editor.getBody();
9917
+ return rawBody && hasElementFocus(SugarElement.fromDom(rawBody));
9918
+ };
9919
+ const hasUiFocus = editor => {
9920
+ const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
9921
+ return active$1(dos).filter(elem => !isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)).isSome();
9922
+ };
9923
+ const hasFocus = editor => editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
9924
+ const hasEditorOrUiFocus = editor => hasFocus(editor) || hasUiFocus(editor);
9925
+ const focusEditor = editor => {
9926
+ const selection = editor.selection;
9927
+ const body = editor.getBody();
9928
+ let rng = selection.getRng();
9929
+ editor.quirks.refreshContentEditable();
9930
+ const restoreBookmark = editor => {
9931
+ getRng(editor).each(bookmarkRng => {
9932
+ editor.selection.setRng(bookmarkRng);
9933
+ rng = bookmarkRng;
9934
+ });
9935
+ };
9936
+ if (!hasFocus(editor) && editor.hasEditableRoot()) {
9937
+ restoreBookmark(editor);
10248
9938
  }
10249
- const walker = new DomTreeWalker(startNode, parentBlockContainer);
10250
- while (node = walker[left ? 'prev' : 'next']()) {
10251
- if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) {
10252
- return Optional.none();
10253
- }
10254
- if (isText$b(node) && node.data.length > 0) {
10255
- if (!hasParentWithName(node, body, 'A')) {
10256
- return Optional.some(CaretPosition(node, left ? node.data.length : 0));
10257
- }
10258
- return Optional.none();
9939
+ const contentEditableHost = getContentEditableHost(editor, selection.getNode());
9940
+ if (contentEditableHost && editor.dom.isChildOf(contentEditableHost, body)) {
9941
+ if (!hasContentEditableFalseParent$1(editor, contentEditableHost)) {
9942
+ focusBody(body);
10259
9943
  }
10260
- if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
10261
- return Optional.none();
9944
+ focusBody(contentEditableHost);
9945
+ if (!editor.hasEditableRoot()) {
9946
+ restoreBookmark(editor);
10262
9947
  }
10263
- lastInlineElement = node;
9948
+ normalizeSelection(editor, rng);
9949
+ activateEditor(editor);
9950
+ return;
10264
9951
  }
10265
- if (isComment(lastInlineElement)) {
10266
- return Optional.none();
9952
+ if (!editor.inline) {
9953
+ if (!Env.browser.isOpera()) {
9954
+ focusBody(body);
9955
+ }
9956
+ editor.getWin().focus();
10267
9957
  }
10268
- if (collapsed && lastInlineElement) {
10269
- return Optional.some(CaretPosition(lastInlineElement, 0));
9958
+ if (Env.browser.isFirefox() || editor.inline) {
9959
+ focusBody(body);
9960
+ normalizeSelection(editor, rng);
10270
9961
  }
10271
- return Optional.none();
9962
+ activateEditor(editor);
10272
9963
  };
10273
- const normalizeEndPoint = (dom, collapsed, start, rng) => {
10274
- const body = dom.getRoot();
10275
- let node;
10276
- let normalized = false;
10277
- let container = start ? rng.startContainer : rng.endContainer;
10278
- let offset = start ? rng.startOffset : rng.endOffset;
10279
- const isAfterNode = isElement$6(container) && offset === container.childNodes.length;
10280
- const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10281
- let directionLeft = start;
10282
- if (isCaretContainer$2(container)) {
10283
- return Optional.none();
9964
+ const activateEditor = editor => editor.editorManager.setActive(editor);
9965
+ const focus = (editor, skipFocus) => {
9966
+ if (editor.removed) {
9967
+ return;
10284
9968
  }
10285
- if (isElement$6(container) && offset > container.childNodes.length - 1) {
10286
- directionLeft = false;
9969
+ if (skipFocus) {
9970
+ activateEditor(editor);
9971
+ } else {
9972
+ focusEditor(editor);
10287
9973
  }
10288
- if (isDocument$1(container)) {
10289
- container = body;
10290
- offset = 0;
9974
+ };
9975
+
9976
+ const VK = {
9977
+ BACKSPACE: 8,
9978
+ DELETE: 46,
9979
+ DOWN: 40,
9980
+ ENTER: 13,
9981
+ ESC: 27,
9982
+ LEFT: 37,
9983
+ RIGHT: 39,
9984
+ SPACEBAR: 32,
9985
+ TAB: 9,
9986
+ UP: 38,
9987
+ PAGE_UP: 33,
9988
+ PAGE_DOWN: 34,
9989
+ END: 35,
9990
+ HOME: 36,
9991
+ modifierPressed: e => {
9992
+ return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e);
9993
+ },
9994
+ metaKeyPressed: e => {
9995
+ return Env.os.isMacOS() || Env.os.isiOS() ? e.metaKey : e.ctrlKey && !e.altKey;
10291
9996
  }
10292
- if (container === body) {
10293
- if (directionLeft) {
10294
- node = container.childNodes[offset > 0 ? offset - 1 : 0];
10295
- if (node) {
10296
- if (isCaretContainer$2(node)) {
10297
- return Optional.none();
10298
- }
10299
- if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
10300
- return Optional.none();
10301
- }
10302
- }
9997
+ };
9998
+
9999
+ const elementSelectionAttr = 'data-mce-selected';
10000
+ const controlElmSelector = 'table,img,figure.image,hr,video,span.mce-preview-object,details';
10001
+ const abs = Math.abs;
10002
+ const round$1 = Math.round;
10003
+ const resizeHandles = {
10004
+ nw: [
10005
+ 0,
10006
+ 0,
10007
+ -1,
10008
+ -1
10009
+ ],
10010
+ ne: [
10011
+ 1,
10012
+ 0,
10013
+ 1,
10014
+ -1
10015
+ ],
10016
+ se: [
10017
+ 1,
10018
+ 1,
10019
+ 1,
10020
+ 1
10021
+ ],
10022
+ sw: [
10023
+ 0,
10024
+ 1,
10025
+ -1,
10026
+ 1
10027
+ ]
10028
+ };
10029
+ const isTouchEvent = evt => evt.type === 'longpress' || evt.type.indexOf('touch') === 0;
10030
+ const ControlSelection = (selection, editor) => {
10031
+ const dom = editor.dom;
10032
+ const editableDoc = editor.getDoc();
10033
+ const rootDocument = document;
10034
+ const rootElement = editor.getBody();
10035
+ let selectedElm, selectedElmGhost, resizeHelper, selectedHandle, resizeBackdrop;
10036
+ let startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
10037
+ let width;
10038
+ let height;
10039
+ let startScrollWidth;
10040
+ let startScrollHeight;
10041
+ const isImage = elm => isNonNullable(elm) && (isImg(elm) || dom.is(elm, 'figure.image'));
10042
+ const isMedia = elm => isMedia$2(elm) || dom.hasClass(elm, 'mce-preview-object');
10043
+ const isEventOnImageOutsideRange = (evt, range) => {
10044
+ if (isTouchEvent(evt)) {
10045
+ const touch = evt.touches[0];
10046
+ return isImage(evt.target) && !isXYWithinRange(touch.clientX, touch.clientY, range);
10047
+ } else {
10048
+ return isImage(evt.target) && !isXYWithinRange(evt.clientX, evt.clientY, range);
10303
10049
  }
10304
- if (container.hasChildNodes()) {
10305
- offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
10306
- container = container.childNodes[offset];
10307
- offset = isText$b(container) && isAfterNode ? container.data.length : 0;
10308
- if (!collapsed && container === body.lastChild && isTable$2(container)) {
10309
- return Optional.none();
10310
- }
10311
- if (hasContentEditableFalseParent$1(body, container) || isCaretContainer$2(container)) {
10312
- return Optional.none();
10313
- }
10314
- if (isDetails(container)) {
10315
- return Optional.none();
10316
- }
10317
- if (container.hasChildNodes() && !isTable$2(container)) {
10318
- node = container;
10319
- const walker = new DomTreeWalker(container, body);
10320
- do {
10321
- if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) {
10322
- normalized = false;
10323
- break;
10324
- }
10325
- if (isText$b(node) && node.data.length > 0) {
10326
- offset = directionLeft ? 0 : node.data.length;
10327
- container = node;
10328
- normalized = true;
10329
- break;
10330
- }
10331
- if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCellOrCaption(node)) {
10332
- offset = dom.nodeIndex(node);
10333
- container = node.parentNode;
10334
- if (!directionLeft) {
10335
- offset++;
10336
- }
10337
- normalized = true;
10338
- break;
10339
- }
10340
- } while (node = directionLeft ? walker.next() : walker.prev());
10341
- }
10050
+ };
10051
+ const contextMenuSelectImage = evt => {
10052
+ const target = evt.target;
10053
+ if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) {
10054
+ editor.selection.select(target);
10055
+ }
10056
+ };
10057
+ const getResizeTargets = elm => {
10058
+ if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
10059
+ return [
10060
+ elm,
10061
+ elm.firstElementChild
10062
+ ];
10063
+ } else if (dom.is(elm, 'figure.image')) {
10064
+ return [elm.querySelector('img')];
10065
+ } else {
10066
+ return [elm];
10067
+ }
10068
+ };
10069
+ const isResizable = elm => {
10070
+ const selector = getObjectResizing(editor);
10071
+ if (!selector || editor.mode.isReadOnly()) {
10072
+ return false;
10073
+ }
10074
+ if (elm.getAttribute('data-mce-resize') === 'false') {
10075
+ return false;
10076
+ }
10077
+ if (elm === editor.getBody()) {
10078
+ return false;
10079
+ }
10080
+ if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
10081
+ return is$1(SugarElement.fromDom(elm.firstElementChild), selector);
10082
+ } else {
10083
+ return is$1(SugarElement.fromDom(elm), selector);
10084
+ }
10085
+ };
10086
+ const createGhostElement = (dom, elm) => {
10087
+ if (isMedia(elm)) {
10088
+ return dom.create('img', { src: Env.transparentSrc });
10089
+ } else if (isTable$2(elm)) {
10090
+ const isNorth = startsWith(selectedHandle.name, 'n');
10091
+ const rowSelect = isNorth ? head : last$2;
10092
+ const tableElm = elm.cloneNode(true);
10093
+ rowSelect(dom.select('tr', tableElm)).each(tr => {
10094
+ const cells = dom.select('td,th', tr);
10095
+ dom.setStyle(tr, 'height', null);
10096
+ each$e(cells, cell => dom.setStyle(cell, 'height', null));
10097
+ });
10098
+ return tableElm;
10099
+ } else {
10100
+ return elm.cloneNode(true);
10342
10101
  }
10343
- }
10344
- if (collapsed) {
10345
- if (isText$b(container) && offset === 0) {
10346
- findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(pos => {
10347
- container = pos.container();
10348
- offset = pos.offset();
10349
- normalized = true;
10102
+ };
10103
+ const setSizeProp = (element, name, value) => {
10104
+ if (isNonNullable(value)) {
10105
+ const targets = getResizeTargets(element);
10106
+ each$e(targets, target => {
10107
+ if (target.style[name] || !editor.schema.isValid(target.nodeName.toLowerCase(), name)) {
10108
+ dom.setStyle(target, name, value);
10109
+ } else {
10110
+ dom.setAttrib(target, name, '' + value);
10111
+ }
10350
10112
  });
10351
10113
  }
10352
- if (isElement$6(container)) {
10353
- node = container.childNodes[offset];
10354
- if (!node) {
10355
- node = container.childNodes[offset - 1];
10356
- }
10357
- if (node && isBr$6(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) {
10358
- findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(pos => {
10359
- container = pos.container();
10360
- offset = pos.offset();
10361
- normalized = true;
10362
- });
10114
+ };
10115
+ const setGhostElmSize = (ghostElm, width, height) => {
10116
+ setSizeProp(ghostElm, 'width', width);
10117
+ setSizeProp(ghostElm, 'height', height);
10118
+ };
10119
+ const resizeGhostElement = e => {
10120
+ let deltaX, deltaY, proportional;
10121
+ let resizeHelperX, resizeHelperY;
10122
+ deltaX = e.screenX - startX;
10123
+ deltaY = e.screenY - startY;
10124
+ width = deltaX * selectedHandle[2] + startW;
10125
+ height = deltaY * selectedHandle[3] + startH;
10126
+ width = width < 5 ? 5 : width;
10127
+ height = height < 5 ? 5 : height;
10128
+ if ((isImage(selectedElm) || isMedia(selectedElm)) && getResizeImgProportional(editor) !== false) {
10129
+ proportional = !VK.modifierPressed(e);
10130
+ } else {
10131
+ proportional = VK.modifierPressed(e);
10132
+ }
10133
+ if (proportional) {
10134
+ if (abs(deltaX) > abs(deltaY)) {
10135
+ height = round$1(width * ratio);
10136
+ width = round$1(height / ratio);
10137
+ } else {
10138
+ width = round$1(height / ratio);
10139
+ height = round$1(width * ratio);
10363
10140
  }
10364
10141
  }
10365
- }
10366
- if (directionLeft && !collapsed && isText$b(container) && offset === container.data.length) {
10367
- findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(pos => {
10368
- container = pos.container();
10369
- offset = pos.offset();
10370
- normalized = true;
10142
+ setGhostElmSize(selectedElmGhost, width, height);
10143
+ resizeHelperX = selectedHandle.startPos.x + deltaX;
10144
+ resizeHelperY = selectedHandle.startPos.y + deltaY;
10145
+ resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
10146
+ resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
10147
+ dom.setStyles(resizeHelper, {
10148
+ left: resizeHelperX,
10149
+ top: resizeHelperY,
10150
+ display: 'block'
10371
10151
  });
10372
- }
10373
- return normalized && container ? Optional.some(CaretPosition(container, offset)) : Optional.none();
10374
- };
10375
- const normalize$2 = (dom, rng) => {
10376
- const collapsed = rng.collapsed, normRng = rng.cloneRange();
10377
- const startPos = CaretPosition.fromRangeStart(rng);
10378
- normalizeEndPoint(dom, collapsed, true, normRng).each(pos => {
10379
- if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
10380
- normRng.setStart(pos.container(), pos.offset());
10152
+ resizeHelper.innerHTML = width + ' &times; ' + height;
10153
+ if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
10154
+ dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
10381
10155
  }
10382
- });
10383
- if (!collapsed) {
10384
- normalizeEndPoint(dom, collapsed, false, normRng).each(pos => {
10385
- normRng.setEnd(pos.container(), pos.offset());
10386
- });
10387
- }
10388
- if (collapsed) {
10389
- normRng.collapse(true);
10390
- }
10391
- return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng);
10392
- };
10393
-
10394
- const splitText = (node, offset) => {
10395
- return node.splitText(offset);
10396
- };
10397
- const split = rng => {
10398
- let startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
10399
- if (startContainer === endContainer && isText$b(startContainer)) {
10400
- if (startOffset > 0 && startOffset < startContainer.data.length) {
10401
- endContainer = splitText(startContainer, startOffset);
10402
- startContainer = endContainer.previousSibling;
10403
- if (endOffset > startOffset) {
10404
- endOffset = endOffset - startOffset;
10405
- const newContainer = splitText(endContainer, endOffset).previousSibling;
10406
- startContainer = endContainer = newContainer;
10407
- endOffset = newContainer.data.length;
10408
- startOffset = 0;
10409
- } else {
10410
- endOffset = 0;
10411
- }
10156
+ if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
10157
+ dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
10412
10158
  }
10413
- } else {
10414
- if (isText$b(startContainer) && startOffset > 0 && startOffset < startContainer.data.length) {
10415
- startContainer = splitText(startContainer, startOffset);
10416
- startOffset = 0;
10159
+ deltaX = rootElement.scrollWidth - startScrollWidth;
10160
+ deltaY = rootElement.scrollHeight - startScrollHeight;
10161
+ if (deltaX + deltaY !== 0) {
10162
+ dom.setStyles(resizeHelper, {
10163
+ left: resizeHelperX - deltaX,
10164
+ top: resizeHelperY - deltaY
10165
+ });
10417
10166
  }
10418
- if (isText$b(endContainer) && endOffset > 0 && endOffset < endContainer.data.length) {
10419
- const newContainer = splitText(endContainer, endOffset).previousSibling;
10420
- endContainer = newContainer;
10421
- endOffset = newContainer.data.length;
10167
+ if (!resizeStarted) {
10168
+ fireObjectResizeStart(editor, selectedElm, startW, startH, 'corner-' + selectedHandle.name);
10169
+ resizeStarted = true;
10422
10170
  }
10423
- }
10424
- return {
10425
- startContainer,
10426
- startOffset,
10427
- endContainer,
10428
- endOffset
10429
- };
10430
- };
10431
-
10432
- const RangeUtils = dom => {
10433
- const walk = (rng, callback) => {
10434
- return walk$3(dom, rng, callback);
10435
10171
  };
10436
- const split$1 = split;
10437
- const normalize = rng => {
10438
- return normalize$2(dom, rng).fold(never, normalizedRng => {
10439
- rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
10440
- rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
10441
- return true;
10442
- });
10172
+ const endGhostResize = () => {
10173
+ const wasResizeStarted = resizeStarted;
10174
+ resizeStarted = false;
10175
+ if (wasResizeStarted) {
10176
+ setSizeProp(selectedElm, 'width', width);
10177
+ setSizeProp(selectedElm, 'height', height);
10178
+ }
10179
+ dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
10180
+ dom.unbind(editableDoc, 'mouseup', endGhostResize);
10181
+ if (rootDocument !== editableDoc) {
10182
+ dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
10183
+ dom.unbind(rootDocument, 'mouseup', endGhostResize);
10184
+ }
10185
+ dom.remove(selectedElmGhost);
10186
+ dom.remove(resizeHelper);
10187
+ dom.remove(resizeBackdrop);
10188
+ showResizeRect(selectedElm);
10189
+ if (wasResizeStarted) {
10190
+ fireObjectResized(editor, selectedElm, width, height, 'corner-' + selectedHandle.name);
10191
+ dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
10192
+ }
10193
+ editor.nodeChanged();
10443
10194
  };
10444
- const expand = (rng, options = { type: 'word' }) => {
10445
- if (options.type === 'word') {
10446
- const rangeLike = expandRng(dom, rng, [{ inline: 'span' }]);
10447
- const newRange = dom.createRng();
10448
- newRange.setStart(rangeLike.startContainer, rangeLike.startOffset);
10449
- newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset);
10450
- return newRange;
10195
+ const showResizeRect = targetElm => {
10196
+ unbindResizeHandleEvents();
10197
+ const position = dom.getPos(targetElm, rootElement);
10198
+ const selectedElmX = position.x;
10199
+ const selectedElmY = position.y;
10200
+ const rect = targetElm.getBoundingClientRect();
10201
+ const targetWidth = rect.width || rect.right - rect.left;
10202
+ const targetHeight = rect.height || rect.bottom - rect.top;
10203
+ if (selectedElm !== targetElm) {
10204
+ hideResizeRect();
10205
+ selectedElm = targetElm;
10206
+ width = height = 0;
10207
+ }
10208
+ const e = editor.dispatch('ObjectSelected', { target: targetElm });
10209
+ if (isResizable(targetElm) && !e.isDefaultPrevented()) {
10210
+ each$d(resizeHandles, (handle, name) => {
10211
+ const startDrag = e => {
10212
+ const target = getResizeTargets(selectedElm)[0];
10213
+ startX = e.screenX;
10214
+ startY = e.screenY;
10215
+ startW = target.clientWidth;
10216
+ startH = target.clientHeight;
10217
+ ratio = startH / startW;
10218
+ selectedHandle = handle;
10219
+ selectedHandle.name = name;
10220
+ selectedHandle.startPos = {
10221
+ x: targetWidth * handle[0] + selectedElmX,
10222
+ y: targetHeight * handle[1] + selectedElmY
10223
+ };
10224
+ startScrollWidth = rootElement.scrollWidth;
10225
+ startScrollHeight = rootElement.scrollHeight;
10226
+ resizeBackdrop = dom.add(rootElement, 'div', {
10227
+ 'class': 'mce-resize-backdrop',
10228
+ 'data-mce-bogus': 'all'
10229
+ });
10230
+ dom.setStyles(resizeBackdrop, {
10231
+ position: 'fixed',
10232
+ left: '0',
10233
+ top: '0',
10234
+ width: '100%',
10235
+ height: '100%'
10236
+ });
10237
+ selectedElmGhost = createGhostElement(dom, selectedElm);
10238
+ dom.addClass(selectedElmGhost, 'mce-clonedresizable');
10239
+ dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
10240
+ selectedElmGhost.contentEditable = 'false';
10241
+ dom.setStyles(selectedElmGhost, {
10242
+ left: selectedElmX,
10243
+ top: selectedElmY,
10244
+ margin: 0
10245
+ });
10246
+ setGhostElmSize(selectedElmGhost, targetWidth, targetHeight);
10247
+ selectedElmGhost.removeAttribute(elementSelectionAttr);
10248
+ rootElement.appendChild(selectedElmGhost);
10249
+ dom.bind(editableDoc, 'mousemove', resizeGhostElement);
10250
+ dom.bind(editableDoc, 'mouseup', endGhostResize);
10251
+ if (rootDocument !== editableDoc) {
10252
+ dom.bind(rootDocument, 'mousemove', resizeGhostElement);
10253
+ dom.bind(rootDocument, 'mouseup', endGhostResize);
10254
+ }
10255
+ resizeHelper = dom.add(rootElement, 'div', {
10256
+ 'class': 'mce-resize-helper',
10257
+ 'data-mce-bogus': 'all'
10258
+ }, startW + ' &times; ' + startH);
10259
+ };
10260
+ let handleElm = dom.get('mceResizeHandle' + name);
10261
+ if (handleElm) {
10262
+ dom.remove(handleElm);
10263
+ }
10264
+ handleElm = dom.add(rootElement, 'div', {
10265
+ 'id': 'mceResizeHandle' + name,
10266
+ 'data-mce-bogus': 'all',
10267
+ 'class': 'mce-resizehandle',
10268
+ 'unselectable': true,
10269
+ 'style': 'cursor:' + name + '-resize; margin:0; padding:0'
10270
+ });
10271
+ dom.bind(handleElm, 'mousedown', e => {
10272
+ e.stopImmediatePropagation();
10273
+ e.preventDefault();
10274
+ startDrag(e);
10275
+ });
10276
+ handle.elm = handleElm;
10277
+ dom.setStyles(handleElm, {
10278
+ left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2,
10279
+ top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2
10280
+ });
10281
+ });
10282
+ } else {
10283
+ hideResizeRect(false);
10451
10284
  }
10452
- return rng;
10453
10285
  };
10454
- return {
10455
- walk,
10456
- split: split$1,
10457
- expand,
10458
- normalize
10286
+ const throttledShowResizeRect = first$1(showResizeRect, 0);
10287
+ const hideResizeRect = (removeSelected = true) => {
10288
+ throttledShowResizeRect.cancel();
10289
+ unbindResizeHandleEvents();
10290
+ if (selectedElm && removeSelected) {
10291
+ selectedElm.removeAttribute(elementSelectionAttr);
10292
+ }
10293
+ each$d(resizeHandles, (value, name) => {
10294
+ const handleElm = dom.get('mceResizeHandle' + name);
10295
+ if (handleElm) {
10296
+ dom.unbind(handleElm);
10297
+ dom.remove(handleElm);
10298
+ }
10299
+ });
10459
10300
  };
10460
- };
10461
- RangeUtils.compareRanges = isEq$4;
10462
- RangeUtils.getCaretRangeFromPoint = fromPoint;
10463
- RangeUtils.getSelectedNode = getSelectedNode;
10464
- RangeUtils.getNode = getNode$1;
10465
-
10466
- const Dimension = (name, getOffset) => {
10467
- const set = (element, h) => {
10468
- if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
10469
- throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
10301
+ const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent);
10302
+ const updateResizeRect = e => {
10303
+ if (resizeStarted || editor.removed || editor.composing) {
10304
+ return;
10470
10305
  }
10471
- const dom = element.dom;
10472
- if (isSupported(dom)) {
10473
- dom.style[name] = h + 'px';
10306
+ const targetElm = e.type === 'mousedown' ? e.target : selection.getNode();
10307
+ 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();
10308
+ const selectedValue = isNonNullable(controlElm) ? dom.getAttrib(controlElm, elementSelectionAttr, '1') : '1';
10309
+ each$e(dom.select(`img[${ elementSelectionAttr }],hr[${ elementSelectionAttr }]`), img => {
10310
+ img.removeAttribute(elementSelectionAttr);
10311
+ });
10312
+ if (isNonNullable(controlElm) && isChildOrEqual(controlElm, rootElement) && hasEditorOrUiFocus(editor)) {
10313
+ disableGeckoResize();
10314
+ const startElm = selection.getStart(true);
10315
+ if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
10316
+ dom.setAttrib(controlElm, elementSelectionAttr, selectedValue);
10317
+ throttledShowResizeRect.throttle(controlElm);
10318
+ return;
10319
+ }
10474
10320
  }
10321
+ hideResizeRect();
10475
10322
  };
10476
- const get = element => {
10477
- const r = getOffset(element);
10478
- if (r <= 0 || r === null) {
10479
- const css = get$7(element, name);
10480
- return parseFloat(css) || 0;
10323
+ const unbindResizeHandleEvents = () => {
10324
+ each$d(resizeHandles, handle => {
10325
+ if (handle.elm) {
10326
+ dom.unbind(handle.elm);
10327
+ delete handle.elm;
10328
+ }
10329
+ });
10330
+ };
10331
+ const disableGeckoResize = () => {
10332
+ try {
10333
+ editor.getDoc().execCommand('enableObjectResizing', false, 'false');
10334
+ } catch (ex) {
10481
10335
  }
10482
- return r;
10483
10336
  };
10484
- const getOuter = get;
10485
- const aggregate = (element, properties) => foldl(properties, (acc, property) => {
10486
- const val = get$7(element, property);
10487
- const value = val === undefined ? 0 : parseInt(val, 10);
10488
- return isNaN(value) ? acc : acc + value;
10489
- }, 0);
10490
- const max = (element, value, properties) => {
10491
- const cumulativeInclusions = aggregate(element, properties);
10492
- const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
10493
- return absoluteMax;
10337
+ editor.on('init', () => {
10338
+ disableGeckoResize();
10339
+ editor.on('NodeChange ResizeEditor ResizeWindow ResizeContent drop', updateResizeRect);
10340
+ editor.on('keyup compositionend', e => {
10341
+ if (selectedElm && selectedElm.nodeName === 'TABLE') {
10342
+ updateResizeRect(e);
10343
+ }
10344
+ });
10345
+ editor.on('hide blur', hideResizeRect);
10346
+ editor.on('contextmenu longpress', contextMenuSelectImage, true);
10347
+ });
10348
+ editor.on('remove', unbindResizeHandleEvents);
10349
+ const destroy = () => {
10350
+ throttledShowResizeRect.cancel();
10351
+ selectedElm = selectedElmGhost = resizeBackdrop = null;
10494
10352
  };
10495
10353
  return {
10496
- set,
10497
- get,
10498
- getOuter,
10499
- aggregate,
10500
- max
10354
+ isResizable,
10355
+ showResizeRect,
10356
+ hideResizeRect,
10357
+ updateResizeRect,
10358
+ destroy
10501
10359
  };
10502
10360
  };
10503
10361
 
10504
- const api = Dimension('height', element => {
10505
- const dom = element.dom;
10506
- return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
10507
- });
10508
- const get$2 = element => api.get(element);
10509
-
10510
- const getDocument = () => SugarElement.fromDom(document);
10511
-
10512
- const walkUp = (navigation, doc) => {
10513
- const frame = navigation.view(doc);
10514
- return frame.fold(constant([]), f => {
10515
- const parent = navigation.owner(f);
10516
- const rest = walkUp(navigation, parent);
10517
- return [f].concat(rest);
10518
- });
10519
- };
10520
- const pathTo = (element, navigation) => {
10521
- const d = navigation.owner(element);
10522
- return walkUp(navigation, d);
10523
- };
10524
-
10525
- const view = doc => {
10526
- var _a;
10527
- const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
10528
- return element.map(SugarElement.fromDom);
10529
- };
10530
- const owner = element => documentOrOwner(element);
10531
-
10532
- var Navigation = /*#__PURE__*/Object.freeze({
10533
- __proto__: null,
10534
- view: view,
10535
- owner: owner
10536
- });
10537
-
10538
- const find = element => {
10539
- const doc = getDocument();
10540
- const scroll = get$5(doc);
10541
- const frames = pathTo(element, Navigation);
10542
- const offset = viewport(element);
10543
- const r = foldr(frames, (b, a) => {
10544
- const loc = viewport(a);
10545
- return {
10546
- left: b.left + loc.left,
10547
- top: b.top + loc.top
10548
- };
10549
- }, {
10550
- left: 0,
10551
- top: 0
10552
- });
10553
- return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
10554
- };
10555
-
10556
- const excludeFromDescend = element => name(element) === 'textarea';
10557
- const fireScrollIntoViewEvent = (editor, data) => {
10558
- const scrollEvent = editor.dispatch('ScrollIntoView', data);
10559
- return scrollEvent.isDefaultPrevented();
10560
- };
10561
- const fireAfterScrollIntoViewEvent = (editor, data) => {
10562
- editor.dispatch('AfterScrollIntoView', data);
10563
- };
10564
- const descend = (element, offset) => {
10565
- const children = children$1(element);
10566
- if (children.length === 0 || excludeFromDescend(element)) {
10567
- return {
10568
- element,
10569
- offset
10570
- };
10571
- } else if (offset < children.length && !excludeFromDescend(children[offset])) {
10572
- return {
10573
- element: children[offset],
10574
- offset: 0
10575
- };
10576
- } else {
10577
- const last = children[children.length - 1];
10578
- if (excludeFromDescend(last)) {
10579
- return {
10580
- element,
10581
- offset
10582
- };
10583
- } else {
10584
- if (name(last) === 'img') {
10585
- return {
10586
- element: last,
10587
- offset: 1
10588
- };
10589
- } else if (isText$c(last)) {
10590
- return {
10591
- element: last,
10592
- offset: get$3(last).length
10593
- };
10594
- } else {
10595
- return {
10596
- element: last,
10597
- offset: children$1(last).length
10598
- };
10599
- }
10600
- }
10601
- }
10602
- };
10603
- const markerInfo = (element, cleanupFun) => {
10604
- const pos = absolute(element);
10605
- const height = get$2(element);
10606
- return {
10607
- element,
10608
- bottom: pos.top + height,
10609
- height,
10610
- pos,
10611
- cleanup: cleanupFun
10612
- };
10613
- };
10614
- const createMarker$1 = (element, offset) => {
10615
- const startPoint = descend(element, offset);
10616
- const span = SugarElement.fromHtml('<span data-mce-bogus="all" style="display: inline-block;">' + ZWSP$1 + '</span>');
10617
- before$3(startPoint.element, span);
10618
- return markerInfo(span, () => remove$4(span));
10619
- };
10620
- const elementMarker = element => markerInfo(SugarElement.fromDom(element), noop);
10621
- const withMarker = (editor, f, rng, alignToTop) => {
10622
- preserveWith(editor, (_s, _e) => applyWithMarker(editor, f, rng, alignToTop), rng);
10623
- };
10624
- const withScrollEvents = (editor, doc, f, marker, alignToTop) => {
10625
- const data = {
10626
- elm: marker.element.dom,
10627
- alignToTop
10628
- };
10629
- if (fireScrollIntoViewEvent(editor, data)) {
10630
- return;
10631
- }
10632
- const scrollTop = get$5(doc).top;
10633
- f(editor, doc, scrollTop, marker, alignToTop);
10634
- fireAfterScrollIntoViewEvent(editor, data);
10362
+ const setStart = (rng, situ) => {
10363
+ situ.fold(e => {
10364
+ rng.setStartBefore(e.dom);
10365
+ }, (e, o) => {
10366
+ rng.setStart(e.dom, o);
10367
+ }, e => {
10368
+ rng.setStartAfter(e.dom);
10369
+ });
10635
10370
  };
10636
- const applyWithMarker = (editor, f, rng, alignToTop) => {
10637
- const body = SugarElement.fromDom(editor.getBody());
10638
- const doc = SugarElement.fromDom(editor.getDoc());
10639
- reflow(body);
10640
- const marker = createMarker$1(SugarElement.fromDom(rng.startContainer), rng.startOffset);
10641
- withScrollEvents(editor, doc, f, marker, alignToTop);
10642
- marker.cleanup();
10371
+ const setFinish = (rng, situ) => {
10372
+ situ.fold(e => {
10373
+ rng.setEndBefore(e.dom);
10374
+ }, (e, o) => {
10375
+ rng.setEnd(e.dom, o);
10376
+ }, e => {
10377
+ rng.setEndAfter(e.dom);
10378
+ });
10643
10379
  };
10644
- const withElement = (editor, element, f, alignToTop) => {
10645
- const doc = SugarElement.fromDom(editor.getDoc());
10646
- withScrollEvents(editor, doc, f, elementMarker(element), alignToTop);
10380
+ const relativeToNative = (win, startSitu, finishSitu) => {
10381
+ const range = win.document.createRange();
10382
+ setStart(range, startSitu);
10383
+ setFinish(range, finishSitu);
10384
+ return range;
10647
10385
  };
10648
- const preserveWith = (editor, f, rng) => {
10649
- const startElement = rng.startContainer;
10650
- const startOffset = rng.startOffset;
10651
- const endElement = rng.endContainer;
10652
- const endOffset = rng.endOffset;
10653
- f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement));
10654
- const newRng = editor.dom.createRng();
10655
- newRng.setStart(startElement, startOffset);
10656
- newRng.setEnd(endElement, endOffset);
10657
- editor.selection.setRng(rng);
10386
+ const exactToNative = (win, start, soffset, finish, foffset) => {
10387
+ const rng = win.document.createRange();
10388
+ rng.setStart(start.dom, soffset);
10389
+ rng.setEnd(finish.dom, foffset);
10390
+ return rng;
10658
10391
  };
10659
- const scrollToMarker = (editor, marker, viewHeight, alignToTop, doc) => {
10660
- const pos = marker.pos;
10661
- if (alignToTop) {
10662
- to(pos.left, pos.top, doc);
10663
- } else {
10664
- const y = pos.top - viewHeight + marker.height;
10665
- to(-editor.getBody().getBoundingClientRect().left, y, doc);
10392
+
10393
+ const adt$1 = Adt.generate([
10394
+ {
10395
+ ltr: [
10396
+ 'start',
10397
+ 'soffset',
10398
+ 'finish',
10399
+ 'foffset'
10400
+ ]
10401
+ },
10402
+ {
10403
+ rtl: [
10404
+ 'start',
10405
+ 'soffset',
10406
+ 'finish',
10407
+ 'foffset'
10408
+ ]
10666
10409
  }
10667
- };
10668
- const intoWindowIfNeeded = (editor, doc, scrollTop, viewHeight, marker, alignToTop) => {
10669
- const viewportBottom = viewHeight + scrollTop;
10670
- const markerTop = marker.pos.top;
10671
- const markerBottom = marker.bottom;
10672
- const largerThanViewport = markerBottom - markerTop >= viewHeight;
10673
- if (markerTop < scrollTop) {
10674
- scrollToMarker(editor, marker, viewHeight, alignToTop !== false, doc);
10675
- } else if (markerTop > viewportBottom) {
10676
- const align = largerThanViewport ? alignToTop !== false : alignToTop === true;
10677
- scrollToMarker(editor, marker, viewHeight, align, doc);
10678
- } else if (markerBottom > viewportBottom && !largerThanViewport) {
10679
- scrollToMarker(editor, marker, viewHeight, alignToTop === true, doc);
10410
+ ]);
10411
+ const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
10412
+ const getRanges = (win, selection) => selection.match({
10413
+ domRange: rng => {
10414
+ return {
10415
+ ltr: constant(rng),
10416
+ rtl: Optional.none
10417
+ };
10418
+ },
10419
+ relative: (startSitu, finishSitu) => {
10420
+ return {
10421
+ ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
10422
+ rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
10423
+ };
10424
+ },
10425
+ exact: (start, soffset, finish, foffset) => {
10426
+ return {
10427
+ ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
10428
+ rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
10429
+ };
10680
10430
  }
10681
- };
10682
- const intoWindow = (editor, doc, scrollTop, marker, alignToTop) => {
10683
- const viewHeight = defaultView(doc).dom.innerHeight;
10684
- intoWindowIfNeeded(editor, doc, scrollTop, viewHeight, marker, alignToTop);
10685
- };
10686
- const intoFrame = (editor, doc, scrollTop, marker, alignToTop) => {
10687
- const frameViewHeight = defaultView(doc).dom.innerHeight;
10688
- intoWindowIfNeeded(editor, doc, scrollTop, frameViewHeight, marker, alignToTop);
10689
- const op = find(marker.element);
10690
- const viewportBounds = getBounds(window);
10691
- if (op.top < viewportBounds.y) {
10692
- intoView(marker.element, alignToTop !== false);
10693
- } else if (op.top > viewportBounds.bottom) {
10694
- intoView(marker.element, alignToTop === true);
10431
+ });
10432
+ const doDiagnose = (win, ranges) => {
10433
+ const rng = ranges.ltr();
10434
+ if (rng.collapsed) {
10435
+ const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
10436
+ return reversed.map(rev => adt$1.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$1.ltr, rng));
10437
+ } else {
10438
+ return fromRange(win, adt$1.ltr, rng);
10695
10439
  }
10696
10440
  };
10697
- const rangeIntoWindow = (editor, rng, alignToTop) => withMarker(editor, intoWindow, rng, alignToTop);
10698
- const elementIntoWindow = (editor, element, alignToTop) => withElement(editor, element, intoWindow, alignToTop);
10699
- const rangeIntoFrame = (editor, rng, alignToTop) => withMarker(editor, intoFrame, rng, alignToTop);
10700
- const elementIntoFrame = (editor, element, alignToTop) => withElement(editor, element, intoFrame, alignToTop);
10701
- const scrollElementIntoView = (editor, element, alignToTop) => {
10702
- const scroller = editor.inline ? elementIntoWindow : elementIntoFrame;
10703
- scroller(editor, element, alignToTop);
10704
- };
10705
- const scrollRangeIntoView = (editor, rng, alignToTop) => {
10706
- const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame;
10707
- scroller(editor, rng, alignToTop);
10708
- };
10709
-
10710
- const focus$1 = (element, preventScroll = false) => element.dom.focus({ preventScroll });
10711
- const hasFocus$1 = element => {
10712
- const root = getRootNode(element).dom;
10713
- return element.dom === root.activeElement;
10441
+ const diagnose = (win, selection) => {
10442
+ const ranges = getRanges(win, selection);
10443
+ return doDiagnose(win, ranges);
10714
10444
  };
10715
- const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
10716
- const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
10445
+ adt$1.ltr;
10446
+ adt$1.rtl;
10717
10447
 
10718
- const clamp$1 = (offset, element) => {
10719
- const max = isText$c(element) ? get$3(element).length : children$1(element).length + 1;
10720
- if (offset > max) {
10721
- return max;
10722
- } else if (offset < 0) {
10723
- return 0;
10724
- }
10725
- return offset;
10726
- };
10727
- const normalizeRng = rng => SimSelection.range(rng.start, clamp$1(rng.soffset, rng.start), rng.finish, clamp$1(rng.foffset, rng.finish));
10728
- const isOrContains = (root, elm) => !isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm));
10729
- const isRngInRoot = root => rng => isOrContains(root, rng.start) && isOrContains(root, rng.finish);
10730
- const shouldStore = editor => editor.inline || Env.browser.isFirefox();
10731
- const nativeRangeToSelectionRange = r => SimSelection.range(SugarElement.fromDom(r.startContainer), r.startOffset, SugarElement.fromDom(r.endContainer), r.endOffset);
10732
- const readRange = win => {
10733
- const selection = win.getSelection();
10734
- const rng = !selection || selection.rangeCount === 0 ? Optional.none() : Optional.from(selection.getRangeAt(0));
10735
- return rng.map(nativeRangeToSelectionRange);
10448
+ const caretPositionFromPoint = (doc, x, y) => {
10449
+ var _a;
10450
+ return Optional.from((_a = doc.caretPositionFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y)).bind(pos => {
10451
+ if (pos.offsetNode === null) {
10452
+ return Optional.none();
10453
+ }
10454
+ const r = doc.createRange();
10455
+ r.setStart(pos.offsetNode, pos.offset);
10456
+ r.collapse();
10457
+ return Optional.some(r);
10458
+ });
10736
10459
  };
10737
- const getBookmark$1 = root => {
10738
- const win = defaultView(root);
10739
- return readRange(win.dom).filter(isRngInRoot(root));
10460
+ const caretRangeFromPoint = (doc, x, y) => {
10461
+ var _a;
10462
+ return Optional.from((_a = doc.caretRangeFromPoint) === null || _a === void 0 ? void 0 : _a.call(doc, x, y));
10740
10463
  };
10741
- const validate = (root, bookmark) => Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
10742
- const bookmarkToNativeRng = bookmark => {
10743
- const rng = document.createRange();
10744
- try {
10745
- rng.setStart(bookmark.start.dom, bookmark.soffset);
10746
- rng.setEnd(bookmark.finish.dom, bookmark.foffset);
10747
- return Optional.some(rng);
10748
- } catch (_) {
10464
+ const availableSearch = (doc, x, y) => {
10465
+ if (doc.caretPositionFromPoint) {
10466
+ return caretPositionFromPoint(doc, x, y);
10467
+ } else if (doc.caretRangeFromPoint) {
10468
+ return caretRangeFromPoint(doc, x, y);
10469
+ } else {
10749
10470
  return Optional.none();
10750
10471
  }
10751
10472
  };
10752
- const store = editor => {
10753
- const newBookmark = shouldStore(editor) ? getBookmark$1(SugarElement.fromDom(editor.getBody())) : Optional.none();
10754
- editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
10755
- };
10756
- const getRng = editor => {
10757
- const bookmark = editor.bookmark ? editor.bookmark : Optional.none();
10758
- return bookmark.bind(x => validate(SugarElement.fromDom(editor.getBody()), x)).bind(bookmarkToNativeRng);
10759
- };
10760
- const restore = editor => {
10761
- getRng(editor).each(rng => editor.selection.setRng(rng));
10762
- };
10763
-
10764
- const isEditorUIElement$1 = elm => {
10765
- const className = elm.className.toString();
10766
- return className.indexOf('tox-') !== -1 || className.indexOf('mce-') !== -1;
10473
+ const fromPoint$1 = (win, x, y) => {
10474
+ const doc = win.document;
10475
+ return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
10767
10476
  };
10768
- const FocusManager = { isEditorUIElement: isEditorUIElement$1 };
10769
10477
 
10770
- const wrappedSetTimeout = (callback, time) => {
10771
- if (!isNumber(time)) {
10772
- time = 0;
10478
+ const beforeSpecial = (element, offset) => {
10479
+ const name$1 = name(element);
10480
+ if ('input' === name$1) {
10481
+ return Situ.after(element);
10482
+ } else if (!contains$2([
10483
+ 'br',
10484
+ 'img'
10485
+ ], name$1)) {
10486
+ return Situ.on(element, offset);
10487
+ } else {
10488
+ return offset === 0 ? Situ.before(element) : Situ.after(element);
10773
10489
  }
10774
- return setTimeout(callback, time);
10775
10490
  };
10776
- const wrappedSetInterval = (callback, time) => {
10777
- if (!isNumber(time)) {
10778
- time = 0;
10779
- }
10780
- return setInterval(callback, time);
10491
+ const preprocessRelative = (startSitu, finishSitu) => {
10492
+ const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
10493
+ const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
10494
+ return SimSelection.relative(start, finish);
10781
10495
  };
10782
- const Delay = {
10783
- setEditorTimeout: (editor, callback, time) => {
10784
- return wrappedSetTimeout(() => {
10785
- if (!editor.removed) {
10786
- callback();
10787
- }
10788
- }, time);
10789
- },
10790
- setEditorInterval: (editor, callback, time) => {
10791
- const timer = wrappedSetInterval(() => {
10792
- if (!editor.removed) {
10793
- callback();
10794
- } else {
10795
- clearInterval(timer);
10796
- }
10797
- }, time);
10798
- return timer;
10799
- }
10496
+ const preprocessExact = (start, soffset, finish, foffset) => {
10497
+ const startSitu = beforeSpecial(start, soffset);
10498
+ const finishSitu = beforeSpecial(finish, foffset);
10499
+ return SimSelection.relative(startSitu, finishSitu);
10800
10500
  };
10501
+ const preprocess = selection => selection.match({
10502
+ domRange: rng => {
10503
+ const start = SugarElement.fromDom(rng.startContainer);
10504
+ const finish = SugarElement.fromDom(rng.endContainer);
10505
+ return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
10506
+ },
10507
+ relative: preprocessRelative,
10508
+ exact: preprocessExact
10509
+ });
10801
10510
 
10802
- const isManualNodeChange = e => {
10803
- return e.type === 'nodechange' && e.selectionChange;
10804
- };
10805
- const registerPageMouseUp = (editor, throttledStore) => {
10806
- const mouseUpPage = () => {
10807
- throttledStore.throttle();
10808
- };
10809
- DOMUtils.DOM.bind(document, 'mouseup', mouseUpPage);
10810
- editor.on('remove', () => {
10811
- DOMUtils.DOM.unbind(document, 'mouseup', mouseUpPage);
10511
+ const fromElements = (elements, scope) => {
10512
+ const doc = scope || document;
10513
+ const fragment = doc.createDocumentFragment();
10514
+ each$e(elements, element => {
10515
+ fragment.appendChild(element.dom);
10812
10516
  });
10517
+ return SugarElement.fromDom(fragment);
10813
10518
  };
10814
- const registerMouseUp = (editor, throttledStore) => {
10815
- editor.on('mouseup touchend', _e => {
10816
- throttledStore.throttle();
10519
+
10520
+ const toNative = selection => {
10521
+ const win = SimSelection.getWin(selection).dom;
10522
+ const getDomRange = (start, soffset, finish, foffset) => exactToNative(win, start, soffset, finish, foffset);
10523
+ const filtered = preprocess(selection);
10524
+ return diagnose(win, filtered).match({
10525
+ ltr: getDomRange,
10526
+ rtl: getDomRange
10817
10527
  });
10818
10528
  };
10819
- const registerEditorEvents = (editor, throttledStore) => {
10820
- registerMouseUp(editor, throttledStore);
10821
- editor.on('keyup NodeChange AfterSetSelectionRange', e => {
10822
- if (!isManualNodeChange(e)) {
10823
- store(editor);
10824
- }
10825
- });
10529
+ const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
10530
+
10531
+ const fromPoint = (clientX, clientY, doc) => {
10532
+ const win = defaultView(SugarElement.fromDom(doc));
10533
+ return getAtPoint(win.dom, clientX, clientY).map(simRange => {
10534
+ const rng = doc.createRange();
10535
+ rng.setStart(simRange.start.dom, simRange.soffset);
10536
+ rng.setEnd(simRange.finish.dom, simRange.foffset);
10537
+ return rng;
10538
+ }).getOrUndefined();
10826
10539
  };
10827
- const register$6 = editor => {
10828
- const throttledStore = first$1(() => {
10829
- store(editor);
10830
- }, 0);
10831
- editor.on('init', () => {
10832
- if (editor.inline) {
10833
- registerPageMouseUp(editor, throttledStore);
10834
- }
10835
- registerEditorEvents(editor, throttledStore);
10836
- });
10837
- editor.on('remove', () => {
10838
- throttledStore.cancel();
10839
- });
10540
+
10541
+ const isEq$4 = (rng1, rng2) => {
10542
+ return isNonNullable(rng1) && isNonNullable(rng2) && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset);
10840
10543
  };
10841
10544
 
10842
- let documentFocusInHandler;
10843
- const DOM$9 = DOMUtils.DOM;
10844
- const isEditorUIElement = elm => {
10845
- return isElement$6(elm) && FocusManager.isEditorUIElement(elm);
10545
+ const findParent = (node, rootNode, predicate) => {
10546
+ let currentNode = node;
10547
+ while (currentNode && currentNode !== rootNode) {
10548
+ if (predicate(currentNode)) {
10549
+ return currentNode;
10550
+ }
10551
+ currentNode = currentNode.parentNode;
10552
+ }
10553
+ return null;
10846
10554
  };
10847
- const isEditorContentAreaElement = elm => {
10848
- const classList = elm.classList;
10849
- if (classList !== undefined) {
10850
- return classList.contains('tox-edit-area') || classList.contains('tox-edit-area__iframe') || classList.contains('mce-content-body');
10851
- } else {
10852
- return false;
10555
+ const hasParent$1 = (node, rootNode, predicate) => findParent(node, rootNode, predicate) !== null;
10556
+ const hasParentWithName = (node, rootNode, name) => hasParent$1(node, rootNode, node => node.nodeName === name);
10557
+ const isCeFalseCaretContainer = (node, rootNode) => isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode);
10558
+ const hasBrBeforeAfter = (dom, node, left) => {
10559
+ const parentNode = node.parentNode;
10560
+ if (parentNode) {
10561
+ const walker = new DomTreeWalker(node, dom.getParent(parentNode, dom.isBlock) || dom.getRoot());
10562
+ let currentNode;
10563
+ while (currentNode = walker[left ? 'prev' : 'next']()) {
10564
+ if (isBr$6(currentNode)) {
10565
+ return true;
10566
+ }
10567
+ }
10853
10568
  }
10569
+ return false;
10854
10570
  };
10855
- const isUIElement = (editor, elm) => {
10856
- const customSelector = getCustomUiSelector(editor);
10857
- const parent = DOM$9.getParent(elm, elm => {
10858
- return isEditorUIElement(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false);
10859
- });
10860
- return parent !== null;
10571
+ const isPrevNode = (node, name) => {
10572
+ var _a;
10573
+ return ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.nodeName) === name;
10861
10574
  };
10862
- const getActiveElement = editor => {
10863
- try {
10864
- const root = getRootNode(SugarElement.fromDom(editor.getElement()));
10865
- return active$1(root).fold(() => document.body, x => x.dom);
10866
- } catch (ex) {
10867
- return document.body;
10575
+ const hasContentEditableFalseParent = (root, node) => {
10576
+ let currentNode = node;
10577
+ while (currentNode && currentNode !== root) {
10578
+ if (isContentEditableFalse$b(currentNode)) {
10579
+ return true;
10580
+ }
10581
+ currentNode = currentNode.parentNode;
10868
10582
  }
10583
+ return false;
10869
10584
  };
10870
- const registerEvents$1 = (editorManager, e) => {
10871
- const editor = e.editor;
10872
- register$6(editor);
10873
- const toggleContentAreaOnFocus = (editor, fn) => {
10874
- if (shouldHighlightOnFocus(editor) && editor.inline !== true) {
10875
- const contentArea = SugarElement.fromDom(editor.getContainer());
10876
- fn(contentArea, 'tox-edit-focus');
10585
+ const findTextNodeRelative = (dom, isAfterNode, collapsed, left, startNode) => {
10586
+ const body = dom.getRoot();
10587
+ const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10588
+ const parentNode = startNode.parentNode;
10589
+ let lastInlineElement;
10590
+ let node;
10591
+ if (!parentNode) {
10592
+ return Optional.none();
10593
+ }
10594
+ const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body;
10595
+ if (left && isBr$6(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) {
10596
+ return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode)));
10597
+ }
10598
+ const walker = new DomTreeWalker(startNode, parentBlockContainer);
10599
+ while (node = walker[left ? 'prev' : 'next']()) {
10600
+ if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) {
10601
+ return Optional.none();
10877
10602
  }
10878
- };
10879
- editor.on('focusin', () => {
10880
- const focusedEditor = editorManager.focusedEditor;
10881
- if (isEditorContentAreaElement(getActiveElement(editor))) {
10882
- toggleContentAreaOnFocus(editor, add$2);
10603
+ if (isText$b(node) && node.data.length > 0) {
10604
+ if (!hasParentWithName(node, body, 'A')) {
10605
+ return Optional.some(CaretPosition(node, left ? node.data.length : 0));
10606
+ }
10607
+ return Optional.none();
10883
10608
  }
10884
- if (focusedEditor !== editor) {
10885
- if (focusedEditor) {
10886
- focusedEditor.dispatch('blur', { focusedEditor: editor });
10609
+ if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
10610
+ return Optional.none();
10611
+ }
10612
+ lastInlineElement = node;
10613
+ }
10614
+ if (isComment(lastInlineElement)) {
10615
+ return Optional.none();
10616
+ }
10617
+ if (collapsed && lastInlineElement) {
10618
+ return Optional.some(CaretPosition(lastInlineElement, 0));
10619
+ }
10620
+ return Optional.none();
10621
+ };
10622
+ const normalizeEndPoint = (dom, collapsed, start, rng) => {
10623
+ const body = dom.getRoot();
10624
+ let node;
10625
+ let normalized = false;
10626
+ let container = start ? rng.startContainer : rng.endContainer;
10627
+ let offset = start ? rng.startOffset : rng.endOffset;
10628
+ const isAfterNode = isElement$6(container) && offset === container.childNodes.length;
10629
+ const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10630
+ let directionLeft = start;
10631
+ if (isCaretContainer$2(container)) {
10632
+ return Optional.none();
10633
+ }
10634
+ if (isElement$6(container) && offset > container.childNodes.length - 1) {
10635
+ directionLeft = false;
10636
+ }
10637
+ if (isDocument$1(container)) {
10638
+ container = body;
10639
+ offset = 0;
10640
+ }
10641
+ if (container === body) {
10642
+ if (directionLeft) {
10643
+ node = container.childNodes[offset > 0 ? offset - 1 : 0];
10644
+ if (node) {
10645
+ if (isCaretContainer$2(node)) {
10646
+ return Optional.none();
10647
+ }
10648
+ if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
10649
+ return Optional.none();
10650
+ }
10887
10651
  }
10888
- editorManager.setActive(editor);
10889
- editorManager.focusedEditor = editor;
10890
- editor.dispatch('focus', { blurredEditor: focusedEditor });
10891
- editor.focus(true);
10892
10652
  }
10893
- });
10894
- editor.on('focusout', () => {
10895
- Delay.setEditorTimeout(editor, () => {
10896
- const focusedEditor = editorManager.focusedEditor;
10897
- if (!isEditorContentAreaElement(getActiveElement(editor)) || focusedEditor !== editor) {
10898
- toggleContentAreaOnFocus(editor, remove$6);
10653
+ if (container.hasChildNodes()) {
10654
+ offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
10655
+ container = container.childNodes[offset];
10656
+ offset = isText$b(container) && isAfterNode ? container.data.length : 0;
10657
+ if (!collapsed && container === body.lastChild && isTable$2(container)) {
10658
+ return Optional.none();
10899
10659
  }
10900
- if (!isUIElement(editor, getActiveElement(editor)) && focusedEditor === editor) {
10901
- editor.dispatch('blur', { focusedEditor: null });
10902
- editorManager.focusedEditor = null;
10660
+ if (hasContentEditableFalseParent(body, container) || isCaretContainer$2(container)) {
10661
+ return Optional.none();
10903
10662
  }
10904
- });
10905
- });
10906
- if (!documentFocusInHandler) {
10907
- documentFocusInHandler = e => {
10908
- const activeEditor = editorManager.activeEditor;
10909
- if (activeEditor) {
10910
- getOriginalEventTarget(e).each(target => {
10911
- const elem = target;
10912
- if (elem.ownerDocument === document) {
10913
- if (elem !== document.body && !isUIElement(activeEditor, elem) && editorManager.focusedEditor === activeEditor) {
10914
- activeEditor.dispatch('blur', { focusedEditor: null });
10915
- editorManager.focusedEditor = null;
10663
+ if (isDetails(container)) {
10664
+ return Optional.none();
10665
+ }
10666
+ if (container.hasChildNodes() && !isTable$2(container)) {
10667
+ node = container;
10668
+ const walker = new DomTreeWalker(container, body);
10669
+ do {
10670
+ if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) {
10671
+ normalized = false;
10672
+ break;
10673
+ }
10674
+ if (isText$b(node) && node.data.length > 0) {
10675
+ offset = directionLeft ? 0 : node.data.length;
10676
+ container = node;
10677
+ normalized = true;
10678
+ break;
10679
+ }
10680
+ if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCellOrCaption(node)) {
10681
+ offset = dom.nodeIndex(node);
10682
+ container = node.parentNode;
10683
+ if (!directionLeft) {
10684
+ offset++;
10916
10685
  }
10686
+ normalized = true;
10687
+ break;
10917
10688
  }
10689
+ } while (node = directionLeft ? walker.next() : walker.prev());
10690
+ }
10691
+ }
10692
+ }
10693
+ if (collapsed) {
10694
+ if (isText$b(container) && offset === 0) {
10695
+ findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(pos => {
10696
+ container = pos.container();
10697
+ offset = pos.offset();
10698
+ normalized = true;
10699
+ });
10700
+ }
10701
+ if (isElement$6(container)) {
10702
+ node = container.childNodes[offset];
10703
+ if (!node) {
10704
+ node = container.childNodes[offset - 1];
10705
+ }
10706
+ if (node && isBr$6(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) {
10707
+ findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(pos => {
10708
+ container = pos.container();
10709
+ offset = pos.offset();
10710
+ normalized = true;
10918
10711
  });
10919
10712
  }
10920
- };
10921
- DOM$9.bind(document, 'focusin', documentFocusInHandler);
10713
+ }
10714
+ }
10715
+ if (directionLeft && !collapsed && isText$b(container) && offset === container.data.length) {
10716
+ findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(pos => {
10717
+ container = pos.container();
10718
+ offset = pos.offset();
10719
+ normalized = true;
10720
+ });
10922
10721
  }
10722
+ return normalized && container ? Optional.some(CaretPosition(container, offset)) : Optional.none();
10923
10723
  };
10924
- const unregisterDocumentEvents = (editorManager, e) => {
10925
- if (editorManager.focusedEditor === e.editor) {
10926
- editorManager.focusedEditor = null;
10724
+ const normalize$2 = (dom, rng) => {
10725
+ const collapsed = rng.collapsed, normRng = rng.cloneRange();
10726
+ const startPos = CaretPosition.fromRangeStart(rng);
10727
+ normalizeEndPoint(dom, collapsed, true, normRng).each(pos => {
10728
+ if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
10729
+ normRng.setStart(pos.container(), pos.offset());
10730
+ }
10731
+ });
10732
+ if (!collapsed) {
10733
+ normalizeEndPoint(dom, collapsed, false, normRng).each(pos => {
10734
+ normRng.setEnd(pos.container(), pos.offset());
10735
+ });
10927
10736
  }
10928
- if (!editorManager.activeEditor && documentFocusInHandler) {
10929
- DOM$9.unbind(document, 'focusin', documentFocusInHandler);
10930
- documentFocusInHandler = null;
10737
+ if (collapsed) {
10738
+ normRng.collapse(true);
10931
10739
  }
10932
- };
10933
- const setup$w = editorManager => {
10934
- editorManager.on('AddEditor', curry(registerEvents$1, editorManager));
10935
- editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
10740
+ return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng);
10936
10741
  };
10937
10742
 
10938
- const getContentEditableHost = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'true');
10939
- const hasContentEditableFalseParent = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'false') !== null;
10940
- const getCollapsedNode = rng => rng.collapsed ? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(SugarElement.fromDom) : Optional.none();
10941
- const getFocusInElement = (root, rng) => getCollapsedNode(rng).bind(node => {
10942
- if (isTableSection(node)) {
10943
- return Optional.some(node);
10944
- } else if (!contains(root, node)) {
10945
- return Optional.some(root);
10743
+ const splitText = (node, offset) => {
10744
+ return node.splitText(offset);
10745
+ };
10746
+ const split = rng => {
10747
+ let startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
10748
+ if (startContainer === endContainer && isText$b(startContainer)) {
10749
+ if (startOffset > 0 && startOffset < startContainer.data.length) {
10750
+ endContainer = splitText(startContainer, startOffset);
10751
+ startContainer = endContainer.previousSibling;
10752
+ if (endOffset > startOffset) {
10753
+ endOffset = endOffset - startOffset;
10754
+ const newContainer = splitText(endContainer, endOffset).previousSibling;
10755
+ startContainer = endContainer = newContainer;
10756
+ endOffset = newContainer.data.length;
10757
+ startOffset = 0;
10758
+ } else {
10759
+ endOffset = 0;
10760
+ }
10761
+ }
10946
10762
  } else {
10947
- return Optional.none();
10763
+ if (isText$b(startContainer) && startOffset > 0 && startOffset < startContainer.data.length) {
10764
+ startContainer = splitText(startContainer, startOffset);
10765
+ startOffset = 0;
10766
+ }
10767
+ if (isText$b(endContainer) && endOffset > 0 && endOffset < endContainer.data.length) {
10768
+ const newContainer = splitText(endContainer, endOffset).previousSibling;
10769
+ endContainer = newContainer;
10770
+ endOffset = newContainer.data.length;
10771
+ }
10948
10772
  }
10949
- });
10950
- const normalizeSelection = (editor, rng) => {
10951
- getFocusInElement(SugarElement.fromDom(editor.getBody()), rng).bind(elm => {
10952
- return firstPositionIn(elm.dom);
10953
- }).fold(() => {
10954
- editor.selection.normalize();
10955
- }, caretPos => editor.selection.setRng(caretPos.toRange()));
10773
+ return {
10774
+ startContainer,
10775
+ startOffset,
10776
+ endContainer,
10777
+ endOffset
10778
+ };
10956
10779
  };
10957
- const focusBody = body => {
10958
- if (body.setActive) {
10959
- try {
10960
- body.setActive();
10961
- } catch (ex) {
10962
- body.focus();
10780
+
10781
+ const RangeUtils = dom => {
10782
+ const walk = (rng, callback) => {
10783
+ return walk$3(dom, rng, callback);
10784
+ };
10785
+ const split$1 = split;
10786
+ const normalize = rng => {
10787
+ return normalize$2(dom, rng).fold(never, normalizedRng => {
10788
+ rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
10789
+ rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
10790
+ return true;
10791
+ });
10792
+ };
10793
+ const expand = (rng, options = { type: 'word' }) => {
10794
+ if (options.type === 'word') {
10795
+ const rangeLike = expandRng(dom, rng, [{ inline: 'span' }]);
10796
+ const newRange = dom.createRng();
10797
+ newRange.setStart(rangeLike.startContainer, rangeLike.startOffset);
10798
+ newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset);
10799
+ return newRange;
10800
+ }
10801
+ return rng;
10802
+ };
10803
+ return {
10804
+ walk,
10805
+ split: split$1,
10806
+ expand,
10807
+ normalize
10808
+ };
10809
+ };
10810
+ RangeUtils.compareRanges = isEq$4;
10811
+ RangeUtils.getCaretRangeFromPoint = fromPoint;
10812
+ RangeUtils.getSelectedNode = getSelectedNode;
10813
+ RangeUtils.getNode = getNode$1;
10814
+
10815
+ const Dimension = (name, getOffset) => {
10816
+ const set = (element, h) => {
10817
+ if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
10818
+ throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
10819
+ }
10820
+ const dom = element.dom;
10821
+ if (isSupported(dom)) {
10822
+ dom.style[name] = h + 'px';
10823
+ }
10824
+ };
10825
+ const get = element => {
10826
+ const r = getOffset(element);
10827
+ if (r <= 0 || r === null) {
10828
+ const css = get$7(element, name);
10829
+ return parseFloat(css) || 0;
10963
10830
  }
10831
+ return r;
10832
+ };
10833
+ const getOuter = get;
10834
+ const aggregate = (element, properties) => foldl(properties, (acc, property) => {
10835
+ const val = get$7(element, property);
10836
+ const value = val === undefined ? 0 : parseInt(val, 10);
10837
+ return isNaN(value) ? acc : acc + value;
10838
+ }, 0);
10839
+ const max = (element, value, properties) => {
10840
+ const cumulativeInclusions = aggregate(element, properties);
10841
+ const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
10842
+ return absoluteMax;
10843
+ };
10844
+ return {
10845
+ set,
10846
+ get,
10847
+ getOuter,
10848
+ aggregate,
10849
+ max
10850
+ };
10851
+ };
10852
+
10853
+ const api = Dimension('height', element => {
10854
+ const dom = element.dom;
10855
+ return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
10856
+ });
10857
+ const get$2 = element => api.get(element);
10858
+
10859
+ const walkUp = (navigation, doc) => {
10860
+ const frame = navigation.view(doc);
10861
+ return frame.fold(constant([]), f => {
10862
+ const parent = navigation.owner(f);
10863
+ const rest = walkUp(navigation, parent);
10864
+ return [f].concat(rest);
10865
+ });
10866
+ };
10867
+ const pathTo = (element, navigation) => {
10868
+ const d = navigation.owner(element);
10869
+ return walkUp(navigation, d);
10870
+ };
10871
+
10872
+ const view = doc => {
10873
+ var _a;
10874
+ const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
10875
+ return element.map(SugarElement.fromDom);
10876
+ };
10877
+ const owner = element => documentOrOwner(element);
10878
+
10879
+ var Navigation = /*#__PURE__*/Object.freeze({
10880
+ __proto__: null,
10881
+ view: view,
10882
+ owner: owner
10883
+ });
10884
+
10885
+ const find = element => {
10886
+ const doc = getDocument();
10887
+ const scroll = get$5(doc);
10888
+ const frames = pathTo(element, Navigation);
10889
+ const offset = viewport(element);
10890
+ const r = foldr(frames, (b, a) => {
10891
+ const loc = viewport(a);
10892
+ return {
10893
+ left: b.left + loc.left,
10894
+ top: b.top + loc.top
10895
+ };
10896
+ }, {
10897
+ left: 0,
10898
+ top: 0
10899
+ });
10900
+ return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
10901
+ };
10902
+
10903
+ const excludeFromDescend = element => name(element) === 'textarea';
10904
+ const fireScrollIntoViewEvent = (editor, data) => {
10905
+ const scrollEvent = editor.dispatch('ScrollIntoView', data);
10906
+ return scrollEvent.isDefaultPrevented();
10907
+ };
10908
+ const fireAfterScrollIntoViewEvent = (editor, data) => {
10909
+ editor.dispatch('AfterScrollIntoView', data);
10910
+ };
10911
+ const descend = (element, offset) => {
10912
+ const children = children$1(element);
10913
+ if (children.length === 0 || excludeFromDescend(element)) {
10914
+ return {
10915
+ element,
10916
+ offset
10917
+ };
10918
+ } else if (offset < children.length && !excludeFromDescend(children[offset])) {
10919
+ return {
10920
+ element: children[offset],
10921
+ offset: 0
10922
+ };
10964
10923
  } else {
10965
- body.focus();
10924
+ const last = children[children.length - 1];
10925
+ if (excludeFromDescend(last)) {
10926
+ return {
10927
+ element,
10928
+ offset
10929
+ };
10930
+ } else {
10931
+ if (name(last) === 'img') {
10932
+ return {
10933
+ element: last,
10934
+ offset: 1
10935
+ };
10936
+ } else if (isText$c(last)) {
10937
+ return {
10938
+ element: last,
10939
+ offset: get$3(last).length
10940
+ };
10941
+ } else {
10942
+ return {
10943
+ element: last,
10944
+ offset: children$1(last).length
10945
+ };
10946
+ }
10947
+ }
10966
10948
  }
10967
10949
  };
10968
- const hasElementFocus = elm => hasFocus$1(elm) || search(elm).isSome();
10969
- const hasIframeFocus = editor => isNonNullable(editor.iframeElement) && hasFocus$1(SugarElement.fromDom(editor.iframeElement));
10970
- const hasInlineFocus = editor => {
10971
- const rawBody = editor.getBody();
10972
- return rawBody && hasElementFocus(SugarElement.fromDom(rawBody));
10950
+ const markerInfo = (element, cleanupFun) => {
10951
+ const pos = absolute(element);
10952
+ const height = get$2(element);
10953
+ return {
10954
+ element,
10955
+ bottom: pos.top + height,
10956
+ height,
10957
+ pos,
10958
+ cleanup: cleanupFun
10959
+ };
10973
10960
  };
10974
- const hasUiFocus = editor => {
10975
- const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
10976
- return active$1(dos).filter(elem => !isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)).isSome();
10961
+ const createMarker$1 = (element, offset) => {
10962
+ const startPoint = descend(element, offset);
10963
+ const span = SugarElement.fromHtml('<span data-mce-bogus="all" style="display: inline-block;">' + ZWSP$1 + '</span>');
10964
+ before$3(startPoint.element, span);
10965
+ return markerInfo(span, () => remove$4(span));
10977
10966
  };
10978
- const hasFocus = editor => editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
10979
- const hasEditorOrUiFocus = editor => hasFocus(editor) || hasUiFocus(editor);
10980
- const focusEditor = editor => {
10981
- const selection = editor.selection;
10982
- const body = editor.getBody();
10983
- let rng = selection.getRng();
10984
- editor.quirks.refreshContentEditable();
10985
- const restoreBookmark = editor => {
10986
- getRng(editor).each(bookmarkRng => {
10987
- editor.selection.setRng(bookmarkRng);
10988
- rng = bookmarkRng;
10989
- });
10967
+ const elementMarker = element => markerInfo(SugarElement.fromDom(element), noop);
10968
+ const withMarker = (editor, f, rng, alignToTop) => {
10969
+ preserveWith(editor, (_s, _e) => applyWithMarker(editor, f, rng, alignToTop), rng);
10970
+ };
10971
+ const withScrollEvents = (editor, doc, f, marker, alignToTop) => {
10972
+ const data = {
10973
+ elm: marker.element.dom,
10974
+ alignToTop
10990
10975
  };
10991
- if (!hasFocus(editor) && editor.hasEditableRoot()) {
10992
- restoreBookmark(editor);
10993
- }
10994
- const contentEditableHost = getContentEditableHost(editor, selection.getNode());
10995
- if (contentEditableHost && editor.dom.isChildOf(contentEditableHost, body)) {
10996
- if (!hasContentEditableFalseParent(editor, contentEditableHost)) {
10997
- focusBody(body);
10998
- }
10999
- focusBody(contentEditableHost);
11000
- if (!editor.hasEditableRoot()) {
11001
- restoreBookmark(editor);
11002
- }
11003
- normalizeSelection(editor, rng);
11004
- activateEditor(editor);
10976
+ if (fireScrollIntoViewEvent(editor, data)) {
11005
10977
  return;
11006
10978
  }
11007
- if (!editor.inline) {
11008
- if (!Env.browser.isOpera()) {
11009
- focusBody(body);
11010
- }
11011
- editor.getWin().focus();
11012
- }
11013
- if (Env.browser.isFirefox() || editor.inline) {
11014
- focusBody(body);
11015
- normalizeSelection(editor, rng);
10979
+ const scrollTop = get$5(doc).top;
10980
+ f(editor, doc, scrollTop, marker, alignToTop);
10981
+ fireAfterScrollIntoViewEvent(editor, data);
10982
+ };
10983
+ const applyWithMarker = (editor, f, rng, alignToTop) => {
10984
+ const body = SugarElement.fromDom(editor.getBody());
10985
+ const doc = SugarElement.fromDom(editor.getDoc());
10986
+ reflow(body);
10987
+ const marker = createMarker$1(SugarElement.fromDom(rng.startContainer), rng.startOffset);
10988
+ withScrollEvents(editor, doc, f, marker, alignToTop);
10989
+ marker.cleanup();
10990
+ };
10991
+ const withElement = (editor, element, f, alignToTop) => {
10992
+ const doc = SugarElement.fromDom(editor.getDoc());
10993
+ withScrollEvents(editor, doc, f, elementMarker(element), alignToTop);
10994
+ };
10995
+ const preserveWith = (editor, f, rng) => {
10996
+ const startElement = rng.startContainer;
10997
+ const startOffset = rng.startOffset;
10998
+ const endElement = rng.endContainer;
10999
+ const endOffset = rng.endOffset;
11000
+ f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement));
11001
+ const newRng = editor.dom.createRng();
11002
+ newRng.setStart(startElement, startOffset);
11003
+ newRng.setEnd(endElement, endOffset);
11004
+ editor.selection.setRng(rng);
11005
+ };
11006
+ const scrollToMarker = (editor, marker, viewHeight, alignToTop, doc) => {
11007
+ const pos = marker.pos;
11008
+ if (alignToTop) {
11009
+ to(pos.left, pos.top, doc);
11010
+ } else {
11011
+ const y = pos.top - viewHeight + marker.height;
11012
+ to(-editor.getBody().getBoundingClientRect().left, y, doc);
11016
11013
  }
11017
- activateEditor(editor);
11018
11014
  };
11019
- const activateEditor = editor => editor.editorManager.setActive(editor);
11020
- const focus = (editor, skipFocus) => {
11021
- if (editor.removed) {
11022
- return;
11015
+ const intoWindowIfNeeded = (editor, doc, scrollTop, viewHeight, marker, alignToTop) => {
11016
+ const viewportBottom = viewHeight + scrollTop;
11017
+ const markerTop = marker.pos.top;
11018
+ const markerBottom = marker.bottom;
11019
+ const largerThanViewport = markerBottom - markerTop >= viewHeight;
11020
+ if (markerTop < scrollTop) {
11021
+ scrollToMarker(editor, marker, viewHeight, alignToTop !== false, doc);
11022
+ } else if (markerTop > viewportBottom) {
11023
+ const align = largerThanViewport ? alignToTop !== false : alignToTop === true;
11024
+ scrollToMarker(editor, marker, viewHeight, align, doc);
11025
+ } else if (markerBottom > viewportBottom && !largerThanViewport) {
11026
+ scrollToMarker(editor, marker, viewHeight, alignToTop === true, doc);
11023
11027
  }
11024
- if (skipFocus) {
11025
- activateEditor(editor);
11026
- } else {
11027
- focusEditor(editor);
11028
+ };
11029
+ const intoWindow = (editor, doc, scrollTop, marker, alignToTop) => {
11030
+ const viewHeight = defaultView(doc).dom.innerHeight;
11031
+ intoWindowIfNeeded(editor, doc, scrollTop, viewHeight, marker, alignToTop);
11032
+ };
11033
+ const intoFrame = (editor, doc, scrollTop, marker, alignToTop) => {
11034
+ const frameViewHeight = defaultView(doc).dom.innerHeight;
11035
+ intoWindowIfNeeded(editor, doc, scrollTop, frameViewHeight, marker, alignToTop);
11036
+ const op = find(marker.element);
11037
+ const viewportBounds = getBounds(window);
11038
+ if (op.top < viewportBounds.y) {
11039
+ intoView(marker.element, alignToTop !== false);
11040
+ } else if (op.top > viewportBounds.bottom) {
11041
+ intoView(marker.element, alignToTop === true);
11028
11042
  }
11029
11043
  };
11044
+ const rangeIntoWindow = (editor, rng, alignToTop) => withMarker(editor, intoWindow, rng, alignToTop);
11045
+ const elementIntoWindow = (editor, element, alignToTop) => withElement(editor, element, intoWindow, alignToTop);
11046
+ const rangeIntoFrame = (editor, rng, alignToTop) => withMarker(editor, intoFrame, rng, alignToTop);
11047
+ const elementIntoFrame = (editor, element, alignToTop) => withElement(editor, element, intoFrame, alignToTop);
11048
+ const scrollElementIntoView = (editor, element, alignToTop) => {
11049
+ const scroller = editor.inline ? elementIntoWindow : elementIntoFrame;
11050
+ scroller(editor, element, alignToTop);
11051
+ };
11052
+ const scrollRangeIntoView = (editor, rng, alignToTop) => {
11053
+ const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame;
11054
+ scroller(editor, rng, alignToTop);
11055
+ };
11030
11056
 
11031
11057
  const isEditableRange = (dom, rng) => {
11032
11058
  if (rng.collapsed) {
@@ -11521,7 +11547,7 @@
11521
11547
  const doc = editor.getDoc();
11522
11548
  const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
11523
11549
  const offscreenDiv = SugarElement.fromTag('div', doc);
11524
- set$3(offscreenDiv, 'data-mce-bogus', 'all');
11550
+ set$4(offscreenDiv, 'data-mce-bogus', 'all');
11525
11551
  setAll(offscreenDiv, {
11526
11552
  position: 'fixed',
11527
11553
  left: '-9999999px',
@@ -12466,7 +12492,7 @@
12466
12492
  editor.selection.collapse(true);
12467
12493
  }
12468
12494
  if (selectedCells.length > 1 && exists(selectedCells, cell => eq(cell, selectedNode))) {
12469
- set$3(selectedNode, 'data-mce-selected', '1');
12495
+ set$4(selectedNode, 'data-mce-selected', '1');
12470
12496
  }
12471
12497
  };
12472
12498
  const emptySingleTableCells = (editor, cells, outsideDetails) => Optional.some(() => {
@@ -15001,13 +15027,21 @@
15001
15027
  const matches = /([a-z0-9+\/=\s]+)/i.exec(data);
15002
15028
  return matches ? matches[1] : '';
15003
15029
  };
15030
+ const decodeData = data => {
15031
+ try {
15032
+ return decodeURIComponent(data);
15033
+ } catch (_a) {
15034
+ return data;
15035
+ }
15036
+ };
15004
15037
  const parseDataUri = uri => {
15005
15038
  const [type, ...rest] = uri.split(',');
15006
15039
  const data = rest.join(',');
15007
15040
  const matches = /data:([^/]+\/[^;]+)(;.+)?/.exec(type);
15008
15041
  if (matches) {
15009
15042
  const base64Encoded = matches[2] === ';base64';
15010
- const extractedData = base64Encoded ? extractBase64Data(data) : decodeURIComponent(data);
15043
+ const decodedData = decodeData(data);
15044
+ const extractedData = base64Encoded ? extractBase64Data(decodedData) : decodedData;
15011
15045
  return Optional.some({
15012
15046
  type: matches[1],
15013
15047
  data: extractedData,
@@ -17182,11 +17216,11 @@
17182
17216
  }
17183
17217
  if (validate && rule && !isInternalElement) {
17184
17218
  each$e((_c = rule.attributesForced) !== null && _c !== void 0 ? _c : [], attr => {
17185
- set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
17219
+ set$4(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
17186
17220
  });
17187
17221
  each$e((_d = rule.attributesDefault) !== null && _d !== void 0 ? _d : [], attr => {
17188
17222
  if (!has$1(element, attr.name)) {
17189
- set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
17223
+ set$4(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
17190
17224
  }
17191
17225
  });
17192
17226
  if (rule.attributesRequired && !exists(rule.attributesRequired, attr => has$1(element, attr))) {
@@ -19800,41 +19834,182 @@
19800
19834
  fireError(editor, errorType, { message: msg });
19801
19835
  console.error(msg);
19802
19836
  };
19803
- const createLoadError = (type, url, name) => name ? `Failed to load ${ type }: ${ name } from url ${ url }` : `Failed to load ${ type } url: ${ url }`;
19804
- const pluginLoadError = (editor, url, name) => {
19805
- logError(editor, 'PluginLoadError', createLoadError('plugin', url, name));
19837
+ const createLoadError = (type, url, name) => name ? `Failed to load ${ type }: ${ name } from url ${ url }` : `Failed to load ${ type } url: ${ url }`;
19838
+ const pluginLoadError = (editor, url, name) => {
19839
+ logError(editor, 'PluginLoadError', createLoadError('plugin', url, name));
19840
+ };
19841
+ const iconsLoadError = (editor, url, name) => {
19842
+ logError(editor, 'IconsLoadError', createLoadError('icons', url, name));
19843
+ };
19844
+ const languageLoadError = (editor, url, name) => {
19845
+ logError(editor, 'LanguageLoadError', createLoadError('language', url, name));
19846
+ };
19847
+ const themeLoadError = (editor, url, name) => {
19848
+ logError(editor, 'ThemeLoadError', createLoadError('theme', url, name));
19849
+ };
19850
+ const modelLoadError = (editor, url, name) => {
19851
+ logError(editor, 'ModelLoadError', createLoadError('model', url, name));
19852
+ };
19853
+ const pluginInitError = (editor, name, err) => {
19854
+ const message = I18n.translate([
19855
+ 'Failed to initialize plugin: {0}',
19856
+ name
19857
+ ]);
19858
+ fireError(editor, 'PluginLoadError', { message });
19859
+ initError(message, err);
19860
+ displayError(editor, message);
19861
+ };
19862
+ const initError = (message, ...x) => {
19863
+ const console = window.console;
19864
+ if (console) {
19865
+ if (console.error) {
19866
+ console.error(message, ...x);
19867
+ } else {
19868
+ console.log(message, ...x);
19869
+ }
19870
+ }
19871
+ };
19872
+
19873
+ const removeFakeSelection = editor => {
19874
+ Optional.from(editor.selection.getNode()).each(elm => {
19875
+ elm.removeAttribute('data-mce-selected');
19876
+ });
19877
+ };
19878
+ const setEditorCommandState = (editor, cmd, state) => {
19879
+ try {
19880
+ editor.getDoc().execCommand(cmd, false, String(state));
19881
+ } catch (ex) {
19882
+ }
19883
+ };
19884
+ const setCommonEditorCommands = (editor, state) => {
19885
+ setEditorCommandState(editor, 'StyleWithCSS', state);
19886
+ setEditorCommandState(editor, 'enableInlineTableEditing', state);
19887
+ setEditorCommandState(editor, 'enableObjectResizing', state);
19888
+ };
19889
+ const restoreFakeSelection = editor => {
19890
+ editor.selection.setRng(editor.selection.getRng());
19891
+ };
19892
+ const toggleClass = (elm, cls, state) => {
19893
+ if (has(elm, cls) && !state) {
19894
+ remove$6(elm, cls);
19895
+ } else if (state) {
19896
+ add$2(elm, cls);
19897
+ }
19898
+ };
19899
+ const disableEditor = editor => {
19900
+ const body = SugarElement.fromDom(editor.getBody());
19901
+ toggleClass(body, 'mce-content-readonly', true);
19902
+ editor.selection.controlSelection.hideResizeRect();
19903
+ editor._selectionOverrides.hideFakeCaret();
19904
+ removeFakeSelection(editor);
19905
+ };
19906
+ const enableEditor = editor => {
19907
+ const body = SugarElement.fromDom(editor.getBody());
19908
+ toggleClass(body, 'mce-content-readonly', false);
19909
+ if (editor.hasEditableRoot()) {
19910
+ set$3(body, true);
19911
+ }
19912
+ setCommonEditorCommands(editor, false);
19913
+ if (hasEditorOrUiFocus(editor)) {
19914
+ editor.focus();
19915
+ }
19916
+ restoreFakeSelection(editor);
19917
+ editor.nodeChanged();
19918
+ };
19919
+
19920
+ const isDisabled = editor => isDisabled$1(editor);
19921
+ const internalContentEditableAttr = 'data-mce-contenteditable';
19922
+ const switchOffContentEditableTrue = elm => {
19923
+ each$e(descendants(elm, '*[contenteditable="true"]'), elm => {
19924
+ set$4(elm, internalContentEditableAttr, 'true');
19925
+ set$3(elm, false);
19926
+ });
19806
19927
  };
19807
- const iconsLoadError = (editor, url, name) => {
19808
- logError(editor, 'IconsLoadError', createLoadError('icons', url, name));
19928
+ const switchOnContentEditableTrue = elm => {
19929
+ each$e(descendants(elm, `*[${ internalContentEditableAttr }="true"]`), elm => {
19930
+ remove$9(elm, internalContentEditableAttr);
19931
+ set$3(elm, true);
19932
+ });
19809
19933
  };
19810
- const languageLoadError = (editor, url, name) => {
19811
- logError(editor, 'LanguageLoadError', createLoadError('language', url, name));
19934
+ const toggleDisabled = (editor, state) => {
19935
+ const body = SugarElement.fromDom(editor.getBody());
19936
+ if (state) {
19937
+ disableEditor(editor);
19938
+ set$3(body, false);
19939
+ switchOffContentEditableTrue(body);
19940
+ } else {
19941
+ switchOnContentEditableTrue(body);
19942
+ enableEditor(editor);
19943
+ }
19812
19944
  };
19813
- const themeLoadError = (editor, url, name) => {
19814
- logError(editor, 'ThemeLoadError', createLoadError('theme', url, name));
19945
+ const registerDisabledContentFilters = editor => {
19946
+ if (editor.serializer) {
19947
+ registerFilters(editor);
19948
+ } else {
19949
+ editor.on('PreInit', () => {
19950
+ registerFilters(editor);
19951
+ });
19952
+ }
19815
19953
  };
19816
- const modelLoadError = (editor, url, name) => {
19817
- logError(editor, 'ModelLoadError', createLoadError('model', url, name));
19954
+ const registerFilters = editor => {
19955
+ editor.parser.addAttributeFilter('contenteditable', nodes => {
19956
+ if (isDisabled(editor)) {
19957
+ each$e(nodes, node => {
19958
+ node.attr(internalContentEditableAttr, node.attr('contenteditable'));
19959
+ node.attr('contenteditable', 'false');
19960
+ });
19961
+ }
19962
+ });
19963
+ editor.serializer.addAttributeFilter(internalContentEditableAttr, nodes => {
19964
+ if (isDisabled(editor)) {
19965
+ each$e(nodes, node => {
19966
+ node.attr('contenteditable', node.attr(internalContentEditableAttr));
19967
+ });
19968
+ }
19969
+ });
19970
+ editor.serializer.addTempAttr(internalContentEditableAttr);
19818
19971
  };
19819
- const pluginInitError = (editor, name, err) => {
19820
- const message = I18n.translate([
19821
- 'Failed to initialize plugin: {0}',
19822
- name
19823
- ]);
19824
- fireError(editor, 'PluginLoadError', { message });
19825
- initError(message, err);
19826
- displayError(editor, message);
19972
+ const isClickEvent = e => e.type === 'click';
19973
+ const allowedEvents = ['copy'];
19974
+ const isAllowedEventInDisabledMode = e => contains$2(allowedEvents, e.type);
19975
+ const getAnchorHrefOpt = (editor, elm) => {
19976
+ const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
19977
+ return closest$3(elm, 'a', isRoot).bind(a => getOpt(a, 'href'));
19827
19978
  };
19828
- const initError = (message, ...x) => {
19829
- const console = window.console;
19830
- if (console) {
19831
- if (console.error) {
19832
- console.error(message, ...x);
19833
- } else {
19834
- console.log(message, ...x);
19835
- }
19979
+ const processDisabledEvents = (editor, e) => {
19980
+ if (isClickEvent(e) && !VK.metaKeyPressed(e)) {
19981
+ const elm = SugarElement.fromDom(e.target);
19982
+ getAnchorHrefOpt(editor, elm).each(href => {
19983
+ e.preventDefault();
19984
+ if (/^#/.test(href)) {
19985
+ const targetEl = editor.dom.select(`${ href },[name="${ removeLeading(href, '#') }"]`);
19986
+ if (targetEl.length) {
19987
+ editor.selection.scrollIntoView(targetEl[0], true);
19988
+ }
19989
+ } else {
19990
+ window.open(href, '_blank', 'rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes');
19991
+ }
19992
+ });
19993
+ } else if (isAllowedEventInDisabledMode(e)) {
19994
+ editor.dispatch(e.type, e);
19836
19995
  }
19837
19996
  };
19997
+ const registerDisabledModeEventHandlers = editor => {
19998
+ editor.on('ShowCaret ObjectSelected', e => {
19999
+ if (isDisabled(editor)) {
20000
+ e.preventDefault();
20001
+ }
20002
+ });
20003
+ editor.on('DisabledStateChange', e => {
20004
+ if (!e.isDefaultPrevented()) {
20005
+ toggleDisabled(editor, e.state);
20006
+ }
20007
+ });
20008
+ };
20009
+ const registerEventsAndFilters$1 = editor => {
20010
+ registerDisabledContentFilters(editor);
20011
+ registerDisabledModeEventHandlers(editor);
20012
+ };
19838
20013
 
19839
20014
  const isContentCssSkinName = url => /^[a-z0-9\-]+$/i.test(url);
19840
20015
  const toContentSkinResourceName = url => 'content/' + url + '/content.css';
@@ -20431,6 +20606,11 @@
20431
20606
  styles: { float: 'left' },
20432
20607
  preview: 'font-family font-size'
20433
20608
  },
20609
+ {
20610
+ selector: '.mce-placeholder',
20611
+ styles: { float: 'left' },
20612
+ ceFalseOverride: true
20613
+ },
20434
20614
  {
20435
20615
  selector: 'table',
20436
20616
  collapsed: false,
@@ -20473,6 +20653,15 @@
20473
20653
  },
20474
20654
  preview: false
20475
20655
  },
20656
+ {
20657
+ selector: '.mce-placeholder',
20658
+ styles: {
20659
+ display: 'block',
20660
+ marginLeft: 'auto',
20661
+ marginRight: 'auto'
20662
+ },
20663
+ ceFalseOverride: true
20664
+ },
20476
20665
  {
20477
20666
  selector: 'table',
20478
20667
  collapsed: false,
@@ -20522,6 +20711,11 @@
20522
20711
  styles: { float: 'right' },
20523
20712
  preview: 'font-family font-size'
20524
20713
  },
20714
+ {
20715
+ selector: '.mce-placeholder',
20716
+ styles: { float: 'right' },
20717
+ ceFalseOverride: true
20718
+ },
20525
20719
  {
20526
20720
  selector: 'table',
20527
20721
  collapsed: false,
@@ -20680,6 +20874,7 @@
20680
20874
  subscript: { inline: 'sub' },
20681
20875
  superscript: { inline: 'sup' },
20682
20876
  code: { inline: 'code' },
20877
+ samp: { inline: 'samp' },
20683
20878
  link: {
20684
20879
  inline: 'a',
20685
20880
  selector: 'a',
@@ -20739,7 +20934,7 @@
20739
20934
  }
20740
20935
  ]
20741
20936
  };
20742
- Tools.each('p h1 h2 h3 h4 h5 h6 div address pre dt dd samp'.split(/\s/), name => {
20937
+ Tools.each('p h1 h2 h3 h4 h5 h6 div address pre dt dd'.split(/\s/), name => {
20743
20938
  formats[name] = {
20744
20939
  block: name,
20745
20940
  remove: 'all'
@@ -24076,6 +24271,29 @@
24076
24271
  toString
24077
24272
  };
24078
24273
  };
24274
+ const oneOf = (props, rawF) => {
24275
+ const f = rawF !== undefined ? rawF : identity;
24276
+ const extract = (path, val) => {
24277
+ const errors = [];
24278
+ for (const prop of props) {
24279
+ const res = prop.extract(path, val);
24280
+ if (res.stype === SimpleResultType.Value) {
24281
+ return {
24282
+ stype: SimpleResultType.Value,
24283
+ svalue: f(res.svalue)
24284
+ };
24285
+ }
24286
+ errors.push(res);
24287
+ }
24288
+ return ResultCombine.consolidateArr(errors);
24289
+ };
24290
+ const toString = () => 'oneOf(' + map$3(props, prop => prop.toString()).join(', ') + ')';
24291
+ return {
24292
+ extract,
24293
+ toString
24294
+ };
24295
+ };
24296
+ const arrOfObj = compose(arrOf, objOf);
24079
24297
 
24080
24298
  const valueOf = validator => value(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
24081
24299
  const extractValue = (label, prop, obj) => {
@@ -24106,6 +24324,7 @@
24106
24324
  const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
24107
24325
  const requiredOf = (key, schema) => field(key, key, required(), schema);
24108
24326
  const requiredString = key => requiredOf(key, string);
24327
+ const requiredStringEnum = (key, values) => field(key, key, required(), validateEnum(values));
24109
24328
  const requiredFunction = key => requiredOf(key, functionProcessor);
24110
24329
  const requiredArrayOf = (key, schema) => field(key, key, required(), arrOf(schema));
24111
24330
  const optionOf = (key, schema) => field(key, key, asOption(), schema);
@@ -24173,12 +24392,14 @@
24173
24392
 
24174
24393
  const contextButtonFields = baseToolbarButtonFields.concat([
24175
24394
  defaultedType('contextformbutton'),
24395
+ defaultedString('align', 'end'),
24176
24396
  primary,
24177
24397
  onAction,
24178
24398
  customField('original', identity)
24179
24399
  ]);
24180
24400
  const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
24181
24401
  defaultedType('contextformbutton'),
24402
+ defaultedString('align', 'end'),
24182
24403
  primary,
24183
24404
  onAction,
24184
24405
  customField('original', identity)
@@ -24189,15 +24410,56 @@
24189
24410
  contextformbutton: contextButtonFields,
24190
24411
  contextformtogglebutton: contextToggleButtonFields
24191
24412
  });
24192
- objOf([
24193
- defaultedType('contextform'),
24194
- defaultedFunction('initValue', constant('')),
24413
+ const baseContextFormFields = [
24195
24414
  optionalLabel,
24196
24415
  requiredArrayOf('commands', toggleOrNormal),
24197
24416
  optionOf('launch', choose('type', {
24198
24417
  contextformbutton: launchButtonFields,
24199
24418
  contextformtogglebutton: launchToggleButtonFields
24419
+ })),
24420
+ defaultedFunction('onInput', noop),
24421
+ defaultedFunction('onSetup', noop)
24422
+ ];
24423
+ const contextFormFields = [
24424
+ ...contextBarFields,
24425
+ ...baseContextFormFields,
24426
+ requiredStringEnum('type', ['contextform']),
24427
+ defaultedFunction('initValue', constant('')),
24428
+ optionString('placeholder')
24429
+ ];
24430
+ const contextSliderFormFields = [
24431
+ ...contextBarFields,
24432
+ ...baseContextFormFields,
24433
+ requiredStringEnum('type', ['contextsliderform']),
24434
+ defaultedFunction('initValue', constant(0)),
24435
+ defaultedFunction('min', constant(0)),
24436
+ defaultedFunction('max', constant(100))
24437
+ ];
24438
+ const contextSizeInputFormFields = [
24439
+ ...contextBarFields,
24440
+ ...baseContextFormFields,
24441
+ requiredStringEnum('type', ['contextsizeinputform']),
24442
+ defaultedFunction('initValue', constant({
24443
+ width: '',
24444
+ height: ''
24200
24445
  }))
24446
+ ];
24447
+ choose('type', {
24448
+ contextform: contextFormFields,
24449
+ contextsliderform: contextSliderFormFields,
24450
+ contextsizeinputform: contextSizeInputFormFields
24451
+ });
24452
+
24453
+ objOf([
24454
+ defaultedType('contexttoolbar'),
24455
+ requiredOf('items', oneOf([
24456
+ string,
24457
+ arrOfObj([
24458
+ optionString('name'),
24459
+ optionString('label'),
24460
+ requiredArrayOf('items', string)
24461
+ ])
24462
+ ]))
24201
24463
  ].concat(contextBarFields));
24202
24464
 
24203
24465
  const register$2 = editor => {
@@ -25930,7 +26192,7 @@
25930
26192
  const editor = this.editor;
25931
26193
  const selection = editor.selection;
25932
26194
  let node;
25933
- if (editor.initialized && selection && !shouldDisableNodeChange(editor)) {
26195
+ if (editor.initialized && selection && !shouldDisableNodeChange(editor) && !isDisabled$1(editor)) {
25934
26196
  const root = editor.getBody();
25935
26197
  node = selection.getStart(true) || root;
25936
26198
  if (node.ownerDocument !== editor.getDoc() || !editor.dom.isChildOf(node, root)) {
@@ -27761,7 +28023,7 @@
27761
28023
  const doc = editor.getDoc();
27762
28024
  const realSelectionContainer = descendant$1(body, '#' + realSelectionId).getOrThunk(() => {
27763
28025
  const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc);
27764
- set$3(newContainer, 'id', realSelectionId);
28026
+ set$4(newContainer, 'id', realSelectionId);
27765
28027
  append$1(body, newContainer);
27766
28028
  return newContainer;
27767
28029
  });
@@ -28864,7 +29126,7 @@
28864
29126
  const body = SugarElement.fromDom(editor.getBody());
28865
29127
  const container = getStyleContainer(getRootNode(body));
28866
29128
  const style = SugarElement.fromTag('style');
28867
- set$3(style, 'type', 'text/css');
29129
+ set$4(style, 'type', 'text/css');
28868
29130
  append$1(style, SugarElement.fromText(text));
28869
29131
  append$1(container, style);
28870
29132
  editor.on('remove', () => {
@@ -29038,6 +29300,9 @@
29038
29300
  initInstanceCallback.call(editor, editor);
29039
29301
  }
29040
29302
  autoFocus(editor);
29303
+ if (isDisabled(editor)) {
29304
+ toggleDisabled(editor, true);
29305
+ }
29041
29306
  };
29042
29307
  const getStyleSheetLoader$1 = editor => editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader;
29043
29308
  const makeStylesheetLoadingPromises = (editor, css, framedFonts) => {
@@ -29165,7 +29430,7 @@
29165
29430
  body.disabled = true;
29166
29431
  editor.readonly = isReadOnly$1(editor);
29167
29432
  editor._editableRoot = hasEditableRoot$1(editor);
29168
- if (editor.hasEditableRoot()) {
29433
+ if (!isDisabled$1(editor) && editor.hasEditableRoot()) {
29169
29434
  if (editor.inline && DOM$6.getStyle(body, 'position', true) === 'static') {
29170
29435
  body.style.position = 'relative';
29171
29436
  }
@@ -29242,7 +29507,7 @@
29242
29507
  const DOM$5 = DOMUtils.DOM;
29243
29508
  const createIframeElement = (id, title, customAttrs, tabindex) => {
29244
29509
  const iframe = SugarElement.fromTag('iframe');
29245
- tabindex.each(t => set$3(iframe, 'tabindex', t));
29510
+ tabindex.each(t => set$4(iframe, 'tabindex', t));
29246
29511
  setAll$1(iframe, customAttrs);
29247
29512
  setAll$1(iframe, {
29248
29513
  id: id + '_ifr',
@@ -29424,7 +29689,7 @@
29424
29689
  hide: Optional.from(api.hide).getOr(noop),
29425
29690
  isEnabled: Optional.from(api.isEnabled).getOr(always),
29426
29691
  setEnabled: state => {
29427
- const shouldSkip = state && editor.mode.get() === 'readonly';
29692
+ const shouldSkip = state && (editor.mode.get() === 'readonly' || isDisabled(editor));
29428
29693
  if (!shouldSkip) {
29429
29694
  Optional.from(api.setEnabled).each(f => f(state));
29430
29695
  }
@@ -29638,8 +29903,10 @@
29638
29903
  const setEditableRoot = (editor, state) => {
29639
29904
  if (editor._editableRoot !== state) {
29640
29905
  editor._editableRoot = state;
29641
- editor.getBody().contentEditable = String(editor.hasEditableRoot());
29642
- editor.nodeChanged();
29906
+ if (!isDisabled(editor)) {
29907
+ editor.getBody().contentEditable = String(editor.hasEditableRoot());
29908
+ editor.nodeChanged();
29909
+ }
29643
29910
  fireEditableRootStateChange(editor, state);
29644
29911
  }
29645
29912
  };
@@ -30327,120 +30594,6 @@
30327
30594
  }
30328
30595
  }
30329
30596
 
30330
- const toggleClass = (elm, cls, state) => {
30331
- if (has(elm, cls) && !state) {
30332
- remove$6(elm, cls);
30333
- } else if (state) {
30334
- add$2(elm, cls);
30335
- }
30336
- };
30337
- const setEditorCommandState = (editor, cmd, state) => {
30338
- try {
30339
- editor.getDoc().execCommand(cmd, false, String(state));
30340
- } catch (ex) {
30341
- }
30342
- };
30343
- const setContentEditable = (elm, state) => {
30344
- elm.dom.contentEditable = state ? 'true' : 'false';
30345
- };
30346
- const removeFakeSelection = editor => {
30347
- Optional.from(editor.selection.getNode()).each(elm => {
30348
- elm.removeAttribute('data-mce-selected');
30349
- });
30350
- };
30351
- const restoreFakeSelection = editor => {
30352
- editor.selection.setRng(editor.selection.getRng());
30353
- };
30354
- const setCommonEditorCommands = (editor, state) => {
30355
- setEditorCommandState(editor, 'StyleWithCSS', state);
30356
- setEditorCommandState(editor, 'enableInlineTableEditing', state);
30357
- setEditorCommandState(editor, 'enableObjectResizing', state);
30358
- };
30359
- const setEditorReadonly = editor => {
30360
- editor.readonly = true;
30361
- editor.selection.controlSelection.hideResizeRect();
30362
- editor._selectionOverrides.hideFakeCaret();
30363
- removeFakeSelection(editor);
30364
- };
30365
- const unsetEditorReadonly = (editor, body) => {
30366
- editor.readonly = false;
30367
- if (editor.hasEditableRoot()) {
30368
- setContentEditable(body, true);
30369
- }
30370
- setCommonEditorCommands(editor, false);
30371
- if (hasEditorOrUiFocus(editor)) {
30372
- editor.focus();
30373
- }
30374
- restoreFakeSelection(editor);
30375
- editor.nodeChanged();
30376
- };
30377
- const toggleReadOnly = (editor, state) => {
30378
- const body = SugarElement.fromDom(editor.getBody());
30379
- toggleClass(body, 'mce-content-readonly', state);
30380
- if (state) {
30381
- setEditorReadonly(editor);
30382
- if (editor.hasEditableRoot()) {
30383
- setContentEditable(body, true);
30384
- }
30385
- } else {
30386
- unsetEditorReadonly(editor, body);
30387
- }
30388
- };
30389
- const isReadOnly = editor => editor.readonly;
30390
- const isClickEvent = e => e.type === 'click';
30391
- const allowedEvents = ['copy'];
30392
- const isReadOnlyAllowedEvent = e => contains$2(allowedEvents, e.type);
30393
- const getAnchorHrefOpt = (editor, elm) => {
30394
- const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
30395
- return closest$3(elm, 'a', isRoot).bind(a => getOpt(a, 'href'));
30396
- };
30397
- const processReadonlyEvents = (editor, e) => {
30398
- if (isClickEvent(e) && !VK.metaKeyPressed(e)) {
30399
- const elm = SugarElement.fromDom(e.target);
30400
- getAnchorHrefOpt(editor, elm).each(href => {
30401
- e.preventDefault();
30402
- if (/^#/.test(href)) {
30403
- const targetEl = editor.dom.select(`${ href },[name="${ removeLeading(href, '#') }"]`);
30404
- if (targetEl.length) {
30405
- editor.selection.scrollIntoView(targetEl[0], true);
30406
- }
30407
- } else {
30408
- window.open(href, '_blank', 'rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes');
30409
- }
30410
- });
30411
- } else if (isReadOnlyAllowedEvent(e)) {
30412
- editor.dispatch(e.type, e);
30413
- }
30414
- };
30415
- const registerReadOnlySelectionBlockers = editor => {
30416
- editor.on('beforeinput paste cut dragend dragover draggesture dragdrop drop drag', e => {
30417
- if (isReadOnly(editor)) {
30418
- e.preventDefault();
30419
- }
30420
- });
30421
- editor.on('BeforeExecCommand', e => {
30422
- if ((e.command === 'Undo' || e.command === 'Redo') && isReadOnly(editor)) {
30423
- e.preventDefault();
30424
- }
30425
- });
30426
- editor.on('input', e => {
30427
- if (!e.isComposing && isReadOnly(editor)) {
30428
- const undoLevel = editor.undoManager.add();
30429
- if (isNonNullable(undoLevel)) {
30430
- editor.undoManager.undo();
30431
- }
30432
- }
30433
- });
30434
- editor.on('compositionend', () => {
30435
- if (isReadOnly(editor)) {
30436
- const undoLevel = editor.undoManager.add();
30437
- if (isNonNullable(undoLevel)) {
30438
- editor.undoManager.undo();
30439
- }
30440
- }
30441
- });
30442
- };
30443
-
30444
30597
  const nativeEvents = Tools.makeMap('focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange ' + 'mouseout mouseenter mouseleave wheel keydown keypress keyup input beforeinput contextmenu dragstart dragend dragover ' + 'draggesture dragdrop drop drag submit ' + 'compositionstart compositionend compositionupdate touchstart touchmove touchend touchcancel', ' ');
30445
30598
  class EventDispatcher {
30446
30599
  static isNative(name) {
@@ -30632,12 +30785,12 @@
30632
30785
  }
30633
30786
  return editor.getBody();
30634
30787
  };
30635
- const isListening = editor => !editor.hidden;
30788
+ const isListening = editor => !editor.hidden && !isDisabled(editor);
30636
30789
  const fireEvent = (editor, eventName, e) => {
30637
30790
  if (isListening(editor)) {
30638
30791
  editor.dispatch(eventName, e);
30639
- } else if (isReadOnly(editor)) {
30640
- processReadonlyEvents(editor, e);
30792
+ } else if (isDisabled(editor)) {
30793
+ processDisabledEvents(editor, e);
30641
30794
  }
30642
30795
  };
30643
30796
  const bindEventDelegate = (editor, eventName) => {
@@ -30886,6 +31039,52 @@
30886
31039
  };
30887
31040
  };
30888
31041
 
31042
+ const setContentEditable = (elm, state) => {
31043
+ elm.dom.contentEditable = state ? 'true' : 'false';
31044
+ };
31045
+ const toggleReadOnly = (editor, state) => {
31046
+ const body = SugarElement.fromDom(editor.getBody());
31047
+ if (state) {
31048
+ editor.readonly = true;
31049
+ if (editor.hasEditableRoot()) {
31050
+ setContentEditable(body, true);
31051
+ }
31052
+ disableEditor(editor);
31053
+ } else {
31054
+ editor.readonly = false;
31055
+ enableEditor(editor);
31056
+ }
31057
+ };
31058
+ const isReadOnly = editor => editor.readonly;
31059
+ const registerReadOnlyInputBlockers = editor => {
31060
+ editor.on('beforeinput paste cut dragend dragover draggesture dragdrop drop drag', e => {
31061
+ if (isReadOnly(editor)) {
31062
+ e.preventDefault();
31063
+ }
31064
+ });
31065
+ editor.on('BeforeExecCommand', e => {
31066
+ if ((e.command === 'Undo' || e.command === 'Redo') && isReadOnly(editor)) {
31067
+ e.preventDefault();
31068
+ }
31069
+ });
31070
+ editor.on('input', e => {
31071
+ if (!e.isComposing && isReadOnly(editor)) {
31072
+ const undoLevel = editor.undoManager.add();
31073
+ if (isNonNullable(undoLevel)) {
31074
+ editor.undoManager.undo();
31075
+ }
31076
+ }
31077
+ });
31078
+ editor.on('compositionend', () => {
31079
+ if (isReadOnly(editor)) {
31080
+ const undoLevel = editor.undoManager.add();
31081
+ if (isNonNullable(undoLevel)) {
31082
+ editor.undoManager.undo();
31083
+ }
31084
+ }
31085
+ });
31086
+ };
31087
+
30889
31088
  const defaultModes = [
30890
31089
  'design',
30891
31090
  'readonly'
@@ -30907,7 +31106,7 @@
30907
31106
  fireSwitchMode(editor, mode);
30908
31107
  };
30909
31108
  const setMode = (editor, availableModes, activeMode, mode) => {
30910
- if (mode === activeMode.get()) {
31109
+ if (mode === activeMode.get() || editor.initialized && isDisabled(editor)) {
30911
31110
  return;
30912
31111
  } else if (!has$2(availableModes, mode)) {
30913
31112
  throw new Error(`Editor mode '${ mode }' is invalid`);
@@ -30951,7 +31150,8 @@
30951
31150
  editorReadOnly: true
30952
31151
  }
30953
31152
  });
30954
- registerReadOnlySelectionBlockers(editor);
31153
+ registerReadOnlyInputBlockers(editor);
31154
+ registerEventsAndFilters$1(editor);
30955
31155
  return {
30956
31156
  isReadOnly: () => isReadOnly(editor),
30957
31157
  set: mode => setMode(editor, availableModes.get(), activeMode, mode),
@@ -31135,6 +31335,12 @@
31135
31335
  type
31136
31336
  };
31137
31337
  };
31338
+ const addDefaulted = (collection, type) => (name, spec) => {
31339
+ collection[name.toLowerCase()] = {
31340
+ type,
31341
+ ...spec
31342
+ };
31343
+ };
31138
31344
  const addIcon = (name, svgData) => icons[name.toLowerCase()] = svgData;
31139
31345
  const addContext = (name, pred) => contexts[name.toLowerCase()] = pred;
31140
31346
  return {
@@ -31149,7 +31355,7 @@
31149
31355
  addAutocompleter: add(popups, 'autocompleter'),
31150
31356
  addContextMenu: add(contextMenus, 'contextmenu'),
31151
31357
  addContextToolbar: add(contextToolbars, 'contexttoolbar'),
31152
- addContextForm: add(contextToolbars, 'contextform'),
31358
+ addContextForm: addDefaulted(contextToolbars, 'contextform'),
31153
31359
  addSidebar: add(sidebars, 'sidebar'),
31154
31360
  addView: add(views, 'views'),
31155
31361
  addIcon,
@@ -31623,8 +31829,8 @@
31623
31829
  documentBaseURL: null,
31624
31830
  suffix: null,
31625
31831
  majorVersion: '7',
31626
- minorVersion: '5.1',
31627
- releaseDate: 'TBD',
31832
+ minorVersion: '6.0',
31833
+ releaseDate: '2024-12-11',
31628
31834
  i18n: I18n,
31629
31835
  activeEditor: null,
31630
31836
  focusedEditor: null,