jodit 4.17.0 → 4.17.2

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 (64) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/es2015/jodit.css +1 -1
  3. package/es2015/jodit.fat.min.js +3 -3
  4. package/es2015/jodit.js +171 -12
  5. package/es2015/jodit.min.js +3 -3
  6. package/es2015/plugins/debug/debug.css +1 -1
  7. package/es2015/plugins/debug/debug.js +1 -1
  8. package/es2015/plugins/debug/debug.min.js +1 -1
  9. package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
  10. package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
  11. package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
  12. package/es2018/jodit.fat.min.js +3 -3
  13. package/es2018/jodit.min.js +3 -3
  14. package/es2018/plugins/debug/debug.min.js +1 -1
  15. package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
  16. package/es2021/jodit.css +1 -1
  17. package/es2021/jodit.fat.min.js +5 -5
  18. package/es2021/jodit.js +171 -12
  19. package/es2021/jodit.min.js +5 -5
  20. package/es2021/plugins/debug/debug.css +1 -1
  21. package/es2021/plugins/debug/debug.js +1 -1
  22. package/es2021/plugins/debug/debug.min.js +1 -1
  23. package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
  24. package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
  25. package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
  26. package/es2021.en/jodit.css +1 -1
  27. package/es2021.en/jodit.fat.min.js +24 -24
  28. package/es2021.en/jodit.js +171 -12
  29. package/es2021.en/jodit.min.js +5 -5
  30. package/es2021.en/plugins/debug/debug.css +1 -1
  31. package/es2021.en/plugins/debug/debug.js +1 -1
  32. package/es2021.en/plugins/debug/debug.min.js +1 -1
  33. package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
  34. package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
  35. package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
  36. package/es5/jodit.css +2 -2
  37. package/es5/jodit.fat.min.js +2 -2
  38. package/es5/jodit.js +186 -12
  39. package/es5/jodit.min.css +2 -2
  40. package/es5/jodit.min.js +2 -2
  41. package/es5/plugins/debug/debug.css +1 -1
  42. package/es5/plugins/debug/debug.js +1 -1
  43. package/es5/plugins/debug/debug.min.js +1 -1
  44. package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
  45. package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
  46. package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
  47. package/es5/polyfills.fat.min.js +1 -1
  48. package/es5/polyfills.js +1 -1
  49. package/es5/polyfills.min.js +1 -1
  50. package/esm/core/constants.js +1 -1
  51. package/esm/core/helpers/html/safe-html.d.ts +1 -1
  52. package/esm/core/helpers/html/safe-html.js +8 -1
  53. package/esm/core/selection/helpers/composed-ranges.d.ts +21 -0
  54. package/esm/core/selection/helpers/composed-ranges.js +45 -0
  55. package/esm/core/selection/helpers/index.d.ts +1 -0
  56. package/esm/core/selection/helpers/index.js +1 -0
  57. package/esm/core/selection/selection.d.ts +23 -0
  58. package/esm/core/selection/selection.js +80 -4
  59. package/esm/plugins/drag-and-drop/drag-and-drop.js +16 -4
  60. package/package.json +1 -1
  61. package/types/core/helpers/html/safe-html.d.ts +1 -1
  62. package/types/core/selection/helpers/composed-ranges.d.ts +21 -0
  63. package/types/core/selection/helpers/index.d.ts +1 -0
  64. package/types/core/selection/selection.d.ts +23 -0
package/es2015/jodit.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.17.0
4
+ * Version: v4.17.2
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1805,7 +1805,7 @@ __webpack_require__.r(__webpack_exports__);
1805
1805
  * ```
1806
1806
  * @packageDocumentation
1807
1807
  * @module constants
1808
- */ const APP_VERSION = "4.17.0";
1808
+ */ const APP_VERSION = "4.17.2";
1809
1809
  // prettier-ignore
1810
1810
  const ES = "es2015";
1811
1811
  const IS_ES_MODERN = true;
@@ -6306,7 +6306,7 @@ function isSmuggledForeignHtml(elm) {
6306
6306
  }
6307
6307
  return /^data:image\/svg/.test(normalized) && DOCUMENT_EMBED_TAGS.has(tagName);
6308
6308
  }
6309
- function sanitizeHTMLElement(elm, { safeJavaScriptLink, removeOnError } = {
6309
+ function sanitizeHTMLElement(elm, { safeJavaScriptLink, removeOnError, removeEventAttributes } = {
6310
6310
  safeJavaScriptLink: true,
6311
6311
  removeOnError: true
6312
6312
  }) {
@@ -6314,6 +6314,13 @@ function sanitizeHTMLElement(elm, { safeJavaScriptLink, removeOnError } = {
6314
6314
  return false;
6315
6315
  }
6316
6316
  let effected = false;
6317
+ // Every `on*` handler, not only `onerror`: the clean-html background
6318
+ // pass calls this directly, and markup that reached the editable area
6319
+ // without `safeHTML` (a drop, a script) kept its handlers otherwise.
6320
+ // See GHSA-jhhp-r3r7-v2cg
6321
+ if (removeEventAttributes && removeAllEventAttributes(elm)) {
6322
+ effected = true;
6323
+ }
6317
6324
  if (removeOnError && elm.hasAttribute('onerror')) {
6318
6325
  (0,jodit_core_helpers_utils__WEBPACK_IMPORTED_MODULE_1__.attr)(elm, 'onerror', null);
6319
6326
  effected = true;
@@ -10589,6 +10596,70 @@ class Response {
10589
10596
  }
10590
10597
 
10591
10598
 
10599
+ /***/ }),
10600
+
10601
+ /***/ 43134:
10602
+ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
10603
+
10604
+ "use strict";
10605
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10606
+ /* harmony export */ composedRanges: function() { return /* binding */ composedRanges; }
10607
+ /* harmony export */ });
10608
+ /* harmony import */ var jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(28686);
10609
+ /*!
10610
+ * Jodit Editor (https://xdsoft.net/jodit/)
10611
+ * Released under MIT see LICENSE.txt in the project root for license information.
10612
+ * Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
10613
+ */ /**
10614
+ * @module selection
10615
+ */
10616
+ function isInside(node, shadowRoot) {
10617
+ return node === shadowRoot || shadowRoot.contains(node);
10618
+ }
10619
+ function usable(ranges, shadowRoot) {
10620
+ return Array.isArray(ranges) && ranges.length > 0 && ranges.every((range)=>isInside(range.startContainer, shadowRoot));
10621
+ }
10622
+ /**
10623
+ * Ranges of a selection that lies inside the given shadow tree.
10624
+ *
10625
+ * `window.getSelection()` stops at the shadow boundary and reports the host
10626
+ * instead of the node the caret is really in. `getComposedRanges` is the
10627
+ * standard way to ask past that boundary.
10628
+ *
10629
+ * @returns `null` when the browser has no `getComposedRanges`, or when neither
10630
+ * call shape returned ranges that point inside the shadow tree — in which case
10631
+ * there is nothing better to offer than the plain window selection.
10632
+ */ function composedRanges(selection, shadowRoot) {
10633
+ const getComposedRanges = selection.getComposedRanges;
10634
+ if (!(0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_0__.isFunction)(getComposedRanges)) {
10635
+ return null;
10636
+ }
10637
+ for (const args of [
10638
+ [
10639
+ {
10640
+ shadowRoots: [
10641
+ shadowRoot
10642
+ ]
10643
+ }
10644
+ ],
10645
+ [
10646
+ shadowRoot
10647
+ ]
10648
+ ]){
10649
+ let ranges;
10650
+ try {
10651
+ ranges = getComposedRanges.apply(selection, args);
10652
+ } catch (unused) {
10653
+ continue;
10654
+ }
10655
+ if (usable(ranges, shadowRoot)) {
10656
+ return ranges;
10657
+ }
10658
+ }
10659
+ return null;
10660
+ }
10661
+
10662
+
10592
10663
  /***/ }),
10593
10664
 
10594
10665
  /***/ 42259:
@@ -10596,14 +10667,16 @@ class Response {
10596
10667
 
10597
10668
  "use strict";
10598
10669
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10670
+ /* harmony export */ composedRanges: function() { return /* reexport safe */ _composed_ranges__WEBPACK_IMPORTED_MODULE_2__.composedRanges; },
10599
10671
  /* harmony export */ cursorInTheEdgeOfString: function() { return /* binding */ cursorInTheEdgeOfString; },
10600
10672
  /* harmony export */ findCorrectCurrentNode: function() { return /* binding */ findCorrectCurrentNode; },
10601
- /* harmony export */ moveNodeInsideStart: function() { return /* reexport safe */ _move_node_inside_start__WEBPACK_IMPORTED_MODULE_2__.moveNodeInsideStart; }
10673
+ /* harmony export */ moveNodeInsideStart: function() { return /* reexport safe */ _move_node_inside_start__WEBPACK_IMPORTED_MODULE_3__.moveNodeInsideStart; }
10602
10674
  /* harmony export */ });
10603
10675
  /* harmony import */ var jodit_core_constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(81937);
10604
10676
  /* harmony import */ var jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23211);
10605
- /* harmony import */ var _move_node_inside_start__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(89817);
10606
- /* harmony import */ var _move_the_node_along_the_edge_outward__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7470);
10677
+ /* harmony import */ var _composed_ranges__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(43134);
10678
+ /* harmony import */ var _move_node_inside_start__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(89817);
10679
+ /* harmony import */ var _move_the_node_along_the_edge_outward__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7470);
10607
10680
  /*!
10608
10681
  * Jodit Editor (https://xdsoft.net/jodit/)
10609
10682
  * Released under MIT see LICENSE.txt in the project root for license information.
@@ -10614,6 +10687,7 @@ class Response {
10614
10687
 
10615
10688
 
10616
10689
 
10690
+
10617
10691
  /**
10618
10692
  * Despite the name, returns `true` when the cursor is NOT at the checked edge
10619
10693
  * of the text node: there is significant (non invisible-space) text between
@@ -10843,11 +10917,87 @@ class Selection {
10843
10917
  /**
10844
10918
  * Return current selection object
10845
10919
  */ get sel() {
10846
- if (this.j.o.shadowRoot && (0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isFunction)(this.j.o.shadowRoot.getSelection)) {
10847
- return this.j.o.shadowRoot.getSelection();
10920
+ const { shadowRoot } = this.j.o;
10921
+ if (shadowRoot) {
10922
+ if ((0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isFunction)(shadowRoot.getSelection)) {
10923
+ return shadowRoot.getSelection();
10924
+ }
10925
+ const composed = this.__composedSelection(shadowRoot);
10926
+ if (composed) {
10927
+ return composed;
10928
+ }
10848
10929
  }
10849
10930
  return this.win.getSelection();
10850
10931
  }
10932
+ /**
10933
+ * Selection of a shadow tree in a browser without `ShadowRoot.getSelection`.
10934
+ *
10935
+ * `ShadowRoot.getSelection()` is a non-standard method that WebKit never
10936
+ * implemented, and `window.getSelection()` stops at the shadow boundary: for
10937
+ * a caret inside the shadow tree it reports the host, or the document
10938
+ * itself. Everything downstream then works on the wrong tree, which is why
10939
+ * Backspace used to throw `HierarchyRequestError` and Enter did nothing when
10940
+ * the editor lived in a shadow root in Safari.
10941
+ *
10942
+ * The standard replacement is `Selection.getComposedRanges()`, which does
10943
+ * reach into a shadow tree it is given. It hands back `StaticRange`s, and
10944
+ * the editor mutates ranges constantly, so they are turned into live ones.
10945
+ *
10946
+ * Reads are answered from those ranges; everything else, including the
10947
+ * writes (`addRange`, `removeAllRanges`, `setBaseAndExtent`), goes to the
10948
+ * real selection, which does accept nodes inside a shadow tree. Reading is
10949
+ * the only side the browser blocks.
10950
+ *
10951
+ * @returns `null` when the browser offers neither API, so the caller falls
10952
+ * back to the plain window selection.
10953
+ */ __composedSelection(shadowRoot) {
10954
+ const selection = this.win.getSelection();
10955
+ if (!selection) {
10956
+ return null;
10957
+ }
10958
+ // Firefox has no `ShadowRoot.getSelection` either, but its window
10959
+ // selection does see into a shadow tree. Where the plain selection
10960
+ // already points at the right node there is nothing to work around, and
10961
+ // taking it over would change behaviour that works today.
10962
+ const { anchorNode } = selection;
10963
+ if (anchorNode && jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_4__.Dom.isOrContains(shadowRoot, anchorNode)) {
10964
+ return null;
10965
+ }
10966
+ const ranges = (0,_helpers__WEBPACK_IMPORTED_MODULE_11__.composedRanges)(selection, shadowRoot);
10967
+ if (!ranges) {
10968
+ return null;
10969
+ }
10970
+ const live = ranges.map((staticRange)=>{
10971
+ const range = this.createRange();
10972
+ range.setStart(staticRange.startContainer, staticRange.startOffset);
10973
+ range.setEnd(staticRange.endContainer, staticRange.endOffset);
10974
+ return range;
10975
+ });
10976
+ const first = live[0];
10977
+ const overrides = {
10978
+ rangeCount: live.length,
10979
+ getRangeAt: (index)=>live[index],
10980
+ isCollapsed: live.every((range)=>range.collapsed),
10981
+ // Without these the editor asks the window selection where the
10982
+ // caret is, is told "outside the editable area", and resets the
10983
+ // caret to the start of it — which is the focus loss that shows up
10984
+ // right after a successful Backspace.
10985
+ anchorNode: first ? first.startContainer : null,
10986
+ anchorOffset: first ? first.startOffset : 0,
10987
+ focusNode: first ? first.endContainer : null,
10988
+ focusOffset: first ? first.endOffset : 0,
10989
+ toString: ()=>live.map((range)=>range.toString()).join('')
10990
+ };
10991
+ return new Proxy(selection, {
10992
+ get (target, property) {
10993
+ if ((0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isString)(property) && property in overrides) {
10994
+ return overrides[property];
10995
+ }
10996
+ const value = Reflect.get(target, property, target);
10997
+ return (0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isFunction)(value) ? value.bind(target) : value;
10998
+ }
10999
+ });
11000
+ }
10851
11001
  /**
10852
11002
  * Return first selected range or create new
10853
11003
  */ get range() {
@@ -31269,7 +31419,11 @@ jodit_core_global__WEBPACK_IMPORTED_MODULE_4__.pluginSystem.add('dragAndDropElem
31269
31419
  window,
31270
31420
  this.j.ed,
31271
31421
  this.j.editor
31272
- ], 'dragstart.DragAndDrop', this.onDragStart);
31422
+ ], 'dragstart.DragAndDrop', this.onDragStart)// Always, not only after a `dragstart` seen in this window: a drop
31423
+ // from another window or application never produces one here, and
31424
+ // the browser then inserted its HTML natively, unsanitized. Routed
31425
+ // through the paste plugin instead. See GHSA-jhhp-r3r7-v2cg
31426
+ .on('drop.DragAndDrop', this.onDrop);
31273
31427
  }
31274
31428
  onDragStart(event) {
31275
31429
  let target = event.target;
@@ -31297,10 +31451,10 @@ jodit_core_global__WEBPACK_IMPORTED_MODULE_4__.pluginSystem.add('dragAndDropElem
31297
31451
  this.addDragListeners();
31298
31452
  }
31299
31453
  addDragListeners() {
31300
- this.j.e.on('dragover', this.onDrag).on('drop.DragAndDrop', this.onDrop).on(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31454
+ this.j.e.on('dragover', this.onDrag).on(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31301
31455
  }
31302
31456
  removeDragListeners() {
31303
- this.j.e.off('dragover', this.onDrag).off('drop.DragAndDrop', this.onDrop).off(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31457
+ this.j.e.off('dragover', this.onDrag).off(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31304
31458
  }
31305
31459
  onDrag(event) {
31306
31460
  if (this.draggable) {
@@ -31362,7 +31516,12 @@ jodit_core_global__WEBPACK_IMPORTED_MODULE_4__.pluginSystem.add('dragAndDropElem
31362
31516
  fragment = (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_6__.dataBind)(this.draggable, 'target');
31363
31517
  }
31364
31518
  } else if (this.getText(event)) {
31365
- fragment = this.j.createInside.fromHTML(this.getText(event));
31519
+ // Dropped markup takes the same sanitizing pass as pasted and
31520
+ // assigned content. See GHSA-jhhp-r3r7-v2cg
31521
+ const box = this.j.createInside.div();
31522
+ box.innerHTML = this.getText(event);
31523
+ this.j.e.fire('safeHTML', box);
31524
+ fragment = box.firstChild !== box.lastChild || !box.firstChild ? box : box.firstChild;
31366
31525
  }
31367
31526
  return fragment;
31368
31527
  }