jodit 4.13.26 → 4.14.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 (167) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/es2015/jodit.css +1 -1
  3. package/es2015/jodit.fat.min.js +19 -19
  4. package/es2015/jodit.js +1104 -884
  5. package/es2015/jodit.min.js +20 -20
  6. package/es2015/plugins/debug/debug.css +1 -1
  7. package/es2015/plugins/debug/debug.js +10 -10
  8. package/es2015/plugins/debug/debug.min.js +4 -4
  9. package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
  10. package/es2015/plugins/speech-recognize/speech-recognize.js +2 -2
  11. package/es2015/plugins/speech-recognize/speech-recognize.min.js +2 -2
  12. package/es2018/jodit.fat.min.js +19 -19
  13. package/es2018/jodit.min.js +19 -19
  14. package/es2018/plugins/debug/debug.min.js +4 -4
  15. package/es2018/plugins/speech-recognize/speech-recognize.min.js +2 -2
  16. package/es2021/jodit.css +1 -1
  17. package/es2021/jodit.fat.min.js +29 -29
  18. package/es2021/jodit.js +1097 -875
  19. package/es2021/jodit.min.js +29 -29
  20. package/es2021/plugins/debug/debug.css +1 -1
  21. package/es2021/plugins/debug/debug.js +10 -10
  22. package/es2021/plugins/debug/debug.min.js +4 -4
  23. package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
  24. package/es2021/plugins/speech-recognize/speech-recognize.js +2 -2
  25. package/es2021/plugins/speech-recognize/speech-recognize.min.js +2 -2
  26. package/es2021.en/jodit.css +1 -1
  27. package/es2021.en/jodit.fat.min.js +29 -29
  28. package/es2021.en/jodit.js +1097 -875
  29. package/es2021.en/jodit.min.js +29 -29
  30. package/es2021.en/plugins/debug/debug.css +1 -1
  31. package/es2021.en/plugins/debug/debug.js +10 -10
  32. package/es2021.en/plugins/debug/debug.min.js +4 -4
  33. package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
  34. package/es2021.en/plugins/speech-recognize/speech-recognize.js +2 -2
  35. package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +2 -2
  36. package/es5/jodit.css +2 -2
  37. package/es5/jodit.fat.min.js +2 -2
  38. package/es5/jodit.js +1221 -925
  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 +10 -10
  43. package/es5/plugins/debug/debug.min.js +2 -2
  44. package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
  45. package/es5/plugins/speech-recognize/speech-recognize.js +2 -2
  46. package/es5/plugins/speech-recognize/speech-recognize.min.js +2 -2
  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/create/create.js +2 -2
  52. package/esm/core/dom/dom.d.ts +21 -13
  53. package/esm/core/dom/dom.js +58 -87
  54. package/esm/core/global.js +3 -2
  55. package/esm/core/helpers/html/apply-styles.js +14 -10
  56. package/esm/core/helpers/html/clean-from-word.js +8 -4
  57. package/esm/core/helpers/html/safe-html.js +23 -14
  58. package/esm/core/helpers/html/strip-tags.js +9 -4
  59. package/esm/core/helpers/utils/align.d.ts +0 -3
  60. package/esm/core/helpers/utils/align.js +15 -18
  61. package/esm/core/helpers/utils/append-script.js +13 -10
  62. package/esm/core/helpers/utils/attr.d.ts +3 -1
  63. package/esm/core/helpers/utils/attr.js +18 -0
  64. package/esm/core/helpers/utils/css.d.ts +18 -1
  65. package/esm/core/helpers/utils/css.js +15 -0
  66. package/esm/core/helpers/utils/print.js +17 -14
  67. package/esm/core/helpers/utils/reset.js +3 -0
  68. package/esm/core/helpers/utils/selector.js +11 -7
  69. package/esm/core/selection/helpers/move-node-inside-start.js +1 -1
  70. package/esm/core/selection/selection.js +29 -26
  71. package/esm/core/selection/style/api/get-suit-parent.js +10 -0
  72. package/esm/core/selection/style/api/is-same-attributes.js +5 -2
  73. package/esm/core/selection/style/api/toggle-attributes.js +8 -9
  74. package/esm/core/selection/style/api/wrap-unwrapped-text.js +2 -2
  75. package/esm/core/traits/elms.js +11 -3
  76. package/esm/core/ui/button/button/button.js +3 -3
  77. package/esm/core/ui/button/group/group.js +2 -1
  78. package/esm/core/ui/button/tooltip/tooltip.js +2 -2
  79. package/esm/core/ui/element.js +1 -1
  80. package/esm/core/ui/form/inputs/area/area.js +3 -2
  81. package/esm/core/ui/form/inputs/file/file.js +2 -1
  82. package/esm/core/ui/form/inputs/input/input.js +5 -5
  83. package/esm/core/ui/group/group.js +7 -7
  84. package/esm/core/ui/icon.js +2 -2
  85. package/esm/core/ui/popup/popup.js +10 -8
  86. package/esm/core/ui/progress-bar/progress-bar.js +3 -4
  87. package/esm/core/view/view-with-toolbar.js +1 -1
  88. package/esm/core/view/view.js +1 -1
  89. package/esm/jodit.js +30 -28
  90. package/esm/modules/dialog/alert.js +1 -1
  91. package/esm/modules/dialog/confirm.js +3 -2
  92. package/esm/modules/dialog/dialog.d.ts +6 -0
  93. package/esm/modules/dialog/dialog.js +40 -22
  94. package/esm/modules/dialog/prompt.js +4 -3
  95. package/esm/modules/file-browser/builders/context-menu.js +5 -5
  96. package/esm/modules/file-browser/config.js +3 -1
  97. package/esm/modules/file-browser/file-browser.js +7 -4
  98. package/esm/modules/file-browser/listeners/state-listeners.js +6 -6
  99. package/esm/modules/image-editor/image-editor.js +31 -17
  100. package/esm/modules/messages/messages.js +2 -1
  101. package/esm/modules/status-bar/status-bar.js +3 -4
  102. package/esm/modules/table/table.js +22 -18
  103. package/esm/modules/toolbar/button/button.js +4 -4
  104. package/esm/modules/toolbar/button/content.js +12 -4
  105. package/esm/modules/toolbar/collection/collection.js +4 -2
  106. package/esm/modules/uploader/config.js +3 -2
  107. package/esm/modules/uploader/helpers/process-old-browser-drag.js +1 -1
  108. package/esm/modules/uploader/uploader.js +7 -2
  109. package/esm/modules/widget/color-picker/color-picker.js +4 -4
  110. package/esm/modules/widget/file-selector/file-selector.js +6 -6
  111. package/esm/modules/widget/tabs/tabs.js +5 -5
  112. package/esm/plugins/add-new-line/add-new-line.js +8 -7
  113. package/esm/plugins/ai-assistant/ui/ui-ai-assistant.js +4 -4
  114. package/esm/plugins/backspace/cases/check-join-neighbors.js +4 -1
  115. package/esm/plugins/clean-html/helpers/visitor/filters/allow-attributes.js +5 -1
  116. package/esm/plugins/clean-html/helpers/visitor/filters/fill-empty-paragraph.js +1 -1
  117. package/esm/plugins/color/config.js +4 -4
  118. package/esm/plugins/copy-format/copy-format.js +1 -1
  119. package/esm/plugins/delete/delete.js +9 -2
  120. package/esm/plugins/drag-and-drop/drag-and-drop.js +1 -1
  121. package/esm/plugins/drag-and-drop-element/drag-and-drop-element.js +1 -1
  122. package/esm/plugins/enter/helpers/insert-paragraph.js +1 -1
  123. package/esm/plugins/enter/helpers/process-empty-li-leaf.js +2 -2
  124. package/esm/plugins/enter/helpers/wrap-text.js +1 -1
  125. package/esm/plugins/fullsize/fullsize.js +3 -2
  126. package/esm/plugins/iframe/iframe.js +6 -5
  127. package/esm/plugins/image-properties/readers/align.js +6 -5
  128. package/esm/plugins/image-properties/readers/index.js +3 -1
  129. package/esm/plugins/image-properties/ui/ui-image-form.js +2 -1
  130. package/esm/plugins/image-properties/writers/index.js +2 -1
  131. package/esm/plugins/image-properties/writers/link.js +1 -1
  132. package/esm/plugins/indent/config.js +3 -2
  133. package/esm/plugins/indent/indent.js +4 -2
  134. package/esm/plugins/media/media.js +10 -7
  135. package/esm/plugins/mobile/config.js +2 -2
  136. package/esm/plugins/paste-storage/paste-storage.js +5 -5
  137. package/esm/plugins/placeholder/placeholder.js +13 -11
  138. package/esm/plugins/print/print.js +2 -2
  139. package/esm/plugins/resize-cells/resize-cells.js +13 -15
  140. package/esm/plugins/resize-handler/resize-handler.js +3 -4
  141. package/esm/plugins/resizer/resizer.js +11 -10
  142. package/esm/plugins/search/helpers/highlight-text-ranges.js +1 -1
  143. package/esm/plugins/search/ui/search.js +1 -1
  144. package/esm/plugins/select/select.js +2 -2
  145. package/esm/plugins/select-cells/select-cells.js +5 -6
  146. package/esm/plugins/source/editor/engines/ace.js +2 -1
  147. package/esm/plugins/source/editor/engines/area.js +3 -3
  148. package/esm/plugins/source/source.js +2 -2
  149. package/esm/plugins/speech-recognize/speech-recognize.js +1 -1
  150. package/esm/plugins/sticky/sticky.js +1 -1
  151. package/esm/plugins/symbols/config.js +3 -2
  152. package/esm/plugins/symbols/symbols.js +6 -5
  153. package/esm/plugins/tab/cases/on-tab-inside-li.js +2 -2
  154. package/esm/plugins/table/config.js +18 -10
  155. package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +2 -2
  156. package/esm/plugins/wrap-nodes/wrap-nodes.js +2 -2
  157. package/esm/plugins/xpath/xpath.js +2 -3
  158. package/esm/types/index.d.ts +1 -0
  159. package/esm/types/vdom.d.ts +96 -0
  160. package/package.json +1 -1
  161. package/types/core/dom/dom.d.ts +21 -13
  162. package/types/core/helpers/utils/align.d.ts +0 -3
  163. package/types/core/helpers/utils/attr.d.ts +3 -1
  164. package/types/core/helpers/utils/css.d.ts +18 -1
  165. package/types/modules/dialog/dialog.d.ts +6 -0
  166. package/types/types/index.d.ts +1 -0
  167. package/types/types/vdom.d.ts +96 -0
@@ -60,14 +60,13 @@ let StatusBar = class StatusBar extends ViewComponent {
60
60
  * Add element in statusbar
61
61
  */
62
62
  append(child, inTheRight = false) {
63
- var _a;
64
63
  const wrapper = this.findEmpty(inTheRight) ||
65
64
  this.j.c.div(this.getFullElName('item'));
66
65
  if (inTheRight) {
67
66
  wrapper.classList.add(this.getFullElName('item-right'));
68
67
  }
69
- wrapper.appendChild(child);
70
- (_a = this.container) === null || _a === void 0 ? void 0 : _a.appendChild(wrapper);
68
+ Dom.append(wrapper, child);
69
+ this.container && Dom.append(this.container, wrapper);
71
70
  if (this.j.o.statusbar) {
72
71
  this.show();
73
72
  }
@@ -78,7 +77,7 @@ let StatusBar = class StatusBar extends ViewComponent {
78
77
  this.target = target;
79
78
  this.mods = {};
80
79
  this.container = jodit.c.div('jodit-status-bar');
81
- target.appendChild(this.container);
80
+ Dom.append(target, this.container);
82
81
  this.hide();
83
82
  }
84
83
  destruct() {
@@ -18,7 +18,8 @@ import * as consts from "../../core/constants.js";
18
18
  import { debounce } from "../../core/decorators/index.js";
19
19
  import { Dom } from "../../core/dom/index.js";
20
20
  import { getContainer } from "../../core/global.js";
21
- import { $$, attr, cssPath, isNumber, toArray, trim } from "../../core/helpers/index.js";
21
+ import { attr, css, cssPath, isNumber, toArray, trim } from "../../core/helpers/index.js";
22
+ import { cssInline } from "../../core/helpers/utils/css.js";
22
23
  const markedValue = new WeakMap();
23
24
  export class Table extends ViewComponent {
24
25
  constructor() {
@@ -166,37 +167,40 @@ export class Table extends ViewComponent {
166
167
  return Table.__formalCoordinate(table, cell, max);
167
168
  }
168
169
  static __appendRow(table, line, after, create) {
169
- var _a;
170
170
  let row;
171
171
  if (!line) {
172
172
  const columnsCount = Table.__getColumnsCount(table);
173
173
  row = create.element('tr');
174
174
  for (let j = 0; j < columnsCount; j += 1) {
175
- row.appendChild(create.element('td'));
175
+ Dom.append(row, create.element('td'));
176
176
  }
177
177
  }
178
178
  else {
179
179
  row = line.cloneNode(true);
180
- $$('td,th', line).forEach(cell => {
180
+ Dom.each(line, cell => {
181
+ if (!Dom.isCell(cell)) {
182
+ return;
183
+ }
181
184
  const rowspan = attr(cell, 'rowspan');
182
185
  if (rowspan && parseInt(rowspan, 10) > 1) {
183
186
  const newRowSpan = parseInt(rowspan, 10) - 1;
184
187
  attr(cell, 'rowspan', newRowSpan > 1 ? newRowSpan : null);
185
188
  }
186
189
  });
187
- $$('td,th', row).forEach(cell => {
188
- cell.innerHTML = '';
190
+ Dom.each(row, cell => {
191
+ if (Dom.isCell(cell)) {
192
+ Dom.detach(cell);
193
+ }
189
194
  });
190
195
  }
191
196
  if (after && line && line.nextSibling) {
192
- line.parentNode &&
193
- line.parentNode.insertBefore(row, line.nextSibling);
197
+ Dom.after(line, row);
194
198
  }
195
199
  else if (!after && line) {
196
- line.parentNode && line.parentNode.insertBefore(row, line);
200
+ Dom.before(line, row);
197
201
  }
198
202
  else {
199
- (((_a = table.getElementsByTagName('tbody')) === null || _a === void 0 ? void 0 : _a[0]) || table).appendChild(row);
203
+ Dom.append(Dom.first(table, node => Dom.isTag(node, 'tbody')) || table, row);
200
204
  }
201
205
  }
202
206
  /**
@@ -243,10 +247,10 @@ export class Table extends ViewComponent {
243
247
  }
244
248
  }
245
249
  if (referenceCell) {
246
- nextRow.insertBefore(cell, referenceCell);
250
+ Dom.before(referenceCell, cell);
247
251
  }
248
252
  else {
249
- nextRow.appendChild(cell);
253
+ Dom.append(nextRow, cell);
250
254
  }
251
255
  }
252
256
  }
@@ -474,7 +478,7 @@ export class Table extends ViewComponent {
474
478
  return;
475
479
  }
476
480
  alreadyMerged.add(td);
477
- if (i === bound[0][0] && td.style.width) {
481
+ if (i === bound[0][0] && cssInline(td, 'width')) {
478
482
  w += td.offsetWidth;
479
483
  }
480
484
  if (trim(cell.innerHTML.replace(/<br(\/)?>/g, '')) !== '') {
@@ -536,7 +540,7 @@ export class Table extends ViewComponent {
536
540
  const __marked = [];
537
541
  Table.__getSelectedCellsByTable(table).forEach((cell) => {
538
542
  td = jodit.createInside.element('td');
539
- td.appendChild(jodit.createInside.element('br'));
543
+ Dom.append(td, jodit.createInside.element('br'));
540
544
  tr = jodit.createInside.element('tr');
541
545
  coord = Table.__formalCoordinate(table, cell);
542
546
  if (cell.rowSpan < 2) {
@@ -548,7 +552,7 @@ export class Table extends ViewComponent {
548
552
  }
549
553
  });
550
554
  Dom.after(Dom.closest(cell, 'tr', table), tr);
551
- tr.appendChild(td);
555
+ Dom.append(tr, td);
552
556
  }
553
557
  else {
554
558
  Table.__mark(cell, 'rowspan', cell.rowSpan - 1, __marked);
@@ -568,7 +572,7 @@ export class Table extends ViewComponent {
568
572
  Dom.after(after, td);
569
573
  }
570
574
  else {
571
- parent.insertBefore(td, parent.firstChild);
575
+ Dom.prepend(parent, td);
572
576
  }
573
577
  }
574
578
  if (cell.colSpan > 1) {
@@ -601,7 +605,7 @@ export class Table extends ViewComponent {
601
605
  Table.__mark(cell, 'colspan', cell.colSpan - 1, __marked);
602
606
  }
603
607
  td = jodit.createInside.element('td');
604
- td.appendChild(jodit.createInside.element('br'));
608
+ Dom.append(td, jodit.createInside.element('br'));
605
609
  if (cell.rowSpan > 1) {
606
610
  Table.__mark(td, 'rowspan', cell.rowSpan, __marked);
607
611
  }
@@ -680,7 +684,7 @@ export class Table extends ViewComponent {
680
684
  }
681
685
  }
682
686
  else {
683
- cell.style.width = value.toString();
687
+ css(cell, 'width', value.toString());
684
688
  }
685
689
  break;
686
690
  }
@@ -131,20 +131,20 @@ let ToolbarButton = class ToolbarButton extends UIButton {
131
131
  value: this,
132
132
  configurable: true
133
133
  });
134
- container.appendChild(button);
134
+ Dom.append(container, button);
135
135
  const trigger = this.j.c.fromHTML(`<span role="button" aria-haspopup="true" aria-expanded="false" class="${cn}__trigger">${Icon.get('chevron')}</span>`);
136
136
  // For caching
137
- button.appendChild(trigger);
137
+ Dom.append(button, trigger);
138
138
  return container;
139
139
  }
140
140
  /** @override */
141
141
  focus() {
142
142
  var _a;
143
- (_a = this.container.querySelector('button')) === null || _a === void 0 ? void 0 : _a.focus();
143
+ (_a = Dom.first(this.container, node => Dom.isTag(node, 'button'))) === null || _a === void 0 ? void 0 : _a.focus();
144
144
  }
145
145
  onChangeHasTrigger() {
146
146
  if (this.state.hasTrigger) {
147
- this.container.appendChild(this.trigger);
147
+ Dom.append(this.container, this.trigger);
148
148
  }
149
149
  else {
150
150
  Dom.safeRemove(this.trigger);
@@ -17,6 +17,12 @@ import { component } from "../../../core/decorators/index.js";
17
17
  import { Dom } from "../../../core/dom/index.js";
18
18
  import { attr, isString } from "../../../core/helpers/index.js";
19
19
  import { UIButton } from "../../../core/ui/button/index.js";
20
+ const FORM_CONTROL_TAGS = new Set([
21
+ 'input',
22
+ 'button',
23
+ 'select',
24
+ 'textarea'
25
+ ]);
20
26
  let ToolbarContent = class ToolbarContent extends UIButton {
21
27
  /** @override */
22
28
  className() {
@@ -29,7 +35,7 @@ let ToolbarContent = class ToolbarContent extends UIButton {
29
35
  const content = control.getContent(this.j, this);
30
36
  if (isString(content) || content.parentNode !== this.container) {
31
37
  Dom.detach(this.container);
32
- this.container.appendChild(isString(content) ? this.j.create.fromHTML(content) : content);
38
+ Dom.append(this.container, isString(content) ? this.j.create.fromHTML(content) : content);
33
39
  }
34
40
  // Content controls never went through the ToolbarButton status
35
41
  // calculation, so `isDisabled`/`isActive`/`update` declared on the
@@ -52,9 +58,11 @@ let ToolbarContent = class ToolbarContent extends UIButton {
52
58
  */
53
59
  onChangeDisabled() {
54
60
  super.onChangeDisabled();
55
- this.container
56
- .querySelectorAll('input,button,select,textarea')
57
- .forEach(elm => attr(elm, 'disabled', this.state.disabled || null));
61
+ Dom.each(this.container, elm => {
62
+ if (Dom.isTag(elm, FORM_CONTROL_TAGS)) {
63
+ attr(elm, 'disabled', this.state.disabled || null);
64
+ }
65
+ });
58
66
  }
59
67
  /** @override */
60
68
  createContainer() {
@@ -18,6 +18,8 @@ import { autobind } from "../../../core/decorators/autobind/autobind.js";
18
18
  import { component } from "../../../core/decorators/component/component.js";
19
19
  import { hook } from "../../../core/decorators/hook/hook.js";
20
20
  import { watch } from "../../../core/decorators/watch/watch.js";
21
+ import { attr } from "../../../core/helpers/utils/attr.js";
22
+ import { css } from "../../../core/helpers/utils/css.js";
21
23
  import { error } from "../../../core/helpers/utils/error/error.js";
22
24
  import { UIList } from "../../../core/ui/group/list.js";
23
25
  import { makeButton, makeSelect } from "../factory.js";
@@ -73,8 +75,8 @@ let ToolbarCollection = class ToolbarCollection extends UIList {
73
75
  * Set direction
74
76
  */
75
77
  setDirection(direction) {
76
- this.container.style.direction = direction;
77
- this.container.setAttribute('dir', direction);
78
+ css(this.container, 'direction', direction);
79
+ attr(this.container, 'dir', direction);
78
80
  }
79
81
  constructor(jodit) {
80
82
  super(jodit);
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { isArray } from "../../core/helpers/checker/is-array.js";
7
7
  import { isJoditObject } from "../../core/helpers/checker/is-jodit-object.js";
8
+ import { attr } from "../../core/helpers/utils/attr.js";
8
9
  import { Config } from "../../config.js";
9
10
  /**
10
11
  * Module for processing download documents and images by Drag and Drop
@@ -68,11 +69,11 @@ Config.prototype.uploader = {
68
69
  }
69
70
  if (resp.files && resp.files.length) {
70
71
  resp.files.forEach((filename, index) => {
71
- const [tagName, attr] = resp.isImages && resp.isImages[index]
72
+ const [tagName, attrName] = resp.isImages && resp.isImages[index]
72
73
  ? ['img', 'src']
73
74
  : ['a', 'href'];
74
75
  const elm = j.createInside.element(tagName);
75
- elm.setAttribute(attr, resp.baseurl + filename);
76
+ attr(elm, attrName, resp.baseurl + filename);
76
77
  if (tagName === 'a') {
77
78
  elm.textContent = j.o.uploader.getDisplayName.call(this, resp.baseurl, filename);
78
79
  }
@@ -17,7 +17,7 @@ export function processOldBrowserDrag(self, cData, handlerSuccess, handlerError,
17
17
  'overflow: hidden; position: fixed; z-index: 2147483647; word-break: break-all;',
18
18
  contenteditable: true
19
19
  });
20
- getContainer(self.j, self.constructor).appendChild(div);
20
+ Dom.append(getContainer(self.j, self.constructor), div);
21
21
  const selection = isJoditObject(self.j) ? self.j.s.save() : null, restore = () => selection && isJoditObject(self.j) && self.j.s.restore();
22
22
  div.focus();
23
23
  self.j.async.setTimeout(() => {
@@ -5,7 +5,8 @@
5
5
  */
6
6
  import { STATUSES, ViewComponent } from "../../core/component/index.js";
7
7
  import { IS_ES_NEXT, IS_IE } from "../../core/constants.js";
8
- import { ConfigProto, error, isFunction, isJoditObject } from "../../core/helpers/index.js";
8
+ import { Dom } from "../../core/dom/dom.js";
9
+ import { attr, ConfigProto, error, isFunction, isJoditObject } from "../../core/helpers/index.js";
9
10
  import { Config } from "../../config.js";
10
11
  import { ajaxInstances, hasFiles, hasItems, processOldBrowserDrag, send, sendFiles } from "./helpers/index.js";
11
12
  import "./config.js";
@@ -129,7 +130,11 @@ export class Uploader extends ViewComponent {
129
130
  sendFiles(self, event.dataTransfer.files, handlerSuccess, handlerError).finally(onFinally);
130
131
  }
131
132
  });
132
- const inputFile = form.querySelector('input[type=file]');
133
+ const inputFile = Dom.first(form, node => {
134
+ var _a;
135
+ return Dom.isTag(node, 'input') &&
136
+ ((_a = attr(node, 'type')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'file';
137
+ });
133
138
  if (inputFile) {
134
139
  self.j.e.on(inputFile, 'change', () => {
135
140
  sendFiles(self, inputFile.files, handlerSuccess, handlerError)
@@ -46,10 +46,10 @@ export const ColorPickerWidget = (editor, callback, coldColor) => {
46
46
  }
47
47
  return stack.join('');
48
48
  };
49
- form.appendChild(editor.c.fromHTML(`<div class="${cn}__groups">${eachColor(editor.o.colors)}</div>`));
50
- form.appendChild(editor.c.fromHTML(`<div data-ref="extra" class="${cn}__extra"></div>`));
49
+ Dom.append(form, editor.c.fromHTML(`<div class="${cn}__groups">${eachColor(editor.o.colors)}</div>`));
50
+ Dom.append(form, editor.c.fromHTML(`<div data-ref="extra" class="${cn}__extra"></div>`));
51
51
  const { extra } = refs(form);
52
- extra.appendChild(editor.c.fromHTML(`<div class="${cn}__hex"><input data-ref="hexInput" type="text" spellcheck="false" aria-label="HEX" placeholder="#FF0000" value="${valueHex || ''}"/></div>`));
52
+ Dom.append(extra, editor.c.fromHTML(`<div class="${cn}__hex"><input data-ref="hexInput" type="text" spellcheck="false" aria-label="HEX" placeholder="#FF0000" value="${valueHex || ''}"/></div>`));
53
53
  const { hexInput } = refs(form);
54
54
  // Enter applies the value and closes the popup; removing the focused
55
55
  // input then makes Chrome fire `change` on it, which would apply the
@@ -84,7 +84,7 @@ export const ColorPickerWidget = (editor, callback, coldColor) => {
84
84
  applyHexInput();
85
85
  });
86
86
  if (editor.o.showBrowserColorPicker && hasBrowserColorPicker()) {
87
- extra.appendChild(editor.c.fromHTML(`<div class="${cn}__native">${iconPalette}<input type="color" value="#ffffff"/></div>`));
87
+ Dom.append(extra, editor.c.fromHTML(`<div class="${cn}__native">${iconPalette}<input type="color" value="#ffffff"/></div>`));
88
88
  editor.e.on(form, 'change', (e) => {
89
89
  e.stopPropagation();
90
90
  const target = e.target;
@@ -88,13 +88,13 @@ export const FileSelectorWidget = (editor, callbacks, elm, close, isImage = true
88
88
  !Dom.isComment(elm) &&
89
89
  (Dom.isTag(elm, 'img') || $$('img', elm).length)) {
90
90
  currentImage = elm.tagName === 'IMG' ? elm : $$('img', elm)[0];
91
- val(form.container, 'input[name=url]', attr(currentImage, 'src'));
92
- val(form.container, 'input[name=text]', attr(currentImage, 'alt'));
91
+ val(form.container, 'url', attr(currentImage, 'src'));
92
+ val(form.container, 'text', attr(currentImage, 'alt'));
93
93
  button.state.text = 'Update';
94
94
  }
95
95
  if (elm && Dom.isTag(elm, 'a')) {
96
- val(form.container, 'input[name=url]', attr(elm, 'href'));
97
- val(form.container, 'input[name=text]', attr(elm, 'title'));
96
+ val(form.container, 'url', attr(elm, 'href'));
97
+ val(form.container, 'text', attr(elm, 'title'));
98
98
  button.state.text = 'Update';
99
99
  }
100
100
  form.onSubmit(data => {
@@ -116,8 +116,8 @@ export const FileSelectorWidget = (editor, callbacks, elm, close, isImage = true
116
116
  box.classList.add('jodit-file-selector');
117
117
  return box;
118
118
  };
119
- function val(elm, selector, value) {
120
- const child = elm.querySelector(selector);
119
+ function val(elm, name, value) {
120
+ const child = Dom.first(elm, node => Dom.isTag(node, 'input') && attr(node, 'name') === name);
121
121
  if (!child) {
122
122
  return '';
123
123
  }
@@ -47,8 +47,8 @@ export const TabsWidget = (jodit, tabs, state) => {
47
47
  const nameToTab = {};
48
48
  const buttonList = [];
49
49
  let firstTab = '';
50
- box.appendChild(buttons);
51
- box.appendChild(tabBox);
50
+ Dom.append(box, buttons);
51
+ Dom.append(box, tabBox);
52
52
  const setActive = (tab) => {
53
53
  if (!nameToTab[tab]) {
54
54
  return;
@@ -72,18 +72,18 @@ export const TabsWidget = (jodit, tabs, state) => {
72
72
  if (!firstTab) {
73
73
  firstTab = name;
74
74
  }
75
- buttons.appendChild(button.container);
75
+ Dom.append(buttons, button.container);
76
76
  buttonList.push(button);
77
77
  button.container.classList.add('jodit-tabs__button', 'jodit-tabs__button_columns_' + tabs.length);
78
78
  if (!isFunction(content)) {
79
- tab.appendChild(Component.isInstanceOf(content, UIElement)
79
+ Dom.append(tab, Component.isInstanceOf(content, UIElement)
80
80
  ? content.container
81
81
  : content);
82
82
  }
83
83
  else {
84
84
  tab.classList.add('jodit-tab_empty');
85
85
  }
86
- tabBox.appendChild(tab);
86
+ Dom.append(tabBox, tab);
87
87
  button.onAction(() => {
88
88
  setActive(name);
89
89
  if (isFunction(content) && !Dom.isElement(content)) {
@@ -16,6 +16,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
16
16
  import { autobind, throttle, watch } from "../../core/decorators/index.js";
17
17
  import { pluginSystem } from "../../core/global.js";
18
18
  import { call, offset, position, scrollIntoViewIfNeeded } from "../../core/helpers/index.js";
19
+ import { css } from "../../core/helpers/utils/css.js";
19
20
  import { Dom, Icon, Plugin } from "../../modules/index.js";
20
21
  import "./config.js";
21
22
  const ns = 'addnewline';
@@ -56,11 +57,11 @@ export class addNewLine extends Plugin {
56
57
  Dom.prepend(editor.editor, p);
57
58
  }
58
59
  else {
59
- this.__current.parentNode.insertBefore(p, this.__current);
60
+ Dom.before(this.__current, p);
60
61
  }
61
62
  }
62
63
  else {
63
- editor.editor.appendChild(p);
64
+ Dom.append(editor.editor, p);
64
65
  }
65
66
  editor.s.setCursorIn(p);
66
67
  scrollIntoViewIfNeeded(p, editor.editor, editor.ed);
@@ -78,8 +79,8 @@ export class addNewLine extends Plugin {
78
79
  return;
79
80
  }
80
81
  this.__isShown = true;
81
- this.j.container.appendChild(this.__line);
82
- this.__line.style.width = this.j.container.clientWidth + 'px';
82
+ Dom.append(this.j.container, this.__line);
83
+ css(this.__line, 'width', this.j.container.clientWidth);
83
84
  }
84
85
  onLock(isLocked) {
85
86
  if (isLocked && this.__isShown) {
@@ -139,10 +140,10 @@ export class addNewLine extends Plugin {
139
140
  if (Math.abs(top - editorBound.top) <
140
141
  Math.abs(top - (editorBound.height + editorBound.top)) &&
141
142
  editor.editor.firstChild) {
142
- editor.editor.insertBefore(p, editor.editor.firstChild);
143
+ Dom.prepend(editor.editor, p);
143
144
  }
144
145
  else {
145
- editor.editor.appendChild(p);
146
+ Dom.append(editor.editor, p);
146
147
  }
147
148
  editor.s.setCursorIn(p);
148
149
  editor.synchronizeValues();
@@ -196,7 +197,7 @@ export class addNewLine extends Plugin {
196
197
  ((isEditor && !this.__isBeforeContent) ||
197
198
  (!isEditor &&
198
199
  !call(this.__isBeforeContent ? Dom.prev : Dom.next, currentElement, this.__canGetFocus, editor.editor)))) {
199
- this.__line.style.top = top + 'px';
200
+ css(this.__line, 'top', top);
200
201
  this.__current = currentElement;
201
202
  this.__show();
202
203
  this.__line.style.setProperty('--jd-anl-handle-offset', clientX - pos.left - 10 + 'px');
@@ -68,11 +68,11 @@ let UiAiAssistant = class UiAiAssistant extends UIElement {
68
68
  this.__results.classList.remove(hideMod);
69
69
  this.__buttons.classList.remove(hideMod);
70
70
  Dom.detach(this.__results);
71
- this.__results.appendChild(this.__spinner);
71
+ Dom.append(this.__results, this.__spinner);
72
72
  this.__insertButton.focus();
73
73
  });
74
- this.__buttons.appendChild(buttonsBLock.container);
75
- this.__body.appendChild(this.__formAiAssistant.container);
74
+ Dom.append(this.__buttons, buttonsBLock.container);
75
+ Dom.append(this.__body, this.__formAiAssistant.container);
76
76
  this.onChangePromptValue();
77
77
  }
78
78
  render() {
@@ -111,7 +111,7 @@ let UiAiAssistant = class UiAiAssistant extends UIElement {
111
111
  this.setMod('loading', false);
112
112
  Dom.detach(this.__results);
113
113
  this.__aiResult = result;
114
- this.__results.appendChild(this.jodit.c.fromHTML(result));
114
+ Dom.append(this.__results, this.jodit.c.fromHTML(result));
115
115
  this.__toggleSubmitButton(false);
116
116
  this.__toggleInsertButton(false);
117
117
  }
@@ -50,7 +50,10 @@ function resolveTableSibling(sibling, backspace) {
50
50
  if (!Dom.isTag(sibling, 'table')) {
51
51
  return sibling;
52
52
  }
53
- const cells = sibling.querySelectorAll('td,th');
53
+ const cells = [];
54
+ Dom.each(sibling, node => {
55
+ Dom.isCell(node) && cells.push(node);
56
+ });
54
57
  return cells.length ? cells[backspace ? cells.length - 1 : 0] : null;
55
58
  }
56
59
  function checkMoveListContent(jodit, mainClosestBox, sibling, backspace) {
@@ -4,6 +4,7 @@
4
4
  * Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
5
5
  */
6
6
  import { Dom } from "../../../../../core/dom/dom.js";
7
+ import { attrRaw } from "../../../../../core/helpers/utils/attr.js";
7
8
  /**
8
9
  * @private
9
10
  */
@@ -29,7 +30,10 @@ export function allowAttributes(jodit, nodeElm, hadEffect, allow) {
29
30
  hadEffect = true;
30
31
  }
31
32
  removeAttrs.forEach(attr => {
32
- nodeElm.removeAttribute(attr);
33
+ // `attrRaw` on purpose: the sanitizer must remove exactly the
34
+ // attribute name from the live list, without the `attr()`
35
+ // helper name normalization
36
+ attrRaw(nodeElm, attr, null);
33
37
  });
34
38
  }
35
39
  }
@@ -21,7 +21,7 @@ export function fillEmptyParagraph(jodit, nodeElm, hadEffect) {
21
21
  Dom.isEmpty(nodeElm, INSEPARABLE_TAGS) &&
22
22
  !Dom.isTag(nodeElm, TABLE_CONTAINER_TAGS)) {
23
23
  const br = jodit.createInside.element('br');
24
- nodeElm.appendChild(br);
24
+ Dom.append(nodeElm, br);
25
25
  return true;
26
26
  }
27
27
  return hadEffect;
@@ -105,7 +105,7 @@ Config.prototype.controls.brush = {
105
105
  editor.execCommand('background', false, value);
106
106
  }
107
107
  else {
108
- currentElement.style.backgroundColor = value;
108
+ css(currentElement, 'backgroundColor', value);
109
109
  }
110
110
  dataBind(button, 'color', value);
111
111
  dataBind(button, 'color-mode', 'background');
@@ -116,7 +116,7 @@ Config.prototype.controls.brush = {
116
116
  editor.execCommand('forecolor', false, value);
117
117
  }
118
118
  else {
119
- currentElement.style.color = value;
119
+ css(currentElement, 'color', value);
120
120
  }
121
121
  dataBind(button, 'color', value);
122
122
  dataBind(button, 'color-mode', 'color');
@@ -148,10 +148,10 @@ Config.prototype.controls.brush = {
148
148
  Dom.isElement(current)) {
149
149
  switch (mode) {
150
150
  case 'color':
151
- current.style.color = color;
151
+ css(current, 'color', color);
152
152
  break;
153
153
  case 'background':
154
- current.style.backgroundColor = color;
154
+ css(current, 'backgroundColor', color);
155
155
  break;
156
156
  }
157
157
  }
@@ -68,7 +68,7 @@ Config.prototype.controls.copyformat = {
68
68
  else {
69
69
  const defaultStyles = {}, box = Dom.up(current, (elm) => elm && !Dom.isText(elm), editor.editor) || editor.editor;
70
70
  const ideal = editor.createInside.span();
71
- editor.editor.appendChild(ideal);
71
+ Dom.append(editor.editor, ideal);
72
72
  copyStyles.forEach((key) => {
73
73
  defaultStyles[key] = css(ideal, key);
74
74
  });
@@ -9,6 +9,13 @@ import { $$ } from "../../core/helpers/index.js";
9
9
  import { trim } from "../../core/helpers/string/trim.js";
10
10
  import { Plugin } from "../../core/plugin/index.js";
11
11
  import "./interface.js";
12
+ const NOT_EMPTY_CONTENT_TAGS = new Set([
13
+ 'img',
14
+ 'table',
15
+ 'jodit',
16
+ 'iframe',
17
+ 'hr'
18
+ ]);
12
19
  export class deleteCommand extends Plugin {
13
20
  afterInit(jodit) {
14
21
  jodit.e.on('afterCommand.delete', (command) => {
@@ -35,9 +42,9 @@ export class deleteCommand extends Plugin {
35
42
  jodit.s.removeNode(current.firstChild);
36
43
  }
37
44
  if (!trim(jodit.editor.textContent || '') &&
38
- !jodit.editor.querySelector('img,table,jodit,iframe,hr') &&
45
+ !Dom.first(jodit.editor, node => Dom.isTag(node, NOT_EMPTY_CONTENT_TAGS)) &&
39
46
  (!current || !Dom.closest(current, 'table', jodit.editor))) {
40
- jodit.editor.innerHTML = '';
47
+ Dom.detach(jodit.editor);
41
48
  const node = jodit.s.setCursorIn(jodit.editor);
42
49
  jodit.s.removeNode(node);
43
50
  }
@@ -58,7 +58,7 @@ export class dragAndDrop extends Plugin {
58
58
  this.startDragPoint.x = event.clientX;
59
59
  this.startDragPoint.y = event.clientY;
60
60
  if (isFileBrowserFilesItem(target)) {
61
- target = target.querySelector('img');
61
+ target = Dom.first(target, node => Dom.isTag(node, 'img'));
62
62
  }
63
63
  if (Dom.isTag(target, 'img')) {
64
64
  this.draggable = target.cloneNode(true);
@@ -150,7 +150,7 @@ export class dragAndDropElement extends Plugin {
150
150
  width: (_a = target === null || target === void 0 ? void 0 : target.offsetWidth) !== null && _a !== void 0 ? _a : 100,
151
151
  height: (_b = target === null || target === void 0 ? void 0 : target.offsetHeight) !== null && _b !== void 0 ? _b : 100
152
152
  });
153
- getContainer(this.j, dragAndDropElement).appendChild(this.draggable);
153
+ Dom.append(getContainer(this.j, dragAndDropElement), this.draggable);
154
154
  }
155
155
  css(this.draggable, {
156
156
  left: event.clientX,
@@ -13,7 +13,7 @@ import { scrollIntoViewIfNeeded } from "../../../core/helpers/utils/scroll-into-
13
13
  export function insertParagraph(fake, editor, wrapperTag, style) {
14
14
  const isBR = wrapperTag.toLowerCase() === 'br', { createInside } = editor, p = createInside.element(wrapperTag), br = createInside.element('br');
15
15
  if (!isBR) {
16
- p.appendChild(br);
16
+ Dom.append(p, br);
17
17
  }
18
18
  if (style && style.cssText) {
19
19
  attr(p, 'style', style.cssText);
@@ -28,11 +28,11 @@ export function processEmptyLILeaf(fake, jodit, li) {
28
28
  Dom.safeRemove(list);
29
29
  }
30
30
  const newLi = insertParagraph(fake, jodit, listInsideLeaf ? 'li' : jodit.o.enter);
31
- if (!rightPart.querySelector('li')) {
31
+ if (!Dom.first(rightPart, node => Dom.isTag(node, 'li'))) {
32
32
  return;
33
33
  }
34
34
  if (listInsideLeaf) {
35
- newLi.appendChild(rightPart);
35
+ Dom.append(newLi, rightPart);
36
36
  }
37
37
  else {
38
38
  Dom.after(newLi, rightPart);
@@ -19,7 +19,7 @@ export function wrapText(fake, jodit) {
19
19
  const currentBox = Dom.wrapInline(needWrap, jodit.o.enter, jodit);
20
20
  if (Dom.isEmpty(currentBox)) {
21
21
  const br = jodit.createInside.element('br');
22
- currentBox.appendChild(br);
22
+ Dom.append(currentBox, br);
23
23
  Dom.before(br, fake);
24
24
  }
25
25
  return currentBox;