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
@@ -5,7 +5,9 @@
5
5
  */
6
6
 
7
7
  /**
8
- * @module plugins/fix
8
+ * [[include:src/plugins/fix/clean-html/README.md]]
9
+ * @packageDocumentation
10
+ * @module plugins/fix/clean-html
9
11
  */
10
12
 
11
13
  import type {
@@ -15,7 +17,6 @@ import type {
15
17
  Nullable,
16
18
  IPlugin
17
19
  } from 'jodit/types';
18
- import { Config } from 'jodit/config';
19
20
  import {
20
21
  INVISIBLE_SPACE_REG_EXP as INV_REG,
21
22
  IS_INLINE,
@@ -24,102 +25,11 @@ import {
24
25
  import { Dom } from 'jodit/modules';
25
26
  import { attr, isString, keys, safeHTML, trim } from 'jodit/core/helpers';
26
27
  import { Plugin } from 'jodit/core/plugin';
27
- import { watch, autobind, debounce } from 'jodit/core/decorators';
28
+ import { watch, autobind, debounce, hook } from 'jodit/core/decorators';
28
29
  import { findNotEmptySibling } from 'jodit/plugins/keyboard/helpers';
30
+ import { LazyWalker } from 'jodit/core/dom/lazy-walker';
29
31
 
30
- declare module 'jodit/config' {
31
- interface Config {
32
- cleanHTML: {
33
- timeout: number;
34
-
35
- /**
36
- * Replace   to plain space
37
- */
38
- replaceNBSP: boolean;
39
- fillEmptyParagraph: boolean;
40
- removeEmptyElements: boolean;
41
- replaceOldTags: IDictionary<HTMLTagNames> | false;
42
-
43
- /**
44
- * Remove onError attributes
45
- */
46
- removeOnError: boolean;
47
-
48
- /**
49
- * Safe href="javascript:" links
50
- */
51
- safeJavaScriptLink: boolean;
52
-
53
- /**
54
- * The allowTags option defines which elements will remain in the
55
- * edited text when the editor saves. You can use this limit the returned HTML.
56
- * @example
57
- * ```javascript
58
- * var jodit = new Jodit('#editor', {
59
- * cleanHTML: {
60
- * cleanOnPaste: false
61
- * }
62
- * });
63
- * ```
64
- * @example
65
- * ```javascript
66
- * var editor = Jodit('#editor', {
67
- * cleanHTML: {
68
- * allowTags: 'p,a[href],table,tr,td, img[src=1.png]' // allow only <p>,<a>,<table>,<tr>,<td>,<img> tags and
69
- * for <a> allow only `href` attribute and <img> allow only `src` attribute == '1.png'
70
- * }
71
- * });
72
- * editor.value = 'Sorry! <strong>Goodby</strong>\
73
- * <span>mr.</span> <a style="color:red" href="http://xdsoft.net">Freeman</a>';
74
- * console.log(editor.value); //Sorry! <a href="http://xdsoft.net">Freeman</a>
75
- * ```
76
- *
77
- * @example
78
- * ```javascript
79
- * var editor = Jodit('#editor', {
80
- * cleanHTML: {
81
- * allowTags: {
82
- * p: true,
83
- * a: {
84
- * href: true
85
- * },
86
- * table: true,
87
- * tr: true,
88
- * td: true,
89
- * img: {
90
- * src: '1.png'
91
- * }
92
- * }
93
- * }
94
- * });
95
- * ```
96
- */
97
- allowTags: false | string | IDictionary<string>;
98
- denyTags: false | string | IDictionary<string>;
99
- };
100
- }
101
- }
102
-
103
- Config.prototype.cleanHTML = {
104
- timeout: 300,
105
- removeEmptyElements: true,
106
- fillEmptyParagraph: true,
107
- replaceNBSP: true,
108
- replaceOldTags: {
109
- i: 'em',
110
- b: 'strong'
111
- },
112
- allowTags: false,
113
- denyTags: false,
114
-
115
- removeOnError: true,
116
- safeJavaScriptLink: true
117
- };
118
-
119
- Config.prototype.controls.eraser = {
120
- command: 'removeFormat',
121
- tooltip: 'Clear Formatting'
122
- };
32
+ import './config';
123
33
 
124
34
  /**
125
35
  * Clean HTML after removeFormat and insertHorizontalRule command
@@ -203,46 +113,42 @@ export class cleanHtml extends Plugin {
203
113
  }
204
114
  }
205
115
 
206
- let node: Node | null = null;
207
-
208
- if (editor.editor.firstChild) {
209
- node = editor.editor.firstChild as Element;
210
- }
211
-
212
- const remove: Node[] = [];
213
- const work = this.visitNode(node, current, remove);
214
-
215
- remove.forEach(Dom.safeRemove);
216
-
217
- if (remove.length || work) {
218
- editor.events && editor.e.fire('synchro');
219
- }
116
+ this.walker.setWork(editor.editor);
117
+ this.currentSelectionNode = current;
220
118
  }
221
119
 
222
- private allowEdit(): boolean {
223
- return !(
224
- this.j.isInDestruct ||
225
- !this.j.isEditorMode() ||
226
- this.j.getReadOnly()
227
- );
120
+ private currentSelectionNode: Nullable<Node> = null;
121
+
122
+ private walker: LazyWalker = new LazyWalker(this.j.async, {
123
+ timeout: this.j.o.cleanHTML.timeout
124
+ });
125
+
126
+ @hook('ready')
127
+ protected startWalker(): void {
128
+ this.walker
129
+ .on('visit', this.visitNode)
130
+ .on('end', (affected: boolean): void => {
131
+ this.j.e.fire(
132
+ affected
133
+ ? 'internalChange finishedCleanHTMLWorker'
134
+ : 'finishedCleanHTMLWorker'
135
+ );
136
+ });
228
137
  }
229
138
 
230
- private visitNode = (
231
- nodeElm: Nullable<Element | Node>,
232
- current: Nullable<Node>,
233
- remove: Node[]
234
- ): boolean => {
235
- let work = false;
139
+ @autobind
140
+ private visitNode(nodeElm: Node): boolean {
141
+ let hasChanges = false;
236
142
 
237
- if (!nodeElm) {
238
- return work;
143
+ const newNodeElm = this.replaceIfMatched(nodeElm);
144
+ if (nodeElm !== newNodeElm) {
145
+ nodeElm = newNodeElm;
146
+ hasChanges = true;
239
147
  }
240
148
 
241
- nodeElm = this.replaceIfMatched(nodeElm);
242
-
243
- if (this.isRemovableNode(nodeElm, current)) {
244
- remove.push(nodeElm);
245
- return this.visitNode(nodeElm.nextSibling, current, remove);
149
+ if (this.isRemovableNode(nodeElm, this.currentSelectionNode)) {
150
+ Dom.safeRemove(nodeElm);
151
+ return true;
246
152
  }
247
153
 
248
154
  if (
@@ -251,14 +157,17 @@ export class cleanHtml extends Plugin {
251
157
  Dom.isEmpty(nodeElm, /^(img|svg|canvas|input|textarea|form|br)$/)
252
158
  ) {
253
159
  const br = this.j.createInside.element('br');
254
-
255
160
  nodeElm.appendChild(br);
256
- work = true;
161
+ hasChanges = true;
257
162
  }
258
163
 
259
164
  const allow = this.allowTagsHash;
260
165
 
261
- if (allow && allow[nodeElm.nodeName] !== true) {
166
+ if (
167
+ allow &&
168
+ Dom.isElement(nodeElm) &&
169
+ allow[nodeElm.nodeName] !== true
170
+ ) {
262
171
  const attrs: NamedNodeMap = (nodeElm as Element).attributes;
263
172
 
264
173
  if (attrs && attrs.length) {
@@ -273,7 +182,7 @@ export class cleanHtml extends Plugin {
273
182
  }
274
183
 
275
184
  if (removeAttrs.length) {
276
- work = true;
185
+ hasChanges = true;
277
186
  }
278
187
 
279
188
  removeAttrs.forEach(attr => {
@@ -282,26 +191,32 @@ export class cleanHtml extends Plugin {
282
191
  }
283
192
  }
284
193
 
285
- work = this.visitNode(nodeElm.firstChild, current, remove) || work;
286
- work = this.visitNode(nodeElm.nextSibling, current, remove) || work;
194
+ return hasChanges;
195
+ }
287
196
 
288
- return work;
289
- };
197
+ private allowEdit(): boolean {
198
+ return !(
199
+ this.j.isInDestruct ||
200
+ !this.j.isEditorMode() ||
201
+ this.j.getReadOnly()
202
+ );
203
+ }
290
204
 
291
205
  private static getHash(
292
206
  tags: false | string | IDictionary<string>
293
207
  ): IDictionary | false {
294
208
  const attributesReg = /([^[]*)\[([^\]]+)]/;
295
- const seperator = /[\s]*,[\s]*/,
209
+ const separator = /[\s]*,[\s]*/,
296
210
  attrReg = /^(.*)[\s]*=[\s]*(.*)$/;
211
+
297
212
  const tagsHash: IDictionary = {};
298
213
 
299
214
  if (isString(tags)) {
300
- tags.split(seperator).map((elm: string) => {
215
+ tags.split(separator).map((elm: string) => {
301
216
  elm = trim(elm);
302
217
  const attr: RegExpExecArray | null = attributesReg.exec(elm),
303
218
  allowAttributes: IDictionary<string | boolean> = {},
304
- attributeMap = (attrName: string) => {
219
+ attributeMap = (attrName: string): void => {
305
220
  attrName = trim(attrName);
306
221
 
307
222
  const val: string[] | null = attrReg.exec(attrName);
@@ -314,7 +229,8 @@ export class cleanHtml extends Plugin {
314
229
  };
315
230
 
316
231
  if (attr) {
317
- const attr2: string[] = attr[2].split(seperator);
232
+ const attr2: string[] = attr[2].split(separator);
233
+
318
234
  if (attr[1]) {
319
235
  attr2.forEach(attributeMap);
320
236
  tagsHash[attr[1].toUpperCase()] = allowAttributes;
@@ -349,7 +265,7 @@ export class cleanHtml extends Plugin {
349
265
  /**
350
266
  * Remove invisible chars if node has another chars
351
267
  */
352
- private onKeyUpCleanUp = () => {
268
+ private onKeyUpCleanUp = (): void => {
353
269
  const editor = this.j;
354
270
 
355
271
  if (!this.allowEdit()) {
@@ -589,5 +505,6 @@ export class cleanHtml extends Plugin {
589
505
  /** @override */
590
506
  protected override beforeDestruct(): void {
591
507
  this.j.e.off('.cleanHtml');
508
+ this.walker.destruct();
592
509
  }
593
510
  }
@@ -0,0 +1,106 @@
1
+ /*!
2
+ * Jodit Editor (https://xdsoft.net/jodit/)
3
+ * Released under MIT see LICENSE.txt in the project root for license information.
4
+ * Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ /**
8
+ * @module plugins/fix/clean-html
9
+ */
10
+
11
+ import type { HTMLTagNames, IDictionary } from 'jodit/types';
12
+ import { Config } from 'jodit/config';
13
+
14
+ declare module 'jodit/config' {
15
+ interface Config {
16
+ cleanHTML: {
17
+ timeout: number;
18
+
19
+ /**
20
+ * Replace &amp;nbsp; to plain space
21
+ */
22
+ replaceNBSP: boolean;
23
+ fillEmptyParagraph: boolean;
24
+ removeEmptyElements: boolean;
25
+ replaceOldTags: IDictionary<HTMLTagNames> | false;
26
+
27
+ /**
28
+ * Remove onError attributes
29
+ */
30
+ removeOnError: boolean;
31
+
32
+ /**
33
+ * Safe href="javascript:" links
34
+ */
35
+ safeJavaScriptLink: boolean;
36
+
37
+ /**
38
+ * The allowTags option defines which elements will remain in the
39
+ * edited text when the editor saves. You can use this limit the returned HTML.
40
+ * @example
41
+ * ```javascript
42
+ * var jodit = new Jodit('#editor', {
43
+ * cleanHTML: {
44
+ * cleanOnPaste: false
45
+ * }
46
+ * });
47
+ * ```
48
+ * @example
49
+ * ```javascript
50
+ * var editor = Jodit('#editor', {
51
+ * cleanHTML: {
52
+ * allowTags: 'p,a[href],table,tr,td, img[src=1.png]' // allow only <p>,<a>,<table>,<tr>,<td>,<img> tags and
53
+ * for <a> allow only `href` attribute and <img> allow only `src` attribute == '1.png'
54
+ * }
55
+ * });
56
+ * editor.value = 'Sorry! <strong>Goodby</strong>\
57
+ * <span>mr.</span> <a style="color:red" href="http://xdsoft.net">Freeman</a>';
58
+ * console.log(editor.value); //Sorry! <a href="http://xdsoft.net">Freeman</a>
59
+ * ```
60
+ *
61
+ * @example
62
+ * ```javascript
63
+ * var editor = Jodit('#editor', {
64
+ * cleanHTML: {
65
+ * allowTags: {
66
+ * p: true,
67
+ * a: {
68
+ * href: true
69
+ * },
70
+ * table: true,
71
+ * tr: true,
72
+ * td: true,
73
+ * img: {
74
+ * src: '1.png'
75
+ * }
76
+ * }
77
+ * }
78
+ * });
79
+ * ```
80
+ */
81
+ allowTags: false | string | IDictionary<string>;
82
+ denyTags: false | string | IDictionary<string>;
83
+ };
84
+ }
85
+ }
86
+
87
+ Config.prototype.cleanHTML = {
88
+ timeout: 300,
89
+ removeEmptyElements: true,
90
+ fillEmptyParagraph: true,
91
+ replaceNBSP: true,
92
+ replaceOldTags: {
93
+ i: 'em',
94
+ b: 'strong'
95
+ },
96
+ allowTags: false,
97
+ denyTags: false,
98
+
99
+ removeOnError: true,
100
+ safeJavaScriptLink: true
101
+ };
102
+
103
+ Config.prototype.controls.eraser = {
104
+ command: 'removeFormat',
105
+ tooltip: 'Clear Formatting'
106
+ };
@@ -0,0 +1,12 @@
1
+ /*!
2
+ * Jodit Editor (https://xdsoft.net/jodit/)
3
+ * Released under MIT see LICENSE.txt in the project root for license information.
4
+ * Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ /**
8
+ * @module plugins/fix
9
+ */
10
+
11
+ export * from './clean-html/clean-html';
12
+ export * from './wrap-nodes/wrap-nodes';
@@ -0,0 +1,27 @@
1
+ A plugin that ensures that there are no elements in the document that are not surrounded by a block element.
2
+
3
+ For example, the plugin will result in HTML:
4
+
5
+ ```html
6
+ test <img src="./test.png" />
7
+ ```
8
+
9
+ Depending on the [[Config.enter]] setting to this view:
10
+
11
+ ```html
12
+ <p>test <img src="./test.png" /></p>
13
+ ```
14
+
15
+ You may encounter a situation where your custom tags will be treated as inline by the plugin.
16
+ And he will also surround them in a block element.
17
+ To prevent this from happening, you can explicitly set in the settings which tags to avoid.
18
+
19
+ ```js
20
+ Jodit.make('#editor', {
21
+ wrapNodes: {
22
+ exclude: ['hr', 'style', 'my-component']
23
+ }
24
+ });
25
+ ```
26
+
27
+ Plugin settings are under the namespace [[Config.wrapNodes]]
@@ -0,0 +1,24 @@
1
+ /*!
2
+ * Jodit Editor (https://xdsoft.net/jodit/)
3
+ * Released under MIT see LICENSE.txt in the project root for license information.
4
+ * Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ /**
8
+ * @module plugins/fix/wrap-nodes
9
+ */
10
+
11
+ import type { HTMLTagNames } from 'jodit/types';
12
+ import { Config } from 'jodit/config';
13
+
14
+ declare module 'jodit/config' {
15
+ interface Config {
16
+ wrapNodes: {
17
+ exclude: HTMLTagNames[];
18
+ };
19
+ }
20
+ }
21
+
22
+ Config.prototype.wrapNodes = {
23
+ exclude: ['hr', 'style']
24
+ };
@@ -5,7 +5,9 @@
5
5
  */
6
6
 
7
7
  /**
8
- * @module plugins/fix
8
+ * [[include:plugins/fix/wrap-nodes/README.md]]
9
+ * @packageDocumentation
10
+ * @module plugins/fix/wrap-nodes
9
11
  */
10
12
 
11
13
  import type { IJodit, Nullable } from 'jodit/types';
@@ -14,10 +16,12 @@ import { Dom } from 'jodit/core/dom';
14
16
  import { isString } from 'jodit/core/helpers/checker';
15
17
  import { autobind } from 'jodit/core/decorators';
16
18
 
19
+ import './config';
20
+
17
21
  /**
18
22
  * Wrap single text nodes in block wrapper
19
23
  */
20
- export class WrapTextNodes extends Plugin {
24
+ export class WrapNodes extends Plugin {
21
25
  /** @override **/
22
26
  protected afterInit(jodit: IJodit): void {
23
27
  if (jodit.o.enter.toLowerCase() === 'br') {
@@ -39,7 +43,7 @@ export class WrapTextNodes extends Plugin {
39
43
  * Process changed value
40
44
  */
41
45
  @autobind
42
- private postProcessSetEditorValue() {
46
+ private postProcessSetEditorValue(): void {
43
47
  const { jodit } = this;
44
48
 
45
49
  if (!jodit.isEditorMode()) {
@@ -113,5 +117,6 @@ export class WrapTextNodes extends Plugin {
113
117
  * Some element which need append in block
114
118
  */
115
119
  private isNotClosed = (n: Nullable<Node>): n is Element =>
116
- Dom.isElement(n) && !(Dom.isBlock(n) || Dom.isTag(n, ['hr', 'style']));
120
+ Dom.isElement(n) &&
121
+ !(Dom.isBlock(n) || Dom.isTag(n, this.j.o.wrapNodes.exclude));
117
122
  }
@@ -50,7 +50,7 @@ export function focus(editor: IJodit): void {
50
50
  });
51
51
  }
52
52
 
53
- const focus = () => {
53
+ const focus = (): void => {
54
54
  editor.s.focus();
55
55
 
56
56
  if (editor.o.cursorAfterAutofocus === 'end') {
@@ -131,7 +131,7 @@ export function formatBlock(editor: IJodit): void {
131
131
  element: third as HTMLTagNames
132
132
  });
133
133
 
134
- editor.setEditorValue();
134
+ editor.synchronizeValues();
135
135
 
136
136
  return false;
137
137
  }
@@ -21,13 +21,13 @@ declare module 'jodit/config' {
21
21
  * Open WYSIWYG in full screen
22
22
  * @example
23
23
  * ```javascript
24
- * var editor = new jodit({
24
+ * var editor = Jodit.make({
25
25
  * fullsize: true // fullsize editor
26
26
  * });
27
27
  * ```
28
28
  * @example
29
29
  * ```javascript
30
- * var editor = new Jodit();
30
+ * var editor = Jodit.make();
31
31
  * editor.e.fire('toggleFullSize');
32
32
  * editor.e.fire('toggleFullSize', true); // fullsize
33
33
  * editor.e.fire('toggleFullSize', false); // usual mode
@@ -81,7 +81,7 @@ export function fullsize(editor: IViewWithToolbar): void {
81
81
  oldWidth: number = 0,
82
82
  wasToggled = false;
83
83
 
84
- const resize = () => {
84
+ const resize = (): void => {
85
85
  const { container, events } = editor;
86
86
 
87
87
  if (events) {
@@ -105,7 +105,7 @@ export function fullsize(editor: IViewWithToolbar): void {
105
105
  /**
106
106
  * Change editor's state between FullSize and normal
107
107
  */
108
- toggle = (enable?: boolean) => {
108
+ toggle = (enable?: boolean): void => {
109
109
  const { container, events } = editor;
110
110
 
111
111
  if (!container) {
@@ -100,9 +100,9 @@ export function iframe(editor: IJodit): void {
100
100
  editor
101
101
  );
102
102
 
103
- const init = () => {
103
+ const init = (): boolean => {
104
104
  if (!editor.iframe) {
105
- return;
105
+ return false;
106
106
  }
107
107
 
108
108
  const doc = (editor.iframe.contentWindow as Window).document;
@@ -110,7 +110,7 @@ export function iframe(editor: IJodit): void {
110
110
 
111
111
  const docMode = opt.editHTMLDocumentMode;
112
112
 
113
- const toggleEditable = () => {
113
+ const toggleEditable = (): void => {
114
114
  attr(
115
115
  doc.body,
116
116
  'contenteditable',
@@ -327,11 +327,11 @@ export class imageProperties extends Plugin {
327
327
  lockSize
328
328
  } = refs<HTMLInputElement>(this.form);
329
329
 
330
- const updateLock = () => {
330
+ const updateLock = (): void => {
331
331
  lockMargin.checked = this.state.marginIsLocked;
332
332
  lockSize.checked = this.state.sizeIsLocked;
333
333
  },
334
- updateAlign = () => {
334
+ updateAlign = (): void => {
335
335
  if (
336
336
  image.style.cssFloat &&
337
337
  ['left', 'right'].indexOf(
@@ -349,24 +349,24 @@ export class imageProperties extends Plugin {
349
349
  }
350
350
  }
351
351
  },
352
- updateBorderRadius = () => {
352
+ updateBorderRadius = (): void => {
353
353
  borderRadius.value = (
354
354
  parseInt(image.style.borderRadius || '0', 10) || '0'
355
355
  ).toString();
356
356
  },
357
- updateId = () => {
357
+ updateId = (): void => {
358
358
  id.value = attr(image, 'id') || '';
359
359
  },
360
- updateStyle = () => {
360
+ updateStyle = (): void => {
361
361
  style.value = attr(image, 'style') || '';
362
362
  },
363
- updateClasses = () => {
363
+ updateClasses = (): void => {
364
364
  classes.value = (attr(image, 'class') || '').replace(
365
365
  /jodit_focused_image[\s]*/,
366
366
  ''
367
367
  );
368
368
  },
369
- updateMargins = () => {
369
+ updateMargins = (): void => {
370
370
  if (!opt.image.editMargins) {
371
371
  return;
372
372
  }
@@ -406,7 +406,7 @@ export class imageProperties extends Plugin {
406
406
 
407
407
  this.state.marginIsLocked = equal;
408
408
  },
409
- updateSizes = () => {
409
+ updateSizes = (): void => {
410
410
  const width =
411
411
  attr(image, 'width') ||
412
412
  css(image, 'width', true) ||
@@ -440,7 +440,7 @@ export class imageProperties extends Plugin {
440
440
  return Math.abs(w - h * this.state.ratio) < 1;
441
441
  })();
442
442
  },
443
- updateText = () => {
443
+ updateText = (): void => {
444
444
  imageTitle.value = attr(image, 'title') || '';
445
445
 
446
446
  imageAlt.value = attr(image, 'alt') || '';
@@ -457,7 +457,7 @@ export class imageProperties extends Plugin {
457
457
  imageLinkOpenInNewTab.checked = false;
458
458
  }
459
459
  },
460
- updateSrc = () => {
460
+ updateSrc = (): void => {
461
461
  imageSrc.value = attr(image, 'src') || '';
462
462
 
463
463
  if (imageViewSrc) {
@@ -601,8 +601,7 @@ export class imageProperties extends Plugin {
601
601
  );
602
602
  }
603
603
 
604
- this.j.setEditorValue();
605
-
604
+ this.j.synchronizeValues();
606
605
  this.dialog.close();
607
606
  }
608
607
 
@@ -613,7 +612,7 @@ export class imageProperties extends Plugin {
613
612
  private openImageEditor(): void {
614
613
  const url: string = attr(this.state.image, 'src') || '',
615
614
  a = this.j.c.element('a'),
616
- loadExternal = () => {
615
+ loadExternal = (): void => {
617
616
  if (a.host !== location.host) {
618
617
  Confirm(
619
618
  this.j.i18n(
@@ -124,7 +124,7 @@ export function indent(editor: IJodit): void {
124
124
  editor.s.restore();
125
125
  });
126
126
 
127
- editor.setEditorValue();
127
+ editor.synchronizeValues();
128
128
 
129
129
  return false;
130
130
  };