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/es2021/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
  */
@@ -1799,7 +1799,7 @@ __webpack_require__.r(__webpack_exports__);
1799
1799
  * ```
1800
1800
  * @packageDocumentation
1801
1801
  * @module constants
1802
- */ const APP_VERSION = "4.17.0";
1802
+ */ const APP_VERSION = "4.17.2";
1803
1803
  // prettier-ignore
1804
1804
  const ES = "es2021";
1805
1805
  const IS_ES_MODERN = true;
@@ -6281,7 +6281,7 @@ function isSmuggledForeignHtml(elm) {
6281
6281
  }
6282
6282
  return /^data:image\/svg/.test(normalized) && DOCUMENT_EMBED_TAGS.has(tagName);
6283
6283
  }
6284
- function sanitizeHTMLElement(elm, { safeJavaScriptLink, removeOnError } = {
6284
+ function sanitizeHTMLElement(elm, { safeJavaScriptLink, removeOnError, removeEventAttributes } = {
6285
6285
  safeJavaScriptLink: true,
6286
6286
  removeOnError: true
6287
6287
  }) {
@@ -6289,6 +6289,13 @@ function sanitizeHTMLElement(elm, { safeJavaScriptLink, removeOnError } = {
6289
6289
  return false;
6290
6290
  }
6291
6291
  let effected = false;
6292
+ // Every `on*` handler, not only `onerror`: the clean-html background
6293
+ // pass calls this directly, and markup that reached the editable area
6294
+ // without `safeHTML` (a drop, a script) kept its handlers otherwise.
6295
+ // See GHSA-jhhp-r3r7-v2cg
6296
+ if (removeEventAttributes && removeAllEventAttributes(elm)) {
6297
+ effected = true;
6298
+ }
6292
6299
  if (removeOnError && elm.hasAttribute('onerror')) {
6293
6300
  (0,jodit_core_helpers_utils__WEBPACK_IMPORTED_MODULE_1__.attr)(elm, 'onerror', null);
6294
6301
  effected = true;
@@ -10534,6 +10541,70 @@ class Response {
10534
10541
  }
10535
10542
 
10536
10543
 
10544
+ /***/ }),
10545
+
10546
+ /***/ 43134:
10547
+ /***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
10548
+
10549
+ "use strict";
10550
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10551
+ /* harmony export */ composedRanges: function() { return /* binding */ composedRanges; }
10552
+ /* harmony export */ });
10553
+ /* harmony import */ var jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(28686);
10554
+ /*!
10555
+ * Jodit Editor (https://xdsoft.net/jodit/)
10556
+ * Released under MIT see LICENSE.txt in the project root for license information.
10557
+ * Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
10558
+ */ /**
10559
+ * @module selection
10560
+ */
10561
+ function isInside(node, shadowRoot) {
10562
+ return node === shadowRoot || shadowRoot.contains(node);
10563
+ }
10564
+ function usable(ranges, shadowRoot) {
10565
+ return Array.isArray(ranges) && ranges.length > 0 && ranges.every((range)=>isInside(range.startContainer, shadowRoot));
10566
+ }
10567
+ /**
10568
+ * Ranges of a selection that lies inside the given shadow tree.
10569
+ *
10570
+ * `window.getSelection()` stops at the shadow boundary and reports the host
10571
+ * instead of the node the caret is really in. `getComposedRanges` is the
10572
+ * standard way to ask past that boundary.
10573
+ *
10574
+ * @returns `null` when the browser has no `getComposedRanges`, or when neither
10575
+ * call shape returned ranges that point inside the shadow tree — in which case
10576
+ * there is nothing better to offer than the plain window selection.
10577
+ */ function composedRanges(selection, shadowRoot) {
10578
+ const getComposedRanges = selection.getComposedRanges;
10579
+ if (!(0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_0__.isFunction)(getComposedRanges)) {
10580
+ return null;
10581
+ }
10582
+ for (const args of [
10583
+ [
10584
+ {
10585
+ shadowRoots: [
10586
+ shadowRoot
10587
+ ]
10588
+ }
10589
+ ],
10590
+ [
10591
+ shadowRoot
10592
+ ]
10593
+ ]){
10594
+ let ranges;
10595
+ try {
10596
+ ranges = getComposedRanges.apply(selection, args);
10597
+ } catch {
10598
+ continue;
10599
+ }
10600
+ if (usable(ranges, shadowRoot)) {
10601
+ return ranges;
10602
+ }
10603
+ }
10604
+ return null;
10605
+ }
10606
+
10607
+
10537
10608
  /***/ }),
10538
10609
 
10539
10610
  /***/ 42259:
@@ -10541,14 +10612,16 @@ class Response {
10541
10612
 
10542
10613
  "use strict";
10543
10614
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
10615
+ /* harmony export */ composedRanges: function() { return /* reexport safe */ _composed_ranges__WEBPACK_IMPORTED_MODULE_2__.composedRanges; },
10544
10616
  /* harmony export */ cursorInTheEdgeOfString: function() { return /* binding */ cursorInTheEdgeOfString; },
10545
10617
  /* harmony export */ findCorrectCurrentNode: function() { return /* binding */ findCorrectCurrentNode; },
10546
- /* harmony export */ moveNodeInsideStart: function() { return /* reexport safe */ _move_node_inside_start__WEBPACK_IMPORTED_MODULE_2__.moveNodeInsideStart; }
10618
+ /* harmony export */ moveNodeInsideStart: function() { return /* reexport safe */ _move_node_inside_start__WEBPACK_IMPORTED_MODULE_3__.moveNodeInsideStart; }
10547
10619
  /* harmony export */ });
10548
10620
  /* harmony import */ var jodit_core_constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(81937);
10549
10621
  /* harmony import */ var jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23211);
10550
- /* harmony import */ var _move_node_inside_start__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(89817);
10551
- /* harmony import */ var _move_the_node_along_the_edge_outward__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7470);
10622
+ /* harmony import */ var _composed_ranges__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(43134);
10623
+ /* harmony import */ var _move_node_inside_start__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(89817);
10624
+ /* harmony import */ var _move_the_node_along_the_edge_outward__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7470);
10552
10625
  /*!
10553
10626
  * Jodit Editor (https://xdsoft.net/jodit/)
10554
10627
  * Released under MIT see LICENSE.txt in the project root for license information.
@@ -10559,6 +10632,7 @@ class Response {
10559
10632
 
10560
10633
 
10561
10634
 
10635
+
10562
10636
  /**
10563
10637
  * Despite the name, returns `true` when the cursor is NOT at the checked edge
10564
10638
  * of the text node: there is significant (non invisible-space) text between
@@ -10787,11 +10861,87 @@ class Selection {
10787
10861
  /**
10788
10862
  * Return current selection object
10789
10863
  */ get sel() {
10790
- if (this.j.o.shadowRoot && (0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isFunction)(this.j.o.shadowRoot.getSelection)) {
10791
- return this.j.o.shadowRoot.getSelection();
10864
+ const { shadowRoot } = this.j.o;
10865
+ if (shadowRoot) {
10866
+ if ((0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isFunction)(shadowRoot.getSelection)) {
10867
+ return shadowRoot.getSelection();
10868
+ }
10869
+ const composed = this.__composedSelection(shadowRoot);
10870
+ if (composed) {
10871
+ return composed;
10872
+ }
10792
10873
  }
10793
10874
  return this.win.getSelection();
10794
10875
  }
10876
+ /**
10877
+ * Selection of a shadow tree in a browser without `ShadowRoot.getSelection`.
10878
+ *
10879
+ * `ShadowRoot.getSelection()` is a non-standard method that WebKit never
10880
+ * implemented, and `window.getSelection()` stops at the shadow boundary: for
10881
+ * a caret inside the shadow tree it reports the host, or the document
10882
+ * itself. Everything downstream then works on the wrong tree, which is why
10883
+ * Backspace used to throw `HierarchyRequestError` and Enter did nothing when
10884
+ * the editor lived in a shadow root in Safari.
10885
+ *
10886
+ * The standard replacement is `Selection.getComposedRanges()`, which does
10887
+ * reach into a shadow tree it is given. It hands back `StaticRange`s, and
10888
+ * the editor mutates ranges constantly, so they are turned into live ones.
10889
+ *
10890
+ * Reads are answered from those ranges; everything else, including the
10891
+ * writes (`addRange`, `removeAllRanges`, `setBaseAndExtent`), goes to the
10892
+ * real selection, which does accept nodes inside a shadow tree. Reading is
10893
+ * the only side the browser blocks.
10894
+ *
10895
+ * @returns `null` when the browser offers neither API, so the caller falls
10896
+ * back to the plain window selection.
10897
+ */ __composedSelection(shadowRoot) {
10898
+ const selection = this.win.getSelection();
10899
+ if (!selection) {
10900
+ return null;
10901
+ }
10902
+ // Firefox has no `ShadowRoot.getSelection` either, but its window
10903
+ // selection does see into a shadow tree. Where the plain selection
10904
+ // already points at the right node there is nothing to work around, and
10905
+ // taking it over would change behaviour that works today.
10906
+ const { anchorNode } = selection;
10907
+ if (anchorNode && jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_4__.Dom.isOrContains(shadowRoot, anchorNode)) {
10908
+ return null;
10909
+ }
10910
+ const ranges = (0,_helpers__WEBPACK_IMPORTED_MODULE_11__.composedRanges)(selection, shadowRoot);
10911
+ if (!ranges) {
10912
+ return null;
10913
+ }
10914
+ const live = ranges.map((staticRange)=>{
10915
+ const range = this.createRange();
10916
+ range.setStart(staticRange.startContainer, staticRange.startOffset);
10917
+ range.setEnd(staticRange.endContainer, staticRange.endOffset);
10918
+ return range;
10919
+ });
10920
+ const first = live[0];
10921
+ const overrides = {
10922
+ rangeCount: live.length,
10923
+ getRangeAt: (index)=>live[index],
10924
+ isCollapsed: live.every((range)=>range.collapsed),
10925
+ // Without these the editor asks the window selection where the
10926
+ // caret is, is told "outside the editable area", and resets the
10927
+ // caret to the start of it — which is the focus loss that shows up
10928
+ // right after a successful Backspace.
10929
+ anchorNode: first ? first.startContainer : null,
10930
+ anchorOffset: first ? first.startOffset : 0,
10931
+ focusNode: first ? first.endContainer : null,
10932
+ focusOffset: first ? first.endOffset : 0,
10933
+ toString: ()=>live.map((range)=>range.toString()).join('')
10934
+ };
10935
+ return new Proxy(selection, {
10936
+ get (target, property) {
10937
+ if ((0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isString)(property) && property in overrides) {
10938
+ return overrides[property];
10939
+ }
10940
+ const value = Reflect.get(target, property, target);
10941
+ return (0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_6__.isFunction)(value) ? value.bind(target) : value;
10942
+ }
10943
+ });
10944
+ }
10795
10945
  /**
10796
10946
  * Return first selected range or create new
10797
10947
  */ get range() {
@@ -31049,7 +31199,11 @@ jodit_core_global__WEBPACK_IMPORTED_MODULE_4__.pluginSystem.add('dragAndDropElem
31049
31199
  window,
31050
31200
  this.j.ed,
31051
31201
  this.j.editor
31052
- ], 'dragstart.DragAndDrop', this.onDragStart);
31202
+ ], 'dragstart.DragAndDrop', this.onDragStart)// Always, not only after a `dragstart` seen in this window: a drop
31203
+ // from another window or application never produces one here, and
31204
+ // the browser then inserted its HTML natively, unsanitized. Routed
31205
+ // through the paste plugin instead. See GHSA-jhhp-r3r7-v2cg
31206
+ .on('drop.DragAndDrop', this.onDrop);
31053
31207
  }
31054
31208
  onDragStart(event) {
31055
31209
  let target = event.target;
@@ -31077,10 +31231,10 @@ jodit_core_global__WEBPACK_IMPORTED_MODULE_4__.pluginSystem.add('dragAndDropElem
31077
31231
  this.addDragListeners();
31078
31232
  }
31079
31233
  addDragListeners() {
31080
- this.j.e.on('dragover', this.onDrag).on('drop.DragAndDrop', this.onDrop).on(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31234
+ this.j.e.on('dragover', this.onDrag).on(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31081
31235
  }
31082
31236
  removeDragListeners() {
31083
- this.j.e.off('dragover', this.onDrag).off('drop.DragAndDrop', this.onDrop).off(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31237
+ this.j.e.off('dragover', this.onDrag).off(window, 'dragend.DragAndDrop drop.DragAndDrop mouseup.DragAndDrop', this.onDragEnd);
31084
31238
  }
31085
31239
  onDrag(event) {
31086
31240
  if (this.draggable) {
@@ -31142,7 +31296,12 @@ jodit_core_global__WEBPACK_IMPORTED_MODULE_4__.pluginSystem.add('dragAndDropElem
31142
31296
  fragment = (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_6__.dataBind)(this.draggable, 'target');
31143
31297
  }
31144
31298
  } else if (this.getText(event)) {
31145
- fragment = this.j.createInside.fromHTML(this.getText(event));
31299
+ // Dropped markup takes the same sanitizing pass as pasted and
31300
+ // assigned content. See GHSA-jhhp-r3r7-v2cg
31301
+ const box = this.j.createInside.div();
31302
+ box.innerHTML = this.getText(event);
31303
+ this.j.e.fire('safeHTML', box);
31304
+ fragment = box.firstChild !== box.lastChild || !box.firstChild ? box : box.firstChild;
31146
31305
  }
31147
31306
  return fragment;
31148
31307
  }