tinymce-rails 7.3.0 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/app/assets/source/tinymce/tinymce.js +168 -116
  4. data/lib/tinymce/rails/version.rb +2 -2
  5. data/vendor/assets/javascripts/tinymce/icons/default/icons.js +1 -1
  6. data/vendor/assets/javascripts/tinymce/models/dom/model.js +2 -2
  7. data/vendor/assets/javascripts/tinymce/plugins/accordion/plugin.js +2 -2
  8. data/vendor/assets/javascripts/tinymce/plugins/advlist/plugin.js +2 -2
  9. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.js +1 -1
  10. data/vendor/assets/javascripts/tinymce/plugins/autolink/plugin.js +2 -2
  11. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.js +1 -1
  12. data/vendor/assets/javascripts/tinymce/plugins/autosave/plugin.js +2 -2
  13. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.js +1 -1
  14. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.js +1 -1
  15. data/vendor/assets/javascripts/tinymce/plugins/codesample/plugin.js +1 -1
  16. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.js +1 -1
  17. data/vendor/assets/javascripts/tinymce/plugins/emoticons/plugin.js +1 -1
  18. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.js +2 -2
  19. data/vendor/assets/javascripts/tinymce/plugins/help/plugin.js +2 -2
  20. data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +2 -2
  21. data/vendor/assets/javascripts/tinymce/plugins/importcss/plugin.js +1 -1
  22. data/vendor/assets/javascripts/tinymce/plugins/insertdatetime/plugin.js +2 -2
  23. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.js +2 -2
  24. data/vendor/assets/javascripts/tinymce/plugins/lists/plugin.js +2 -2
  25. data/vendor/assets/javascripts/tinymce/plugins/media/plugin.js +1 -1
  26. data/vendor/assets/javascripts/tinymce/plugins/nonbreaking/plugin.js +1 -1
  27. data/vendor/assets/javascripts/tinymce/plugins/pagebreak/plugin.js +1 -1
  28. data/vendor/assets/javascripts/tinymce/plugins/preview/plugin.js +2 -2
  29. data/vendor/assets/javascripts/tinymce/plugins/quickbars/plugin.js +1 -1
  30. data/vendor/assets/javascripts/tinymce/plugins/save/plugin.js +1 -1
  31. data/vendor/assets/javascripts/tinymce/plugins/searchreplace/plugin.js +1 -1
  32. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
  33. data/vendor/assets/javascripts/tinymce/plugins/visualblocks/plugin.js +2 -2
  34. data/vendor/assets/javascripts/tinymce/plugins/visualchars/plugin.js +2 -2
  35. data/vendor/assets/javascripts/tinymce/plugins/wordcount/plugin.js +2 -2
  36. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.css +1 -1
  37. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.css +1 -1
  38. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.js +1 -1
  39. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.min.css +1 -1
  40. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.js +1 -1
  41. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.min.css +1 -1
  42. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.css +1 -1
  43. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.js +1 -1
  44. data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.min.css +1 -1
  45. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.css +1 -1
  46. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.css +1 -1
  47. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.js +1 -1
  48. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.min.css +1 -1
  49. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.js +1 -1
  50. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.min.css +1 -1
  51. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.css +1 -1
  52. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.js +1 -1
  53. data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.min.css +1 -1
  54. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.css +1 -1
  55. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.css +1 -1
  56. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.js +1 -1
  57. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.min.css +1 -1
  58. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.js +1 -1
  59. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.min.css +1 -1
  60. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.css +1 -1
  61. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.js +1 -1
  62. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.min.css +1 -1
  63. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.css +1 -1
  64. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.css +1 -1
  65. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.js +1 -1
  66. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css +1 -1
  67. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.js +1 -1
  68. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.min.css +1 -1
  69. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.css +1 -1
  70. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.js +1 -1
  71. data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.min.css +1 -1
  72. data/vendor/assets/javascripts/tinymce/themes/silver/theme.js +2 -2
  73. data/vendor/assets/javascripts/tinymce/tinymce.d.ts +23 -0
  74. data/vendor/assets/javascripts/tinymce/tinymce.js +2 -2
  75. metadata +6 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f2cff298fe1ce0fd108d0ebe03fe0dfd4952d2aaa0762649b29be1a1d4df3f9
4
- data.tar.gz: a592e9e5d1d70c0ba1b0c06d02611236ec6120599991e4126409facc4cb410dc
3
+ metadata.gz: a66f1198e46acd5dfd476f6ffe9759d8dc75ee76048293f613207dbf9e21c04c
4
+ data.tar.gz: da1acf90b1e5f7500cff7c378b6c0be2aded36636440018909f87ca9bcc80732
5
5
  SHA512:
6
- metadata.gz: 4f0e2323551e3fd6d8dbf152121bda436bac579e380a079114ce6efa7192b30e71b6583a6995b355a5adc9744fbb4470b8ba8a93201b6568722d02f29e3a5981
7
- data.tar.gz: 5e219df2c3e9014062ba1f1d464302010da46bd385a018fde27ba9b53750576c0fe98eeb5bf51cea5b820dd812e580e27857b0a2addf6baf9d291416b73ed9f3
6
+ metadata.gz: cdc19cef2ea9075c7a46559850807c8bac0db219662d845bffc8443652c3fb01d6e058f43e3e06588619e643ce3f0b4635d55d6acd75bdcb9862289d24a61365
7
+ data.tar.gz: 1e1268da77e3b9feb50f06945749b7a8d6463071c151cfc4e79acf79fd230fe9894ff6e63b6b0d5207a6c2294fb9c5feb144137a76be368202727a083c17bfa1
data/README.md CHANGED
@@ -11,6 +11,8 @@ Please see alternate branches for [TinyMCE 6](https://github.com/spohlenz/tinymc
11
11
  > [!IMPORTANT]
12
12
  > Please note that as of version 7, TinyMCE (and therefore this project) is now licensed under the GPL.
13
13
 
14
+ [![Latest Gem Version](https://img.shields.io/gem/v/tinymce-rails)](https://rubygems.org/gems/tinymce-rails)
15
+ [![Upstream Version](https://img.shields.io/npm/v/tinymce?label=upstream&color=%23335dff)](https://www.tiny.cloud/docs/tinymce/latest/release-notes/)
14
16
  [![Build Status](https://img.shields.io/github/actions/workflow/status/spohlenz/tinymce-rails/rspec.yml)](https://github.com/spohlenz/tinymce-rails/actions)
15
17
 
16
18
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * TinyMCE version 7.3.0 (2024-08-07)
2
+ * TinyMCE version 7.4.0 (2024-10-09)
3
3
  */
4
4
 
5
5
  (function () {
@@ -7290,6 +7290,19 @@
7290
7290
  processor: 'boolean',
7291
7291
  default: false
7292
7292
  });
7293
+ registerOption('allow_mathml_annotation_encodings', {
7294
+ processor: value => {
7295
+ const valid = isArrayOf(value, isString);
7296
+ return valid ? {
7297
+ value,
7298
+ valid
7299
+ } : {
7300
+ valid: false,
7301
+ message: 'Must be an array of strings.'
7302
+ };
7303
+ },
7304
+ default: []
7305
+ });
7293
7306
  registerOption('convert_fonts_to_spans', {
7294
7307
  processor: 'boolean',
7295
7308
  default: true,
@@ -7948,7 +7961,7 @@
7948
7961
  const isContentEditableTrue$1 = isContentEditableTrue$3;
7949
7962
  const isContentEditableFalse$7 = isContentEditableFalse$b;
7950
7963
  const isMedia = isMedia$2;
7951
- const isBlockLike = matchStyleValues('display', 'block table table-cell table-caption list-item');
7964
+ const isBlockLike = matchStyleValues('display', 'block table table-cell table-row table-caption list-item');
7952
7965
  const isCaretContainer = isCaretContainer$2;
7953
7966
  const isCaretContainerBlock = isCaretContainerBlock$1;
7954
7967
  const isElement$2 = isElement$6;
@@ -9635,7 +9648,7 @@
9635
9648
  };
9636
9649
  const isResizable = elm => {
9637
9650
  const selector = getObjectResizing(editor);
9638
- if (!selector) {
9651
+ if (!selector || editor.mode.isReadOnly()) {
9639
9652
  return false;
9640
9653
  }
9641
9654
  if (elm.getAttribute('data-mce-resize') === 'false') {
@@ -13243,6 +13256,9 @@
13243
13256
  if (node && node.attr('id') === 'mce_marker') {
13244
13257
  const marker = node;
13245
13258
  for (node = node.prev; node; node = node.walk(true)) {
13259
+ if (node.name === 'table') {
13260
+ break;
13261
+ }
13246
13262
  if (node.type === 3 || !dom.isBlock(node.name)) {
13247
13263
  if (node.parent && editor.schema.isValidChild(node.parent.name, 'span')) {
13248
13264
  node.parent.insert(marker, node, node.name === 'br');
@@ -17230,37 +17246,55 @@
17230
17246
  }
17231
17247
  return config;
17232
17248
  };
17233
- const sanitizeNamespaceElement = ele => {
17249
+ const sanitizeSvgElement = ele => {
17250
+ const xlinkAttrs = [
17251
+ 'type',
17252
+ 'href',
17253
+ 'role',
17254
+ 'arcrole',
17255
+ 'title',
17256
+ 'show',
17257
+ 'actuate',
17258
+ 'label',
17259
+ 'from',
17260
+ 'to'
17261
+ ].map(name => `xlink:${ name }`);
17262
+ const config = {
17263
+ IN_PLACE: true,
17264
+ USE_PROFILES: {
17265
+ html: true,
17266
+ svg: true,
17267
+ svgFilters: true
17268
+ },
17269
+ ALLOWED_ATTR: xlinkAttrs
17270
+ };
17271
+ purify().sanitize(ele, config);
17272
+ };
17273
+ const sanitizeMathmlElement = (node, settings) => {
17274
+ const config = {
17275
+ IN_PLACE: true,
17276
+ USE_PROFILES: { mathMl: true }
17277
+ };
17278
+ const purify$1 = purify();
17279
+ purify$1.addHook('uponSanitizeElement', (node, evt) => {
17280
+ var _a;
17281
+ const lcTagName = (_a = evt.tagName) !== null && _a !== void 0 ? _a : node.nodeName.toLowerCase();
17282
+ const allowedEncodings = settings.allow_mathml_annotation_encodings;
17283
+ if (lcTagName === 'annotation' && isArray$1(allowedEncodings) && allowedEncodings.length > 0) {
17284
+ const encoding = node.getAttribute('encoding');
17285
+ if (isString(encoding) && contains$2(allowedEncodings, encoding)) {
17286
+ evt.allowedTags[lcTagName] = true;
17287
+ }
17288
+ }
17289
+ });
17290
+ purify$1.sanitize(node, config);
17291
+ };
17292
+ const mkSanitizeNamespaceElement = settings => ele => {
17234
17293
  const namespaceType = toScopeType(ele);
17235
17294
  if (namespaceType === 'svg') {
17236
- const xlinkAttrs = [
17237
- 'type',
17238
- 'href',
17239
- 'role',
17240
- 'arcrole',
17241
- 'title',
17242
- 'show',
17243
- 'actuate',
17244
- 'label',
17245
- 'from',
17246
- 'to'
17247
- ].map(name => `xlink:${ name }`);
17248
- const config = {
17249
- IN_PLACE: true,
17250
- USE_PROFILES: {
17251
- html: true,
17252
- svg: true,
17253
- svgFilters: true
17254
- },
17255
- ALLOWED_ATTR: xlinkAttrs
17256
- };
17257
- purify().sanitize(ele, config);
17295
+ sanitizeSvgElement(ele);
17258
17296
  } else if (namespaceType === 'math') {
17259
- const config = {
17260
- IN_PLACE: true,
17261
- USE_PROFILES: { mathMl: true }
17262
- };
17263
- purify().sanitize(ele, config);
17297
+ sanitizeMathmlElement(ele, settings);
17264
17298
  } else {
17265
17299
  throw new Error('Not a namespace element');
17266
17300
  }
@@ -17276,7 +17310,7 @@
17276
17310
  };
17277
17311
  return {
17278
17312
  sanitizeHtmlElement,
17279
- sanitizeNamespaceElement
17313
+ sanitizeNamespaceElement: mkSanitizeNamespaceElement(settings)
17280
17314
  };
17281
17315
  } else {
17282
17316
  const sanitizeHtmlElement = (body, _mimeType) => {
@@ -18743,6 +18777,9 @@
18743
18777
  return !sel || rng.collapsed;
18744
18778
  };
18745
18779
  const isEditable = () => {
18780
+ if (editor.mode.isReadOnly()) {
18781
+ return false;
18782
+ }
18746
18783
  const rng = getRng$1();
18747
18784
  const fakeSelectedElements = editor.getBody().querySelectorAll('[data-mce-selected="1"]');
18748
18785
  if (fakeSelectedElements.length > 0) {
@@ -22659,6 +22696,9 @@
22659
22696
  const getBlocksToIndent = editor => filter$5(fromDom$1(editor.selection.getSelectedBlocks()), el => !isListComponent(el) && !parentIsListComponent(el) && isEditable(el));
22660
22697
  const handle = (editor, command) => {
22661
22698
  var _a, _b;
22699
+ if (editor.mode.isReadOnly()) {
22700
+ return;
22701
+ }
22662
22702
  const {dom} = editor;
22663
22703
  const indentation = getIndentation(editor);
22664
22704
  const indentUnit = (_b = (_a = /[a-z%]+$/i.exec(indentation)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 'px';
@@ -23398,6 +23438,9 @@
23398
23438
  return getCellFirstCursorPosition(cell);
23399
23439
  });
23400
23440
  }, current => {
23441
+ if (editor.mode.isReadOnly()) {
23442
+ return Optional.none();
23443
+ }
23401
23444
  editor.execCommand('mceTableInsertRowAfter');
23402
23445
  return tabForward(editor, isRoot, current);
23403
23446
  });
@@ -24078,7 +24121,8 @@
24078
24121
  optionalTooltip,
24079
24122
  optionalIcon,
24080
24123
  optionalText,
24081
- onSetup
24124
+ onSetup,
24125
+ defaultedString('context', 'mode:design')
24082
24126
  ];
24083
24127
 
24084
24128
  const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
@@ -24941,9 +24985,12 @@
24941
24985
  const isEmptyAnchor = (dom, elm) => {
24942
24986
  return elm && elm.nodeName === 'A' && dom.isEmpty(elm);
24943
24987
  };
24944
- const containerAndSiblingName = (container, nodeName) => {
24988
+ const containerAndPreviousSiblingName = (container, nodeName) => {
24945
24989
  return container.nodeName === nodeName || container.previousSibling && container.previousSibling.nodeName === nodeName;
24946
24990
  };
24991
+ const containerAndNextSiblingName = (container, nodeName) => {
24992
+ return container.nodeName === nodeName || container.nextSibling && container.nextSibling.nodeName === nodeName;
24993
+ };
24947
24994
  const canSplitBlock = (dom, node) => {
24948
24995
  return isNonNullable(node) && dom.isBlock(node) && !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) && !/^(fixed|absolute)/i.test(node.style.position) && dom.isEditable(node.parentNode) && dom.getContentEditable(node) !== 'false';
24949
24996
  };
@@ -25085,7 +25132,10 @@
25085
25132
  if (start && isElement$6(container) && container === parentBlock.firstChild) {
25086
25133
  return true;
25087
25134
  }
25088
- if (containerAndSiblingName(container, 'TABLE') || containerAndSiblingName(container, 'HR')) {
25135
+ if (containerAndPreviousSiblingName(container, 'TABLE') || containerAndPreviousSiblingName(container, 'HR')) {
25136
+ if (containerAndNextSiblingName(container, 'BR')) {
25137
+ return !start;
25138
+ }
25089
25139
  return isAfterLastNodeInContainer && !start || !isAfterLastNodeInContainer && start;
25090
25140
  }
25091
25141
  const walker = new DomTreeWalker(container, parentBlock);
@@ -25203,7 +25253,7 @@
25203
25253
  const afterBr = isAfterBr(parentBlockSugar, caretPos, editor.schema);
25204
25254
  const prevBrOpt = afterBr ? findPreviousBr(parentBlockSugar, caretPos, editor.schema).bind(pos => Optional.from(pos.getNode())) : Optional.none();
25205
25255
  newBlock = parentBlockParent.insertBefore(createNewBlock$1(), parentBlock);
25206
- const root = containerAndSiblingName(parentBlock, 'HR') || afterTable ? newBlock : prevBrOpt.getOr(parentBlock);
25256
+ const root = containerAndPreviousSiblingName(parentBlock, 'HR') || afterTable ? newBlock : prevBrOpt.getOr(parentBlock);
25207
25257
  moveToCaretPosition(editor, root);
25208
25258
  } else {
25209
25259
  const tmpRng = includeZwspInRange(rng).cloneRange();
@@ -25463,6 +25513,9 @@
25463
25513
  };
25464
25514
 
25465
25515
  const insertBreak = (breakType, editor, evt) => {
25516
+ if (editor.mode.isReadOnly()) {
25517
+ return;
25518
+ }
25466
25519
  if (!editor.selection.isCollapsed()) {
25467
25520
  execEditorDeleteCommand(editor);
25468
25521
  }
@@ -25478,6 +25531,9 @@
25478
25531
  }
25479
25532
  };
25480
25533
  const insert$1 = (editor, evt) => {
25534
+ if (editor.mode.isReadOnly()) {
25535
+ return;
25536
+ }
25481
25537
  const br = () => insertBreak(linebreak, editor, evt);
25482
25538
  const block = () => insertBreak(blockbreak, editor, evt);
25483
25539
  const logicalAction = getAction(editor, evt);
@@ -25840,16 +25896,17 @@
25840
25896
  });
25841
25897
  }
25842
25898
  nodeChanged(args = {}) {
25843
- const selection = this.editor.selection;
25899
+ const editor = this.editor;
25900
+ const selection = editor.selection;
25844
25901
  let node;
25845
- if (this.editor.initialized && selection && !shouldDisableNodeChange(this.editor) && !this.editor.mode.isReadOnly()) {
25846
- const root = this.editor.getBody();
25902
+ if (editor.initialized && selection && !shouldDisableNodeChange(editor)) {
25903
+ const root = editor.getBody();
25847
25904
  node = selection.getStart(true) || root;
25848
- if (node.ownerDocument !== this.editor.getDoc() || !this.editor.dom.isChildOf(node, root)) {
25905
+ if (node.ownerDocument !== editor.getDoc() || !editor.dom.isChildOf(node, root)) {
25849
25906
  node = root;
25850
25907
  }
25851
25908
  const parents = [];
25852
- this.editor.dom.getParent(node, node => {
25909
+ editor.dom.getParent(node, node => {
25853
25910
  if (node === root) {
25854
25911
  return true;
25855
25912
  } else {
@@ -25857,7 +25914,7 @@
25857
25914
  return false;
25858
25915
  }
25859
25916
  });
25860
- this.editor.dispatch('NodeChange', {
25917
+ editor.dispatch('NodeChange', {
25861
25918
  ...args,
25862
25919
  element: node,
25863
25920
  parents
@@ -28328,7 +28385,7 @@
28328
28385
  }), getTextPatternsLookup(editor));
28329
28386
  const hasDynamicPatterns = () => hasTextPatternsLookup(editor);
28330
28387
  editor.on('keydown', e => {
28331
- if (e.keyCode === 13 && !VK.modifierPressed(e) && editor.selection.isCollapsed()) {
28388
+ if (e.keyCode === 13 && !VK.modifierPressed(e) && editor.selection.isCollapsed() && editor.selection.isEditable()) {
28332
28389
  const patternSet = filterByTrigger(getPatternSet(), 'enter');
28333
28390
  const hasPatterns = patternSet.inlinePatterns.length > 0 || patternSet.blockPatterns.length > 0 || hasDynamicPatterns();
28334
28391
  if (hasPatterns && handleEnter(editor, patternSet)) {
@@ -28337,7 +28394,7 @@
28337
28394
  }
28338
28395
  }, true);
28339
28396
  editor.on('keydown', e => {
28340
- if (e.keyCode === 32 && editor.selection.isCollapsed()) {
28397
+ if (e.keyCode === 32 && editor.selection.isCollapsed() && editor.selection.isEditable()) {
28341
28398
  const patternSet = filterByTrigger(getPatternSet(), 'space');
28342
28399
  const hasPatterns = patternSet.blockPatterns.length > 0 || hasDynamicPatterns();
28343
28400
  if (hasPatterns && handleBlockPatternOnSpace(editor, patternSet)) {
@@ -28346,7 +28403,7 @@
28346
28403
  }
28347
28404
  }, true);
28348
28405
  const handleInlineTrigger = () => {
28349
- if (editor.selection.isCollapsed()) {
28406
+ if (editor.selection.isCollapsed() && editor.selection.isEditable()) {
28350
28407
  const patternSet = filterByTrigger(getPatternSet(), 'space');
28351
28408
  const hasPatterns = patternSet.inlinePatterns.length > 0 || hasDynamicPatterns();
28352
28409
  if (hasPatterns) {
@@ -28794,6 +28851,7 @@
28794
28851
  allow_svg_data_urls: getOption('allow_svg_data_urls'),
28795
28852
  allow_html_in_named_anchor: getOption('allow_html_in_named_anchor'),
28796
28853
  allow_script_urls: getOption('allow_script_urls'),
28854
+ allow_mathml_annotation_encodings: getOption('allow_mathml_annotation_encodings'),
28797
28855
  allow_unsafe_link_target: getOption('allow_unsafe_link_target'),
28798
28856
  convert_unsafe_embeds: getOption('convert_unsafe_embeds'),
28799
28857
  convert_fonts_to_spans: getOption('convert_fonts_to_spans'),
@@ -29076,7 +29134,7 @@
29076
29134
  body.disabled = true;
29077
29135
  editor.readonly = isReadOnly$1(editor);
29078
29136
  editor._editableRoot = hasEditableRoot$1(editor);
29079
- if (!editor.readonly && editor.hasEditableRoot()) {
29137
+ if (editor.hasEditableRoot()) {
29080
29138
  if (editor.inline && DOM$6.getStyle(body, 'position', true) === 'static') {
29081
29139
  body.style.position = 'relative';
29082
29140
  }
@@ -29335,7 +29393,8 @@
29335
29393
  hide: Optional.from(api.hide).getOr(noop),
29336
29394
  isEnabled: Optional.from(api.isEnabled).getOr(always),
29337
29395
  setEnabled: state => {
29338
- if (!editor.mode.isReadOnly()) {
29396
+ const shouldSkip = state && editor.mode.get() === 'readonly';
29397
+ if (!shouldSkip) {
29339
29398
  Optional.from(api.setEnabled).each(f => f(state));
29340
29399
  }
29341
29400
  }
@@ -29548,10 +29607,8 @@
29548
29607
  const setEditableRoot = (editor, state) => {
29549
29608
  if (editor._editableRoot !== state) {
29550
29609
  editor._editableRoot = state;
29551
- if (!editor.readonly) {
29552
- editor.getBody().contentEditable = String(editor.hasEditableRoot());
29553
- editor.nodeChanged();
29554
- }
29610
+ editor.getBody().contentEditable = String(editor.hasEditableRoot());
29611
+ editor.nodeChanged();
29555
29612
  fireEditableRootStateChange(editor, state);
29556
29613
  }
29557
29614
  };
@@ -29992,6 +30049,9 @@
29992
30049
 
29993
30050
  const registerCommands$4 = editor => {
29994
30051
  const applyLinkToSelection = (_command, _ui, value) => {
30052
+ if (editor.mode.isReadOnly()) {
30053
+ return;
30054
+ }
29995
30055
  const linkDetails = isString(value) ? { href: value } : value;
29996
30056
  const anchor = editor.dom.getParent(editor.selection.getNode(), 'a');
29997
30057
  if (isObject(linkDetails) && isString(linkDetails.href)) {
@@ -30029,6 +30089,9 @@
30029
30089
  return Optional.from(topParentBlock).map(SugarElement.fromDom);
30030
30090
  };
30031
30091
  const insert = (editor, before) => {
30092
+ if (editor.mode.isReadOnly()) {
30093
+ return;
30094
+ }
30032
30095
  const dom = editor.dom;
30033
30096
  const rng = editor.selection.getRng();
30034
30097
  const node = before ? editor.selection.getStart() : editor.selection.getEnd();
@@ -30233,7 +30296,6 @@
30233
30296
  }
30234
30297
  }
30235
30298
 
30236
- const internalContentEditableAttr = 'data-mce-contenteditable';
30237
30299
  const toggleClass = (elm, cls, state) => {
30238
30300
  if (has(elm, cls) && !state) {
30239
30301
  remove$6(elm, cls);
@@ -30250,18 +30312,6 @@
30250
30312
  const setContentEditable = (elm, state) => {
30251
30313
  elm.dom.contentEditable = state ? 'true' : 'false';
30252
30314
  };
30253
- const switchOffContentEditableTrue = elm => {
30254
- each$e(descendants(elm, '*[contenteditable="true"]'), elm => {
30255
- set$3(elm, internalContentEditableAttr, 'true');
30256
- setContentEditable(elm, false);
30257
- });
30258
- };
30259
- const switchOnContentEditableTrue = elm => {
30260
- each$e(descendants(elm, `*[${ internalContentEditableAttr }="true"]`), elm => {
30261
- remove$9(elm, internalContentEditableAttr);
30262
- setContentEditable(elm, true);
30263
- });
30264
- };
30265
30315
  const removeFakeSelection = editor => {
30266
30316
  Optional.from(editor.selection.getNode()).each(elm => {
30267
30317
  elm.removeAttribute('data-mce-selected');
@@ -30270,60 +30320,42 @@
30270
30320
  const restoreFakeSelection = editor => {
30271
30321
  editor.selection.setRng(editor.selection.getRng());
30272
30322
  };
30323
+ const setCommonEditorCommands = (editor, state) => {
30324
+ setEditorCommandState(editor, 'StyleWithCSS', state);
30325
+ setEditorCommandState(editor, 'enableInlineTableEditing', state);
30326
+ setEditorCommandState(editor, 'enableObjectResizing', state);
30327
+ };
30328
+ const setEditorReadonly = editor => {
30329
+ editor.readonly = true;
30330
+ editor.selection.controlSelection.hideResizeRect();
30331
+ editor._selectionOverrides.hideFakeCaret();
30332
+ removeFakeSelection(editor);
30333
+ };
30334
+ const unsetEditorReadonly = (editor, body) => {
30335
+ editor.readonly = false;
30336
+ if (editor.hasEditableRoot()) {
30337
+ setContentEditable(body, true);
30338
+ }
30339
+ setCommonEditorCommands(editor, false);
30340
+ if (hasEditorOrUiFocus(editor)) {
30341
+ editor.focus();
30342
+ }
30343
+ restoreFakeSelection(editor);
30344
+ editor.nodeChanged();
30345
+ };
30273
30346
  const toggleReadOnly = (editor, state) => {
30274
30347
  const body = SugarElement.fromDom(editor.getBody());
30275
30348
  toggleClass(body, 'mce-content-readonly', state);
30276
30349
  if (state) {
30277
- editor.selection.controlSelection.hideResizeRect();
30278
- editor._selectionOverrides.hideFakeCaret();
30279
- removeFakeSelection(editor);
30280
- editor.readonly = true;
30281
- setContentEditable(body, false);
30282
- switchOffContentEditableTrue(body);
30283
- } else {
30284
- editor.readonly = false;
30350
+ setEditorReadonly(editor);
30285
30351
  if (editor.hasEditableRoot()) {
30286
30352
  setContentEditable(body, true);
30287
30353
  }
30288
- switchOnContentEditableTrue(body);
30289
- setEditorCommandState(editor, 'StyleWithCSS', false);
30290
- setEditorCommandState(editor, 'enableInlineTableEditing', false);
30291
- setEditorCommandState(editor, 'enableObjectResizing', false);
30292
- if (hasEditorOrUiFocus(editor)) {
30293
- editor.focus();
30294
- }
30295
- restoreFakeSelection(editor);
30296
- editor.nodeChanged();
30297
- }
30298
- };
30299
- const isReadOnly = editor => editor.readonly;
30300
- const registerFilters = editor => {
30301
- editor.parser.addAttributeFilter('contenteditable', nodes => {
30302
- if (isReadOnly(editor)) {
30303
- each$e(nodes, node => {
30304
- node.attr(internalContentEditableAttr, node.attr('contenteditable'));
30305
- node.attr('contenteditable', 'false');
30306
- });
30307
- }
30308
- });
30309
- editor.serializer.addAttributeFilter(internalContentEditableAttr, nodes => {
30310
- if (isReadOnly(editor)) {
30311
- each$e(nodes, node => {
30312
- node.attr('contenteditable', node.attr(internalContentEditableAttr));
30313
- });
30314
- }
30315
- });
30316
- editor.serializer.addTempAttr(internalContentEditableAttr);
30317
- };
30318
- const registerReadOnlyContentFilters = editor => {
30319
- if (editor.serializer) {
30320
- registerFilters(editor);
30321
30354
  } else {
30322
- editor.on('PreInit', () => {
30323
- registerFilters(editor);
30324
- });
30355
+ unsetEditorReadonly(editor, body);
30325
30356
  }
30326
30357
  };
30358
+ const isReadOnly = editor => editor.readonly;
30327
30359
  const isClickEvent = e => e.type === 'click';
30328
30360
  const allowedEvents = ['copy'];
30329
30361
  const isReadOnlyAllowedEvent = e => contains$2(allowedEvents, e.type);
@@ -30350,16 +30382,32 @@
30350
30382
  }
30351
30383
  };
30352
30384
  const registerReadOnlySelectionBlockers = editor => {
30353
- editor.on('ShowCaret', e => {
30385
+ editor.on('beforeinput paste cut dragend dragover draggesture dragdrop drop drag', e => {
30354
30386
  if (isReadOnly(editor)) {
30355
30387
  e.preventDefault();
30356
30388
  }
30357
30389
  });
30358
- editor.on('ObjectSelected', e => {
30359
- if (isReadOnly(editor)) {
30390
+ editor.on('BeforeExecCommand', e => {
30391
+ if ((e.command === 'Undo' || e.command === 'Redo') && isReadOnly(editor)) {
30360
30392
  e.preventDefault();
30361
30393
  }
30362
30394
  });
30395
+ editor.on('input', e => {
30396
+ if (!e.isComposing && isReadOnly(editor)) {
30397
+ const undoLevel = editor.undoManager.add();
30398
+ if (isNonNullable(undoLevel)) {
30399
+ editor.undoManager.undo();
30400
+ }
30401
+ }
30402
+ });
30403
+ editor.on('compositionend', () => {
30404
+ if (isReadOnly(editor)) {
30405
+ const undoLevel = editor.undoManager.add();
30406
+ if (isNonNullable(undoLevel)) {
30407
+ editor.undoManager.undo();
30408
+ }
30409
+ }
30410
+ });
30363
30411
  };
30364
30412
 
30365
30413
  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', ' ');
@@ -30553,7 +30601,7 @@
30553
30601
  }
30554
30602
  return editor.getBody();
30555
30603
  };
30556
- const isListening = editor => !editor.hidden && !isReadOnly(editor);
30604
+ const isListening = editor => !editor.hidden;
30557
30605
  const fireEvent = (editor, eventName, e) => {
30558
30606
  if (isListening(editor)) {
30559
30607
  editor.dispatch(eventName, e);
@@ -30872,7 +30920,6 @@
30872
30920
  editorReadOnly: true
30873
30921
  }
30874
30922
  });
30875
- registerReadOnlyContentFilters(editor);
30876
30923
  registerReadOnlySelectionBlockers(editor);
30877
30924
  return {
30878
30925
  isReadOnly: () => isReadOnly(editor),
@@ -31048,6 +31095,7 @@
31048
31095
  const icons = {};
31049
31096
  const contextMenus = {};
31050
31097
  const contextToolbars = {};
31098
+ const contexts = {};
31051
31099
  const sidebars = {};
31052
31100
  const views = {};
31053
31101
  const add = (collection, type) => (name, spec) => {
@@ -31057,6 +31105,7 @@
31057
31105
  };
31058
31106
  };
31059
31107
  const addIcon = (name, svgData) => icons[name.toLowerCase()] = svgData;
31108
+ const addContext = (name, pred) => contexts[name.toLowerCase()] = pred;
31060
31109
  return {
31061
31110
  addButton: add(buttons, 'button'),
31062
31111
  addGroupToolbarButton: add(buttons, 'grouptoolbarbutton'),
@@ -31073,6 +31122,7 @@
31073
31122
  addSidebar: add(sidebars, 'sidebar'),
31074
31123
  addView: add(views, 'views'),
31075
31124
  addIcon,
31125
+ addContext,
31076
31126
  getAll: () => ({
31077
31127
  buttons,
31078
31128
  menuItems,
@@ -31081,7 +31131,8 @@
31081
31131
  contextMenus,
31082
31132
  contextToolbars,
31083
31133
  sidebars,
31084
- views
31134
+ views,
31135
+ contexts
31085
31136
  })
31086
31137
  };
31087
31138
  };
@@ -31104,6 +31155,7 @@
31104
31155
  addGroupToolbarButton: bridge.addGroupToolbarButton,
31105
31156
  addToggleMenuItem: bridge.addToggleMenuItem,
31106
31157
  addView: bridge.addView,
31158
+ addContext: bridge.addContext,
31107
31159
  getAll: bridge.getAll
31108
31160
  };
31109
31161
  };
@@ -31540,8 +31592,8 @@
31540
31592
  documentBaseURL: null,
31541
31593
  suffix: null,
31542
31594
  majorVersion: '7',
31543
- minorVersion: '3.0',
31544
- releaseDate: '2024-08-07',
31595
+ minorVersion: '4.0',
31596
+ releaseDate: '2024-10-09',
31545
31597
  i18n: I18n,
31546
31598
  activeEditor: null,
31547
31599
  focusedEditor: null,
@@ -1,6 +1,6 @@
1
1
  module TinyMCE
2
2
  module Rails
3
- VERSION = "7.3.0"
4
- TINYMCE_VERSION = "7.3.0"
3
+ VERSION = "7.4.0"
4
+ TINYMCE_VERSION = "7.4.0"
5
5
  end
6
6
  end