jodit 3.15.2 → 3.16.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 (260) hide show
  1. package/.idea/workspace.xml +301 -299
  2. package/CHANGELOG.MD +88 -7
  3. package/CONTRIBUTING.md +97 -0
  4. package/README.md +7 -7
  5. package/build/jodit.css +38 -32
  6. package/build/jodit.es2018.css +37 -31
  7. package/build/jodit.es2018.en.css +37 -31
  8. package/build/jodit.es2018.en.js +1981 -1393
  9. package/build/jodit.es2018.en.min.css +1 -1
  10. package/build/jodit.es2018.en.min.js +1 -1
  11. package/build/jodit.es2018.js +2053 -1447
  12. package/build/jodit.es2018.min.css +1 -1
  13. package/build/jodit.es2018.min.js +1 -1
  14. package/build/jodit.js +3475 -2625
  15. package/build/jodit.min.css +2 -2
  16. package/build/jodit.min.js +1 -1
  17. package/build/vdom.css +1 -1
  18. package/build/vdom.js +32 -20
  19. package/package.json +13 -13
  20. package/src/README.md +1 -1
  21. package/src/config.ts +69 -36
  22. package/src/core/async/async.ts +46 -24
  23. package/src/core/constants.ts +1 -0
  24. package/src/core/decorators/README.md +35 -0
  25. package/src/core/decorators/cache/cache.ts +1 -1
  26. package/src/core/decorators/debounce/debounce.ts +20 -9
  27. package/src/core/decorators/idle/README.md +14 -0
  28. package/src/core/decorators/idle/idle.ts +1 -1
  29. package/src/core/decorators/watch/watch.ts +8 -7
  30. package/src/core/dom/README.md +42 -0
  31. package/src/core/dom/dom.ts +37 -23
  32. package/src/core/dom/index.ts +1 -0
  33. package/src/core/dom/lazy-walker.ts +133 -0
  34. package/src/core/event-emitter/event-emitter.ts +8 -8
  35. package/src/core/event-emitter/eventify.ts +73 -0
  36. package/src/core/event-emitter/index.ts +1 -0
  37. package/src/core/helpers/html/apply-styles.ts +1 -1
  38. package/src/core/helpers/html/strip-tags.ts +3 -2
  39. package/src/core/helpers/string/fuzzy-search-index.ts +58 -0
  40. package/src/core/helpers/string/i18n.ts +1 -1
  41. package/src/core/helpers/string/index.ts +3 -2
  42. package/src/core/helpers/utils/append-script.ts +1 -1
  43. package/src/core/helpers/utils/css.ts +1 -1
  44. package/src/core/helpers/utils/selector.ts +1 -1
  45. package/src/core/helpers/utils/utils.ts +3 -3
  46. package/src/core/plugin/plugin-system.ts +14 -8
  47. package/src/core/request/ajax.ts +3 -3
  48. package/src/core/selection/select.ts +10 -10
  49. package/src/core/selection/style/api/toggle/toggle-css.ts +5 -2
  50. package/src/core/selection/style/api/wrap-unwrapped-text.ts +1 -1
  51. package/src/core/selection/style/apply-style.ts +4 -4
  52. package/src/core/storage/engines/local-storage-provider.ts +20 -19
  53. package/src/core/ui/button/button/button.ts +5 -5
  54. package/src/core/ui/element.ts +2 -2
  55. package/src/core/ui/form/inputs/input/input.ts +1 -1
  56. package/src/core/ui/form/inputs/select/select.ts +1 -1
  57. package/src/core/ui/group/list.ts +2 -2
  58. package/src/core/vdom/render/index.ts +12 -8
  59. package/src/core/vdom/v-dom-jodit.ts +1 -1
  60. package/src/core/view/view.ts +1 -1
  61. package/src/index.ts +3 -3
  62. package/src/jodit.ts +72 -55
  63. package/src/langs/README.md +1 -1
  64. package/src/langs/ar.js +2 -1
  65. package/src/langs/cs_cz.js +2 -1
  66. package/src/langs/de.js +2 -1
  67. package/src/langs/es.js +2 -1
  68. package/src/langs/fa.js +2 -1
  69. package/src/langs/fr.js +2 -1
  70. package/src/langs/he.js +2 -1
  71. package/src/langs/hu.js +2 -1
  72. package/src/langs/id.js +2 -1
  73. package/src/langs/index.ts +1 -1
  74. package/src/langs/it.js +2 -1
  75. package/src/langs/ja.js +2 -1
  76. package/src/langs/ko.js +2 -1
  77. package/src/langs/nl.js +2 -1
  78. package/src/langs/pl.js +2 -1
  79. package/src/langs/pt_br.js +2 -1
  80. package/src/langs/ru.js +2 -1
  81. package/src/langs/tr.js +2 -1
  82. package/src/langs/zh_cn.js +2 -1
  83. package/src/langs/zh_tw.js +2 -1
  84. package/src/modules/dialog/dialog.ts +6 -6
  85. package/src/modules/dialog/prompt.ts +1 -1
  86. package/src/modules/file-browser/README.md +2 -2
  87. package/src/modules/file-browser/builders/context-menu.ts +12 -13
  88. package/src/modules/file-browser/fetch/load-tree.ts +1 -1
  89. package/src/modules/file-browser/file-browser.ts +10 -7
  90. package/src/modules/history/README.md +5 -0
  91. package/src/modules/{observer → history}/command.ts +5 -5
  92. package/src/modules/{observer/observer.ts → history/history.ts} +97 -55
  93. package/src/modules/{observer → history}/snapshot.ts +3 -4
  94. package/src/modules/{observer → history}/stack.ts +4 -4
  95. package/src/modules/image-editor/image-editor.ts +8 -8
  96. package/src/modules/image-editor/templates/form.ts +2 -2
  97. package/src/modules/index.ts +3 -3
  98. package/src/modules/status-bar/status-bar.ts +4 -0
  99. package/src/modules/table/table.ts +2 -2
  100. package/src/modules/toolbar/button/button.ts +2 -2
  101. package/src/modules/toolbar/collection/collection.ts +1 -1
  102. package/src/modules/uploader/helpers/process-old-browser-drag.ts +1 -1
  103. package/src/modules/uploader/helpers/send-files.ts +1 -1
  104. package/src/modules/uploader/helpers/send.ts +1 -1
  105. package/src/modules/uploader/uploader.ts +3 -3
  106. package/src/modules/widget/color-picker/color-picker.ts +2 -3
  107. package/src/modules/widget/tabs/tabs.ts +17 -12
  108. package/src/plugins/add-new-line/add-new-line.ts +8 -8
  109. package/src/plugins/class-span/class-span.ts +1 -1
  110. package/src/plugins/clipboard/copy-format.ts +1 -1
  111. package/src/plugins/clipboard/drag-and-drop-element.ts +4 -2
  112. package/src/plugins/clipboard/paste/config.ts +19 -3
  113. package/src/plugins/clipboard/paste/helpers.ts +17 -50
  114. package/src/plugins/clipboard/paste/interface.ts +6 -0
  115. package/src/plugins/clipboard/paste/paste.ts +22 -8
  116. package/src/plugins/clipboard/paste-from-word/config.ts +17 -0
  117. package/src/plugins/clipboard/paste-from-word/paste-from-word.ts +15 -6
  118. package/src/plugins/clipboard/paste-storage/paste-storage.ts +6 -6
  119. package/src/plugins/color/color.ts +2 -2
  120. package/src/plugins/error-messages/error-messages.ts +2 -2
  121. package/src/plugins/fix/clean-html/README.md +26 -0
  122. package/src/plugins/fix/{clean-html.ts → clean-html/clean-html.ts} +59 -142
  123. package/src/plugins/fix/clean-html/config.ts +106 -0
  124. package/src/plugins/fix/index.ts +12 -0
  125. package/src/plugins/fix/wrap-nodes/README.md +27 -0
  126. package/src/plugins/fix/wrap-nodes/config.ts +24 -0
  127. package/src/plugins/fix/{wrap-text-nodes.ts → wrap-nodes/wrap-nodes.ts} +9 -4
  128. package/src/plugins/focus/focus.ts +1 -1
  129. package/src/plugins/format-block/format-block.ts +1 -1
  130. package/src/plugins/fullsize/fullsize.ts +4 -4
  131. package/src/plugins/iframe/iframe.ts +3 -3
  132. package/src/plugins/image/image-properties/image-properties.ts +12 -13
  133. package/src/plugins/indent/indent.ts +1 -1
  134. package/src/plugins/index.ts +2 -2
  135. package/src/plugins/inline-popup/config/items/a.ts +2 -2
  136. package/src/plugins/inline-popup/config/items/cells.ts +11 -11
  137. package/src/plugins/inline-popup/config/items/iframe.ts +1 -1
  138. package/src/plugins/inline-popup/config/items/img.ts +7 -7
  139. package/src/plugins/inline-popup/inline-popup.ts +5 -5
  140. package/src/plugins/keyboard/backspace/backspace.ts +1 -1
  141. package/src/plugins/keyboard/backspace/cases/check-join-neighbors.ts +1 -1
  142. package/src/plugins/keyboard/helpers.ts +1 -1
  143. package/src/plugins/keyboard/hotkeys.ts +1 -1
  144. package/src/plugins/limit/limit.ts +3 -3
  145. package/src/plugins/line-height/line-height.ts +1 -1
  146. package/src/plugins/link/link.ts +8 -8
  147. package/src/plugins/link/template.ts +2 -2
  148. package/src/plugins/media/file.ts +1 -1
  149. package/src/plugins/media/media.ts +1 -1
  150. package/src/plugins/media/video/config.ts +1 -1
  151. package/src/plugins/mobile/config.ts +1 -1
  152. package/src/plugins/mobile/mobile.ts +1 -1
  153. package/src/plugins/ordered-list/config.ts +61 -0
  154. package/src/plugins/ordered-list/ordered-list.ts +3 -153
  155. package/src/plugins/placeholder/placeholder.ts +3 -3
  156. package/src/plugins/print/helpers.ts +14 -7
  157. package/src/plugins/print/index.ts +1 -1
  158. package/src/plugins/print/{preview.less → preview/preview.less} +1 -1
  159. package/src/plugins/print/{preview.ts → preview/preview.ts} +9 -8
  160. package/src/plugins/print/print.ts +19 -10
  161. package/src/plugins/redo-undo/redo-undo.ts +3 -3
  162. package/src/plugins/resizer/resizer.ts +11 -11
  163. package/src/plugins/search/README.md +38 -0
  164. package/src/plugins/search/config.ts +82 -0
  165. package/src/plugins/search/helpers/index.ts +12 -0
  166. package/src/plugins/search/helpers/sentence-finder.ts +103 -0
  167. package/src/plugins/search/helpers/wrap-ranges-texts-in-tmp-span.ts +120 -0
  168. package/src/plugins/search/search.ts +269 -615
  169. package/src/plugins/search/ui/search.less +159 -0
  170. package/src/plugins/search/ui/search.ts +256 -0
  171. package/src/plugins/select/select.ts +1 -1
  172. package/src/plugins/size/config.ts +8 -8
  173. package/src/plugins/size/resize-handler.ts +3 -3
  174. package/src/plugins/size/size.ts +4 -4
  175. package/src/plugins/source/editor/engines/ace.ts +9 -9
  176. package/src/plugins/source/editor/engines/area.ts +3 -3
  177. package/src/plugins/source/source.ts +6 -6
  178. package/src/plugins/spellcheck/README.md +1 -0
  179. package/src/plugins/spellcheck/config.ts +34 -0
  180. package/src/plugins/spellcheck/spellcheck.svg +4 -0
  181. package/src/plugins/spellcheck/spellcheck.ts +48 -0
  182. package/src/plugins/sticky/sticky.ts +3 -3
  183. package/src/plugins/table/resize-cells.ts +11 -11
  184. package/src/plugins/table/select-cells.ts +2 -2
  185. package/src/plugins/tooltip/tooltip.ts +1 -1
  186. package/src/plugins/xpath/xpath.ts +8 -8
  187. package/src/polyfills.ts +5 -4
  188. package/src/styles/icons/README.md +2 -2
  189. package/src/types/async.d.ts +12 -2
  190. package/src/types/core.ts +1 -1
  191. package/src/types/events.d.ts +6 -2
  192. package/src/types/file-browser.d.ts +1 -2
  193. package/{types/types/observer.d.ts → src/types/history.d.ts} +11 -7
  194. package/src/types/index.d.ts +1 -1
  195. package/src/types/jodit.d.ts +12 -4
  196. package/src/types/toolbar.d.ts +5 -5
  197. package/src/types/types.d.ts +11 -4
  198. package/types/config.d.ts +68 -35
  199. package/types/core/async/async.d.ts +11 -4
  200. package/types/core/constants.d.ts +1 -0
  201. package/types/core/dom/dom.d.ts +3 -5
  202. package/types/core/dom/index.d.ts +1 -0
  203. package/types/core/dom/lazy-walker.d.ts +37 -0
  204. package/types/core/event-emitter/eventify.d.ts +39 -0
  205. package/types/core/event-emitter/index.d.ts +1 -0
  206. package/types/core/helpers/string/fuzzy-search-index.d.ts +10 -0
  207. package/types/core/helpers/string/i18n.d.ts +1 -1
  208. package/types/core/helpers/string/index.d.ts +3 -2
  209. package/types/core/helpers/utils/utils.d.ts +1 -1
  210. package/types/core/selection/select.d.ts +1 -1
  211. package/types/core/ui/button/button/button.d.ts +4 -4
  212. package/types/core/view/view.d.ts +1 -1
  213. package/types/jodit.d.ts +19 -6
  214. package/types/modules/{observer → history}/command.d.ts +4 -4
  215. package/types/modules/{observer/observer.d.ts → history/history.d.ts} +17 -9
  216. package/types/modules/{observer → history}/snapshot.d.ts +1 -1
  217. package/types/modules/{observer → history}/stack.d.ts +3 -3
  218. package/types/modules/image-editor/image-editor.d.ts +1 -1
  219. package/types/modules/index.d.ts +3 -3
  220. package/types/modules/toolbar/button/button.d.ts +2 -5
  221. package/types/modules/widget/tabs/tabs.d.ts +1 -1
  222. package/types/plugins/class-span/class-span.d.ts +1 -1
  223. package/types/plugins/clipboard/paste/config.d.ts +8 -0
  224. package/types/plugins/clipboard/paste/helpers.d.ts +2 -2
  225. package/types/plugins/clipboard/paste/interface.d.ts +5 -0
  226. package/types/plugins/clipboard/paste-from-word/config.d.ts +5 -0
  227. package/types/plugins/clipboard/paste-from-word/paste-from-word.d.ts +3 -2
  228. package/types/plugins/fix/clean-html/clean-html.d.ts +70 -0
  229. package/types/plugins/fix/{clean-html.d.ts → clean-html/config.d.ts} +2 -57
  230. package/types/plugins/fix/index.d.ts +10 -0
  231. package/types/plugins/fix/wrap-nodes/config.d.ts +16 -0
  232. package/types/plugins/fix/{wrap-text-nodes.d.ts → wrap-nodes/wrap-nodes.d.ts} +5 -2
  233. package/types/plugins/fullsize/fullsize.d.ts +2 -2
  234. package/types/plugins/index.d.ts +2 -2
  235. package/types/plugins/ordered-list/config.d.ts +6 -0
  236. package/types/plugins/ordered-list/ordered-list.d.ts +1 -1
  237. package/types/plugins/print/helpers.d.ts +2 -2
  238. package/types/plugins/print/index.d.ts +1 -1
  239. package/types/plugins/print/{preview.d.ts → preview/preview.d.ts} +1 -1
  240. package/types/plugins/search/config.d.ts +36 -0
  241. package/types/plugins/search/helpers/index.d.ts +10 -0
  242. package/types/plugins/search/helpers/sentence-finder.d.ts +21 -0
  243. package/types/plugins/search/helpers/wrap-ranges-texts-in-tmp-span.d.ts +14 -0
  244. package/types/plugins/search/search.d.ts +25 -39
  245. package/types/plugins/search/ui/search.d.ts +37 -0
  246. package/types/plugins/spellcheck/config.d.ts +15 -0
  247. package/types/plugins/spellcheck/spellcheck.d.ts +19 -0
  248. package/types/plugins/sticky/sticky.d.ts +2 -2
  249. package/types/types/async.d.ts +12 -2
  250. package/types/types/core.d.ts +1 -1
  251. package/types/types/core.ts +1 -1
  252. package/types/types/events.d.ts +6 -2
  253. package/types/types/file-browser.d.ts +1 -2
  254. package/{src/types/observer.d.ts → types/types/history.d.ts} +11 -7
  255. package/types/types/index.d.ts +1 -1
  256. package/types/types/jodit.d.ts +12 -4
  257. package/types/types/toolbar.d.ts +5 -5
  258. package/types/types/types.d.ts +11 -4
  259. package/src/modules/observer/README.md +0 -0
  260. package/src/plugins/search/search.less +0 -152
@@ -95,7 +95,7 @@ export class Uploader extends ViewComponent implements IUploader {
95
95
  handlerSuccess?: HandlerSuccess,
96
96
  handlerError?: HandlerError
97
97
  ): void {
98
- const onFinally = () => {
98
+ const onFinally = (): void => {
99
99
  form.classList.remove('jodit_drag_hover');
100
100
  };
101
101
 
@@ -105,7 +105,7 @@ export class Uploader extends ViewComponent implements IUploader {
105
105
 
106
106
  const cData = e.clipboardData;
107
107
 
108
- const process = (formdata: FormData) => {
108
+ const process = (formdata: FormData): void => {
109
109
  if (file) {
110
110
  formdata.append('extension', extension);
111
111
  formdata.append('mimetype', file.type);
@@ -182,7 +182,7 @@ export class Uploader extends ViewComponent implements IUploader {
182
182
  handlerSuccess?: HandlerSuccess,
183
183
  handlerError?: HandlerError,
184
184
  onFinally?: () => void
185
- ) {
185
+ ): void {
186
186
  const self = this;
187
187
 
188
188
  self.j.e
@@ -53,7 +53,7 @@ export const ColorPickerWidget = (
53
53
  iconPalette: string = editor.o.textIcons
54
54
  ? `<span>${editor.i18n('palette')}</span>`
55
55
  : Icon.get('palette'),
56
- eachColor = (colors: string[] | IDictionary<string[]>) => {
56
+ eachColor = (colors: string[] | IDictionary<string[]>): string => {
57
57
  const stack: string[] = [];
58
58
 
59
59
  if (isPlainObject(colors)) {
@@ -119,6 +119,7 @@ export const ColorPickerWidget = (
119
119
 
120
120
  editor.e.on(form, 'mousedown touchend', (e: MouseEvent) => {
121
121
  e.stopPropagation();
122
+ e.preventDefault();
122
123
 
123
124
  let target = e.target as HTMLElement;
124
125
 
@@ -148,8 +149,6 @@ export const ColorPickerWidget = (
148
149
  if (callback && isFunction(callback)) {
149
150
  callback(color);
150
151
  }
151
-
152
- e.preventDefault();
153
152
  });
154
153
 
155
154
  editor.e.fire('afterGenerateColorPicker', form, extra, callback, valueHex);
@@ -40,13 +40,13 @@ export interface TabOption {
40
40
  * ```
41
41
  */
42
42
  export const TabsWidget = (
43
- editor: IJodit,
43
+ jodit: IJodit,
44
44
  tabs: TabOption[],
45
45
  state?: { __activeTab: string }
46
46
  ): HTMLDivElement => {
47
- const box: HTMLDivElement = editor.c.div('jodit-tabs'),
48
- tabBox: HTMLDivElement = editor.c.div('jodit-tabs__wrapper'),
49
- buttons: HTMLDivElement = editor.c.div('jodit-tabs__buttons'),
47
+ const box: HTMLDivElement = jodit.c.div('jodit-tabs'),
48
+ tabBox: HTMLDivElement = jodit.c.div('jodit-tabs__wrapper'),
49
+ buttons: HTMLDivElement = jodit.c.div('jodit-tabs__buttons'),
50
50
  nameToTab: IDictionary<{
51
51
  button: IUIButton;
52
52
  tab: HTMLElement;
@@ -54,7 +54,7 @@ export const TabsWidget = (
54
54
  buttonList: IUIButton[] = [];
55
55
 
56
56
  let firstTab: string = '',
57
- tabcount: number = 0;
57
+ tabCount: number = 0;
58
58
 
59
59
  box.appendChild(buttons);
60
60
  box.appendChild(tabBox);
@@ -77,8 +77,13 @@ export const TabsWidget = (
77
77
  };
78
78
 
79
79
  tabs.forEach(({ icon, name, content }) => {
80
- const tab = editor.c.div('jodit-tab'),
81
- button = Button(editor, icon || name, name);
80
+ const tab = jodit.c.div('jodit-tab'),
81
+ button = Button(jodit, icon || name, name);
82
+
83
+ // Stop lose the focus
84
+ jodit.e.on(button.container, 'mousedown', (e: MouseEvent) =>
85
+ e.preventDefault()
86
+ );
82
87
 
83
88
  if (!firstTab) {
84
89
  firstTab = name;
@@ -97,7 +102,7 @@ export const TabsWidget = (
97
102
  content instanceof UIElement ? content.container : content
98
103
  );
99
104
  } else {
100
- tab.appendChild(editor.c.div('jodit-tab_empty'));
105
+ tab.appendChild(jodit.c.div('jodit-tab_empty'));
101
106
  }
102
107
 
103
108
  tabBox.appendChild(tab);
@@ -106,7 +111,7 @@ export const TabsWidget = (
106
111
  setActive(name);
107
112
 
108
113
  if (isFunction(content)) {
109
- content.call(editor);
114
+ content.call(jodit);
110
115
  }
111
116
 
112
117
  if (state) {
@@ -121,15 +126,15 @@ export const TabsWidget = (
121
126
  tab
122
127
  };
123
128
 
124
- tabcount += 1;
129
+ tabCount += 1;
125
130
  });
126
131
 
127
- if (!tabcount) {
132
+ if (!tabCount) {
128
133
  return box;
129
134
  }
130
135
 
131
136
  $$('a', buttons).forEach(a => {
132
- a.style.width = (100 / tabcount).toFixed(10) + '%';
137
+ a.style.width = (100 / tabCount).toFixed(10) + '%';
133
138
  });
134
139
 
135
140
  const tab =
@@ -91,7 +91,7 @@ export class addNewLine extends Plugin {
91
91
  private lineInFocus: boolean = false;
92
92
  private isShown: boolean = false;
93
93
 
94
- private show() {
94
+ private show(): void {
95
95
  if (this.isShown || this.j.o.readonly || this.j.isLocked) {
96
96
  return;
97
97
  }
@@ -104,7 +104,7 @@ export class addNewLine extends Plugin {
104
104
  this.line.style.width = this.j.editor.clientWidth + 'px';
105
105
  }
106
106
 
107
- private hideForce = () => {
107
+ private hideForce = (): void => {
108
108
  if (!this.isShown) {
109
109
  return;
110
110
  }
@@ -115,7 +115,7 @@ export class addNewLine extends Plugin {
115
115
  Dom.safeRemove(this.line);
116
116
  };
117
117
 
118
- private hide = () => {
118
+ private hide = (): void => {
119
119
  if (!this.isShown || this.lineInFocus) {
120
120
  return;
121
121
  }
@@ -157,7 +157,7 @@ export class addNewLine extends Plugin {
157
157
  this.addEventListeners();
158
158
  }
159
159
 
160
- private addEventListeners() {
160
+ private addEventListeners(): void {
161
161
  const editor = this.j;
162
162
 
163
163
  editor.e
@@ -181,7 +181,7 @@ export class addNewLine extends Plugin {
181
181
  );
182
182
  }
183
183
 
184
- private onClickLine = (e: MouseEvent) => {
184
+ private onClickLine = (e: MouseEvent): void => {
185
185
  const editor = this.j;
186
186
  const p = editor.createInside.element(editor.o.enter);
187
187
 
@@ -200,7 +200,7 @@ export class addNewLine extends Plugin {
200
200
  e.preventDefault();
201
201
  };
202
202
 
203
- private onDblClickEditor = (e: MouseEvent) => {
203
+ private onDblClickEditor = (e: MouseEvent): void => {
204
204
  const editor = this.j;
205
205
 
206
206
  if (
@@ -230,14 +230,14 @@ export class addNewLine extends Plugin {
230
230
  }
231
231
 
232
232
  editor.s.setCursorIn(p);
233
- editor.setEditorValue();
233
+ editor.synchronizeValues();
234
234
 
235
235
  this.hideForce();
236
236
  e.preventDefault();
237
237
  }
238
238
  };
239
239
 
240
- private onMouseMove = (e: MouseEvent) => {
240
+ private onMouseMove = (e: MouseEvent): void => {
241
241
  const editor = this.j;
242
242
 
243
243
  let currentElement: HTMLElement | null = editor.ed.elementFromPoint(
@@ -93,7 +93,7 @@ Config.prototype.controls.classSpan = {
93
93
  * Applying some className to selected text.
94
94
  * @example
95
95
  * ```js
96
- * const editor = new Jodit('#editor', {
96
+ * const editor = Jodit.make('#editor', {
97
97
  * controls: {
98
98
  * classSpan: {
99
99
  * list: {
@@ -114,7 +114,7 @@ Config.prototype.controls.copyformat = {
114
114
 
115
115
  const format = getStyles(editor, box, defaultStyles);
116
116
 
117
- const onMouseUp = () => {
117
+ const onMouseUp = (): void => {
118
118
  editor.buffer.delete(pluginKey);
119
119
 
120
120
  const currentNode = editor.s.current();
@@ -74,8 +74,10 @@ export class DragAndDropElement extends Plugin {
74
74
  return;
75
75
  }
76
76
 
77
- const matched = (node: Nullable<Node>) =>
78
- node && this.dragList.includes(node.nodeName.toLowerCase());
77
+ const matched = (node: Nullable<Node>): boolean =>
78
+ Boolean(
79
+ node && this.dragList.includes(node.nodeName.toLowerCase())
80
+ );
79
81
 
80
82
  let lastTarget: Nullable<HTMLElement> =
81
83
  (Dom.furthest(target, matched, this.j.editor) as HTMLElement) ||
@@ -8,13 +8,18 @@
8
8
  * @module plugins/clipboard/paste
9
9
  */
10
10
 
11
- import { INSERT_AS_HTML, TEXT_PLAIN } from 'jodit/core/constants';
11
+ import type { IControlType, IJodit, IUIOption } from 'jodit/types';
12
+ import type { InsertMode } from 'jodit/plugins/clipboard/paste/interface';
13
+ import {
14
+ INSERT_AS_HTML,
15
+ INSERT_AS_TEXT,
16
+ INSERT_ONLY_TEXT,
17
+ TEXT_PLAIN
18
+ } from 'jodit/core/constants';
12
19
  import { Config } from 'jodit/config';
13
- import type { IControlType, IJodit } from 'jodit/types';
14
20
  import { pluginKey as clipboardPluginKey } from '../clipboard';
15
21
  import { pasteInsertHtml } from './helpers';
16
22
  import { Alert } from 'jodit/modules/dialog/alert';
17
- import type { InsertMode } from 'jodit/plugins/clipboard/paste/interface';
18
23
 
19
24
  declare module 'jodit/config' {
20
25
  interface Config {
@@ -49,12 +54,23 @@ declare module 'jodit/config' {
49
54
  * Draggable elements
50
55
  */
51
56
  draggableTags: string | string[];
57
+
58
+ /**
59
+ * Options when inserting HTML string
60
+ */
61
+ pasteHTMLActionList: IUIOption[];
52
62
  }
53
63
  }
54
64
 
55
65
  Config.prototype.askBeforePasteHTML = true;
56
66
  Config.prototype.processPasteHTML = true;
57
67
 
68
+ Config.prototype.pasteHTMLActionList = [
69
+ { value: INSERT_AS_HTML, text: 'Keep' },
70
+ { value: INSERT_AS_TEXT, text: 'Insert as Text' },
71
+ { value: INSERT_ONLY_TEXT, text: 'Insert only Text' }
72
+ ];
73
+
58
74
  Config.prototype.memorizeChoiceWhenPasteFragment = false;
59
75
 
60
76
  Config.prototype.nl2brInPlainText = true;
@@ -8,7 +8,7 @@
8
8
  * @module plugins/clipboard/paste
9
9
  */
10
10
 
11
- import type { IJodit, Nullable } from 'jodit/types';
11
+ import type { IJodit, IUIOption, Nullable } from 'jodit/types';
12
12
  import type {
13
13
  PasteEvent,
14
14
  InsertMode
@@ -21,12 +21,7 @@ import {
21
21
  } from 'jodit/core/helpers/checker';
22
22
 
23
23
  import { Dom } from 'jodit/core/dom';
24
- import {
25
- INSERT_AS_HTML,
26
- INSERT_AS_TEXT,
27
- INSERT_ONLY_TEXT,
28
- TEXT_PLAIN
29
- } from 'jodit/core/constants';
24
+ import { TEXT_PLAIN } from 'jodit/core/constants';
30
25
 
31
26
  import { Confirm, Dialog } from 'jodit/modules';
32
27
  import { Button } from 'jodit/core/ui';
@@ -136,8 +131,7 @@ export function askInsertTypeDialog(
136
131
  msg: string,
137
132
  title: string,
138
133
  callback: (yes: InsertMode) => void,
139
- clearButton: string = 'Clean',
140
- insertText: string = 'Insert only Text'
134
+ buttonList: IUIOption[]
141
135
  ): Dialog | void {
142
136
  if (
143
137
  jodit.e.fire(
@@ -145,8 +139,7 @@ export function askInsertTypeDialog(
145
139
  msg,
146
140
  title,
147
141
  callback,
148
- clearButton,
149
- insertText
142
+ buttonList
150
143
  ) === false
151
144
  ) {
152
145
  return;
@@ -163,50 +156,25 @@ export function askInsertTypeDialog(
163
156
 
164
157
  markOwner(jodit, dialog.container);
165
158
 
166
- const keep = Button(jodit, {
167
- text: 'Keep',
168
- name: 'keep',
169
- variant: 'primary',
170
- tabIndex: 0
171
- });
172
-
173
- const clear = Button(jodit, {
174
- text: clearButton,
175
- tabIndex: 0
176
- });
177
-
178
- const clear2 = Button(jodit, {
179
- text: insertText,
180
- tabIndex: 0
181
- });
159
+ const buttons = buttonList.map(({ text, value }) =>
160
+ Button(jodit, {
161
+ text,
162
+ name: text.toLowerCase(),
163
+ tabIndex: 0
164
+ }).onAction(() => callback(value as InsertMode))
165
+ );
182
166
 
183
167
  const cancel = Button(jodit, {
184
168
  text: 'Cancel',
185
169
  tabIndex: 0
186
170
  });
187
171
 
188
- keep.onAction(() => {
189
- dialog.close();
190
- callback(INSERT_AS_HTML);
191
- });
192
-
193
- clear.onAction(() => {
194
- dialog.close();
195
- callback(INSERT_AS_TEXT);
196
- });
197
-
198
- clear2.onAction(() => {
199
- dialog.close();
200
- callback(INSERT_ONLY_TEXT);
201
- });
202
-
203
- cancel.onAction(() => {
204
- dialog.close();
205
- });
206
-
207
- dialog.setFooter([keep, clear, insertText ? clear2 : '', cancel]);
172
+ dialog.setFooter(
173
+ [...buttons, cancel].map(btn => btn.onAction(() => dialog.close()))
174
+ );
208
175
 
209
- keep.focus();
176
+ buttons[0].focus();
177
+ buttons[0].state.variant = 'primary';
210
178
 
211
179
  jodit.e.fire(
212
180
  'afterOpenPasteDialog',
@@ -214,8 +182,7 @@ export function askInsertTypeDialog(
214
182
  msg,
215
183
  title,
216
184
  callback,
217
- clearButton,
218
- insertText
185
+ buttonList
219
186
  );
220
187
 
221
188
  return dialog;
@@ -27,3 +27,9 @@ export type PastedValue = {
27
27
  html: string | Node;
28
28
  action?: InsertMode;
29
29
  };
30
+
31
+ export interface PastedData {
32
+ html?: string;
33
+ plain?: string;
34
+ rtf?: string;
35
+ }
@@ -11,7 +11,12 @@
11
11
  */
12
12
 
13
13
  import type { IJodit } from 'jodit/types';
14
- import type { InsertMode, PastedValue, PasteEvent } from './interface';
14
+ import type {
15
+ InsertMode,
16
+ PastedData,
17
+ PastedValue,
18
+ PasteEvent
19
+ } from './interface';
15
20
  import { Plugin } from 'jodit/core/plugin';
16
21
  import {
17
22
  askInsertTypeDialog,
@@ -27,7 +32,8 @@ import {
27
32
  INSERT_CLEAR_HTML,
28
33
  INSERT_ONLY_TEXT,
29
34
  TEXT_HTML,
30
- TEXT_PLAIN
35
+ TEXT_PLAIN,
36
+ TEXT_RTF
31
37
  } from 'jodit/core/constants';
32
38
 
33
39
  import {
@@ -93,13 +99,21 @@ export class paste extends Plugin {
93
99
  }
94
100
 
95
101
  const dt = getDataTransfer(e),
96
- texts = [dt?.getData(TEXT_HTML), dt?.getData(TEXT_PLAIN)];
102
+ texts: PastedData = {
103
+ html: dt?.getData(TEXT_HTML),
104
+ plain: dt?.getData(TEXT_PLAIN),
105
+ rtf: dt?.getData(TEXT_RTF)
106
+ };
107
+
108
+ let key: keyof PastedData;
109
+
110
+ for (key in texts) {
111
+ const value = texts[key];
97
112
 
98
- for (const text of texts) {
99
113
  if (
100
- isHTML(text) &&
101
- (this.j.e.fire('processHTML', e, text) ||
102
- this.processHTML(e, text))
114
+ isHTML(value) &&
115
+ (this.j.e.fire('processHTML', e, value, texts) ||
116
+ this.processHTML(e, value))
103
117
  ) {
104
118
  return false;
105
119
  }
@@ -161,7 +175,7 @@ export class paste extends Plugin {
161
175
  insertType => {
162
176
  this.insertByType(e, html, insertType);
163
177
  },
164
- 'Insert as Text'
178
+ this.j.o.pasteHTMLActionList
165
179
  );
166
180
 
167
181
  return true;
@@ -10,6 +10,12 @@
10
10
 
11
11
  import type { InsertMode } from 'jodit/plugins/clipboard/paste/interface';
12
12
  import { Config } from 'jodit/config';
13
+ import type { IUIOption } from 'jodit/types';
14
+ import {
15
+ INSERT_AS_HTML,
16
+ INSERT_AS_TEXT,
17
+ INSERT_ONLY_TEXT
18
+ } from 'jodit/core/constants';
13
19
 
14
20
  declare module 'jodit/config' {
15
21
  interface Config {
@@ -33,9 +39,20 @@ declare module 'jodit/config' {
33
39
  * ```
34
40
  */
35
41
  defaultActionOnPasteFromWord: InsertMode | null;
42
+
43
+ /**
44
+ * Options when inserting data from Word
45
+ */
46
+ pasteFromWordActionList: IUIOption[];
36
47
  }
37
48
  }
38
49
 
39
50
  Config.prototype.askBeforePasteFromWord = true;
40
51
  Config.prototype.processPasteFromWord = true;
41
52
  Config.prototype.defaultActionOnPasteFromWord = null;
53
+
54
+ Config.prototype.pasteFromWordActionList = [
55
+ { value: INSERT_AS_HTML, text: 'Keep' },
56
+ { value: INSERT_AS_TEXT, text: 'Clean' },
57
+ { value: INSERT_ONLY_TEXT, text: 'Insert only Text' }
58
+ ];
@@ -33,6 +33,7 @@ import {
33
33
  askInsertTypeDialog,
34
34
  pasteInsertHtml
35
35
  } from 'jodit/plugins/clipboard/paste/helpers';
36
+ import type { PastedData } from 'jodit/plugins/clipboard/paste/interface';
36
37
  import { watch } from 'jodit/src/core/decorators';
37
38
 
38
39
  import './config';
@@ -45,13 +46,18 @@ export class PasteFromWord extends Plugin {
45
46
  * Try if text is Word's document fragment and try process this
46
47
  */
47
48
  @watch(':processHTML')
48
- protected processWordHTML(e: PasteEvent, text: string): boolean {
49
+ protected processWordHTML(
50
+ e: PasteEvent,
51
+ text: string,
52
+ texts: PastedData
53
+ ): boolean {
49
54
  const { j } = this,
50
55
  {
51
56
  processPasteFromWord,
52
57
  askBeforePasteFromWord,
53
58
  defaultActionOnPasteFromWord,
54
- defaultActionOnPaste
59
+ defaultActionOnPaste,
60
+ pasteFromWordActionList
55
61
  } = j.o;
56
62
 
57
63
  if (processPasteFromWord && isHtmlFromWord(text)) {
@@ -62,14 +68,16 @@ export class PasteFromWord extends Plugin {
62
68
  'Do you want to keep the format or clean it up?',
63
69
  'Word Paste Detected',
64
70
  insertType => {
65
- this.insertFromWordByType(e, text, insertType);
66
- }
71
+ this.insertFromWordByType(e, text, insertType, texts);
72
+ },
73
+ pasteFromWordActionList
67
74
  );
68
75
  } else {
69
76
  this.insertFromWordByType(
70
77
  e,
71
78
  text,
72
- defaultActionOnPasteFromWord || defaultActionOnPaste
79
+ defaultActionOnPasteFromWord || defaultActionOnPaste,
80
+ texts
73
81
  );
74
82
  }
75
83
 
@@ -85,7 +93,8 @@ export class PasteFromWord extends Plugin {
85
93
  protected insertFromWordByType(
86
94
  e: PasteEvent,
87
95
  html: string,
88
- insertType: InsertMode
96
+ insertType: InsertMode,
97
+ texts: PastedData
89
98
  ): void {
90
99
  switch (insertType) {
91
100
  case INSERT_AS_HTML: {
@@ -36,7 +36,7 @@ export class pasteStorage extends Plugin {
36
36
 
37
37
  private dialog: Dialog | null = null;
38
38
 
39
- private paste = () => {
39
+ private paste = (): void => {
40
40
  this.j.s.focus();
41
41
  this.j.s.insertHTML(this.list[this.currentIndex]);
42
42
 
@@ -48,12 +48,12 @@ export class pasteStorage extends Plugin {
48
48
  }
49
49
 
50
50
  this.dialog && this.dialog.close();
51
- this.j.setEditorValue();
51
+ this.j.synchronizeValues();
52
52
 
53
53
  this.j.e.fire('afterPaste');
54
54
  };
55
55
 
56
- private onKeyDown = (e: KeyboardEvent) => {
56
+ private onKeyDown = (e: KeyboardEvent): void => {
57
57
  let index: number = this.currentIndex;
58
58
  if ([KEY_UP, KEY_DOWN, KEY_ENTER].indexOf(e.key) === -1) {
59
59
  return;
@@ -87,7 +87,7 @@ export class pasteStorage extends Plugin {
87
87
  e.preventDefault();
88
88
  };
89
89
 
90
- private selectIndex = (index: number) => {
90
+ private selectIndex = (index: number): void => {
91
91
  if (this.listBox) {
92
92
  toArray(
93
93
  this.listBox.childNodes as NodeListOf<HTMLAnchorElement>
@@ -104,7 +104,7 @@ export class pasteStorage extends Plugin {
104
104
  this.currentIndex = index;
105
105
  };
106
106
 
107
- private showDialog = () => {
107
+ private showDialog = (): void => {
108
108
  if (this.list.length < 2) {
109
109
  return;
110
110
  }
@@ -140,7 +140,7 @@ export class pasteStorage extends Plugin {
140
140
  }, 100);
141
141
  };
142
142
 
143
- private createDialog() {
143
+ private createDialog(): void {
144
144
  this.dialog = new Dialog({
145
145
  language: this.j.o.language
146
146
  });
@@ -19,7 +19,7 @@ Config.prototype.controls.brush = {
19
19
  const color = dataBind(button, 'color');
20
20
  const editor = button.j as IJodit;
21
21
 
22
- const update = (key: string, value: string) => {
22
+ const update = (key: string, value: string): void => {
23
23
  if (value && value !== css(editor.editor, key).toString()) {
24
24
  button.state.icon.fill = value;
25
25
  return;
@@ -209,7 +209,7 @@ export function color(editor: IJodit): void {
209
209
  break;
210
210
  }
211
211
 
212
- editor.setEditorValue();
212
+ editor.synchronizeValues();
213
213
  return false;
214
214
  };
215
215
 
@@ -44,7 +44,7 @@ export function errorMessages(editor: IJodit): void {
44
44
  if (editor.o.showMessageErrors) {
45
45
  const activeClass = editor.getFullElName(ELM_NAME, 'active', true),
46
46
  messagesBox = editor.c.div(editor.getFullElName(ELM_NAME)),
47
- calcOffsets = () => {
47
+ calcOffsets = (): void => {
48
48
  let height = 5;
49
49
 
50
50
  toArray(
@@ -65,7 +65,7 @@ export function errorMessages(editor: IJodit): void {
65
65
  * options.showMessageErrorTime = 2000
66
66
  * @example
67
67
  * ```javascript
68
- * const editor = new Jodit('#editors');
68
+ * const editor = Jodit.make('#editors');
69
69
  * editor.e.fire('errorMessage', 'Error 123. File has not been upload');
70
70
  * editor.e.fire('errorMessage', 'You can upload file', 'info', 4000);
71
71
  * editor.e.fire('errorMessage', 'File was uploaded', 'success', 4000);
@@ -0,0 +1,26 @@
1
+ The plugin allows you to ensure that the document does not contain unwanted tags, xxs scripts and the like.
2
+
3
+ For example, you can explicitly specify which tags or attributes are allowed and which are not.:
4
+
5
+ ```javascript
6
+ Jodit.make('#editor', {
7
+ cleanHTML: {
8
+ allowTags: {
9
+ p: true,
10
+ a: {
11
+ href: true
12
+ },
13
+ table: true,
14
+ tbody: true,
15
+ tr: true,
16
+ td: true,
17
+ th: false,
18
+ img: {
19
+ src: '1.png'
20
+ }
21
+ }
22
+ }
23
+ });
24
+ ```
25
+
26
+ Plugin settings are under the namespace [[Config.cleanHTML]]