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
@@ -8,7 +8,7 @@
8
8
  * @module modules/file-browser
9
9
  */
10
10
 
11
- import type { IFileBrowser } from 'jodit/types';
11
+ import type { IDialog, IFileBrowser } from 'jodit/types';
12
12
  import { Dialog } from 'jodit/modules/dialog';
13
13
 
14
14
  import { Dom } from 'jodit/core/dom';
@@ -22,7 +22,7 @@ import { loadTree } from 'jodit/modules/file-browser/fetch/load-tree';
22
22
  import { deleteFile } from 'jodit/modules/file-browser/fetch/delete-file';
23
23
 
24
24
  const CLASS_PREVIEW = 'jodit-filebrowser-preview',
25
- preview_tpl_next = (next = 'next', right = 'right') =>
25
+ preview_tpl_next = (next = 'next', right = 'right'): string =>
26
26
  `<div class="${CLASS_PREVIEW}__navigation ${CLASS_PREVIEW}__navigation_arrow_${next}">` +
27
27
  '' +
28
28
  Icon.get('angle-' + right) +
@@ -45,7 +45,7 @@ export default (self: IFileBrowser): ((e: DragEvent) => boolean | void) => {
45
45
  let item: HTMLElement = a;
46
46
 
47
47
  const opt = self.options,
48
- ga = (key: string) => attr(item, key) || '';
48
+ ga = (key: string): string => attr(item, key) || '';
49
49
 
50
50
  self.async.setTimeout(() => {
51
51
  const selectedItem = elementToItem(a, elementsMap(self));
@@ -64,15 +64,14 @@ export default (self: IFileBrowser): ((e: DragEvent) => boolean | void) => {
64
64
  ? {
65
65
  icon: 'pencil',
66
66
  title: 'Edit',
67
- exec: () => {
68
- return openImageEditor.call(
67
+ exec: (): Promise<IDialog> =>
68
+ openImageEditor.call(
69
69
  self,
70
70
  ga('href'),
71
71
  ga('data-name'),
72
72
  ga('data-path'),
73
73
  ga('data-source')
74
- );
75
- }
74
+ )
76
75
  }
77
76
  : false,
78
77
 
@@ -80,7 +79,7 @@ export default (self: IFileBrowser): ((e: DragEvent) => boolean | void) => {
80
79
  ? {
81
80
  icon: 'italic',
82
81
  title: 'Rename',
83
- exec: async () => {
82
+ exec: (): void => {
84
83
  self.e.fire(
85
84
  'fileRename.filebrowser',
86
85
  ga('data-name'),
@@ -95,7 +94,7 @@ export default (self: IFileBrowser): ((e: DragEvent) => boolean | void) => {
95
94
  ? {
96
95
  icon: 'bin',
97
96
  title: 'Delete',
98
- exec: async () => {
97
+ exec: async (): Promise<void> => {
99
98
  try {
100
99
  await deleteFile(
101
100
  self,
@@ -117,7 +116,7 @@ export default (self: IFileBrowser): ((e: DragEvent) => boolean | void) => {
117
116
  ? {
118
117
  icon: 'eye',
119
118
  title: 'Preview',
120
- exec: () => {
119
+ exec: (): void => {
121
120
  const preview = new Dialog({
122
121
  fullsize: self.o.fullsize,
123
122
  language: self.o.language,
@@ -134,12 +133,12 @@ export default (self: IFileBrowser): ((e: DragEvent) => boolean | void) => {
134
133
  prev = self.c.fromHTML(
135
134
  preview_tpl_next('prev', 'left')
136
135
  ),
137
- addLoadHandler = (src: string) => {
136
+ addLoadHandler = (src: string): void => {
138
137
  const image = self.c.element('img');
139
138
 
140
139
  image.setAttribute('src', src);
141
140
 
142
- const onload = () => {
141
+ const onload = (): void => {
143
142
  if (self.isInDestruct) {
144
143
  return;
145
144
  }
@@ -250,7 +249,7 @@ export default (self: IFileBrowser): ((e: DragEvent) => boolean | void) => {
250
249
  {
251
250
  icon: 'upload',
252
251
  title: 'Download',
253
- exec: () => {
252
+ exec: (): void => {
254
253
  const url = ga('href');
255
254
 
256
255
  if (url) {
@@ -17,7 +17,7 @@ import { loadItems } from 'jodit/modules/file-browser/fetch/load-items';
17
17
  * Loads a list of directories
18
18
  */
19
19
  export async function loadTree(fb: IFileBrowser): Promise<any> {
20
- const errorUni = (e: string | Error) => {
20
+ const errorUni = (e: string | Error): Error => {
21
21
  throw e instanceof Error ? e : error(e);
22
22
  };
23
23
 
@@ -28,7 +28,8 @@ import type {
28
28
  IUploaderOptions,
29
29
  IDialog,
30
30
  CanUndef,
31
- IViewOptions
31
+ IViewOptions,
32
+ CallbackFunction
32
33
  } from 'jodit/types';
33
34
 
34
35
  import { Storage } from 'jodit/core/storage';
@@ -90,8 +91,10 @@ export class FileBrowser extends ViewWithToolbar implements IFileBrowser {
90
91
  dataProvider!: IFileBrowserDataProvider;
91
92
 
92
93
  // eslint-disable-next-line no-unused-vars
93
- private onSelect(callback?: (_: IFileBrowserCallBackData) => void) {
94
- return () => {
94
+ private onSelect(
95
+ callback?: (_: IFileBrowserCallBackData) => void
96
+ ): CallbackFunction {
97
+ return (): boolean => {
95
98
  if (this.state.activeElements.length) {
96
99
  const files: string[] = [];
97
100
  const isImages: boolean[] = [];
@@ -124,7 +127,7 @@ export class FileBrowser extends ViewWithToolbar implements IFileBrowser {
124
127
  };
125
128
  }
126
129
 
127
- private errorHandler = (resp: Error | IFileBrowserAnswer) => {
130
+ private errorHandler = (resp: Error | IFileBrowserAnswer): void => {
128
131
  if (resp instanceof Error) {
129
132
  this.status(this.i18n(resp.message));
130
133
  } else {
@@ -258,7 +261,7 @@ export class FileBrowser extends ViewWithToolbar implements IFileBrowser {
258
261
  });
259
262
  }
260
263
 
261
- private initUploader(editor?: IFileBrowser | IJodit) {
264
+ private initUploader(editor?: IFileBrowser | IJodit): void {
262
265
  const self = this,
263
266
  options = editor?.options?.uploader,
264
267
  uploaderOptions: IUploaderOptions<IUploader> = ConfigProto(
@@ -266,7 +269,7 @@ export class FileBrowser extends ViewWithToolbar implements IFileBrowser {
266
269
  Config.defaultOptions.uploader
267
270
  ) as IUploaderOptions<IUploader>;
268
271
 
269
- const uploadHandler = () => loadItems(this);
272
+ const uploadHandler = (): Promise<any> => loadItems(this);
270
273
 
271
274
  self.uploader = self.getInstance('Uploader', uploaderOptions);
272
275
  self.uploader
@@ -399,7 +402,7 @@ export class FileBrowser extends ViewWithToolbar implements IFileBrowser {
399
402
  self.setStatus(STATUSES.ready);
400
403
  }
401
404
 
402
- private proxyDialogEvents(self: FileBrowser) {
405
+ private proxyDialogEvents(self: FileBrowser): void {
403
406
  ['afterClose', 'beforeOpen'].forEach(proxyEvent => {
404
407
  self.dialog.events.on(self.dialog, proxyEvent, () => {
405
408
  this.e.fire(proxyEvent);
@@ -0,0 +1,5 @@
1
+ To clear the history, you can call the method:
2
+
3
+ ```js
4
+ editor.history.clear();
5
+ ```
@@ -5,25 +5,25 @@
5
5
  */
6
6
 
7
7
  /**
8
- * @module modules/observer
8
+ * @module modules/history
9
9
  */
10
10
 
11
11
  import type { SnapshotType } from 'jodit/types';
12
- import type { Observer } from './observer';
12
+ import type { History } from './history';
13
13
 
14
14
  export class Command {
15
15
  undo(): void {
16
- this.observer.snapshot.restore(this.oldValue);
16
+ this.history.snapshot.restore(this.oldValue);
17
17
  }
18
18
 
19
19
  redo(): void {
20
- this.observer.snapshot.restore(this.newValue);
20
+ this.history.snapshot.restore(this.newValue);
21
21
  }
22
22
 
23
23
  constructor(
24
24
  readonly oldValue: SnapshotType,
25
25
  readonly newValue: SnapshotType,
26
- readonly observer: Observer,
26
+ private readonly history: History,
27
27
  readonly tick: number
28
28
  ) {}
29
29
  }
@@ -5,12 +5,19 @@
5
5
  */
6
6
 
7
7
  /**
8
- * [[include:modules/observer/README.md]]
8
+ * [[include:modules/history/README.md]]
9
9
  * @packageDocumentation
10
- * @module modules/observer
10
+ * @module modules/history
11
11
  */
12
12
 
13
- import type { IJodit, SnapshotType, IObserver } from 'jodit/types';
13
+ import type {
14
+ IJodit,
15
+ SnapshotType,
16
+ IHistory,
17
+ ISnapshot,
18
+ IStack,
19
+ IDestructible
20
+ } from 'jodit/types';
14
21
  import { Config } from 'jodit/config';
15
22
  import { ViewComponent } from 'jodit/core/component';
16
23
  import { Snapshot } from './snapshot';
@@ -20,7 +27,9 @@ import { debounce } from 'jodit/core/decorators';
20
27
 
21
28
  declare module 'jodit/config' {
22
29
  interface Config {
23
- observer: {
30
+ history: {
31
+ enable: boolean;
32
+
24
33
  /**
25
34
  * Limit of history length
26
35
  */
@@ -31,21 +40,29 @@ declare module 'jodit/config' {
31
40
  */
32
41
  timeout: number;
33
42
  };
43
+
44
+ /**
45
+ * @deprecated Instead use `history`
46
+ */
47
+ observer: this['history'];
34
48
  }
35
49
  }
36
50
 
37
- Config.prototype.observer = {
51
+ Config.prototype.history = {
52
+ enable: true,
38
53
  maxHistoryLength: Infinity,
39
- timeout: 100
54
+ timeout: 1000
40
55
  };
41
56
 
57
+ Config.prototype.observer = Config.prototype.history;
58
+
42
59
  /**
43
60
  * The module monitors the status of the editor and creates / deletes the required number of Undo / Redo shots .
44
61
  */
45
- export class Observer extends ViewComponent<IJodit> implements IObserver {
62
+ export class History extends ViewComponent<IJodit> implements IHistory {
46
63
  /** @override */
47
- className(): string {
48
- return 'Observer';
64
+ override className(): string {
65
+ return 'History';
49
66
  }
50
67
 
51
68
  private __startValue!: SnapshotType;
@@ -58,8 +75,58 @@ export class Observer extends ViewComponent<IJodit> implements IObserver {
58
75
  this.__startValue = value;
59
76
  }
60
77
 
61
- stack: Stack = new Stack(this.j.o.observer.maxHistoryLength);
62
- snapshot: Snapshot = new Snapshot(this.j);
78
+ private readonly stack: IStack;
79
+ public snapshot: ISnapshot & IDestructible;
80
+
81
+ constructor(
82
+ editor: IJodit,
83
+ stack = new Stack(editor.o.history.maxHistoryLength),
84
+ snapshot = new Snapshot(editor)
85
+ ) {
86
+ super(editor);
87
+
88
+ this.stack = stack;
89
+ this.snapshot = snapshot;
90
+
91
+ if (editor.o.history.enable) {
92
+ editor.e.on('afterAddPlace.history', () => {
93
+ if (this.isInDestruct) {
94
+ return;
95
+ }
96
+
97
+ this.startValue = this.snapshot.make();
98
+
99
+ editor.events
100
+ // save selection
101
+ .on('internalChange', () => {
102
+ this.startValue = this.snapshot.make();
103
+ })
104
+ .on(
105
+ editor.editor,
106
+ [
107
+ 'changeSelection',
108
+ 'selectionstart',
109
+ 'selectionchange',
110
+ 'mousedown',
111
+ 'mouseup',
112
+ 'keydown',
113
+ 'keyup'
114
+ ]
115
+ .map(f => f + '.history')
116
+ .join(' '),
117
+ () => {
118
+ if (
119
+ this.startValue.html ===
120
+ this.j.getNativeEditorValue()
121
+ ) {
122
+ this.startValue = this.snapshot.make();
123
+ }
124
+ }
125
+ )
126
+ .on(this, 'change.history', this.onChange);
127
+ });
128
+ }
129
+ }
63
130
 
64
131
  private updateTick: number = 0;
65
132
 
@@ -72,6 +139,10 @@ export class Observer extends ViewComponent<IJodit> implements IObserver {
72
139
  */
73
140
  @debounce()
74
141
  private onChange(): void {
142
+ this.processChanges();
143
+ }
144
+
145
+ processChanges(): void {
75
146
  if (this.snapshot.isBlocked) {
76
147
  return;
77
148
  }
@@ -118,6 +189,10 @@ export class Observer extends ViewComponent<IJodit> implements IObserver {
118
189
  }
119
190
  }
120
191
 
192
+ canRedo(): boolean {
193
+ return this.stack.canRedo();
194
+ }
195
+
121
196
  /**
122
197
  * Return the state of the WYSIWYG editor to step forward
123
198
  */
@@ -128,64 +203,31 @@ export class Observer extends ViewComponent<IJodit> implements IObserver {
128
203
  }
129
204
  }
130
205
 
206
+ canUndo(): boolean {
207
+ return this.stack.canUndo();
208
+ }
209
+
131
210
  clear(): void {
132
211
  this.startValue = this.snapshot.make();
133
212
  this.stack.clear();
134
213
  this.fireChangeStack();
135
214
  }
136
215
 
137
- replaceSnapshot(): void {
138
- this.updateStack(true);
216
+ get length(): number {
217
+ return this.stack.length;
139
218
  }
140
219
 
141
220
  private fireChangeStack(): void {
142
221
  this.j && !this.j.isInDestruct && this.j.events?.fire('changeStack');
143
222
  }
144
223
 
145
- constructor(editor: IJodit) {
146
- super(editor);
147
-
148
- editor.e.on('afterAddPlace.observer', () => {
149
- if (this.isInDestruct) {
150
- return;
151
- }
152
-
153
- this.startValue = this.snapshot.make();
154
-
155
- editor.events
156
- // save selection
157
- .on('internalChange', () => {
158
- this.startValue = this.snapshot.make();
159
- })
160
- .on(
161
- editor.editor,
162
- [
163
- 'changeSelection',
164
- 'selectionstart',
165
- 'selectionchange',
166
- 'mousedown',
167
- 'mouseup',
168
- 'keydown',
169
- 'keyup'
170
- ]
171
- .map(f => f + '.observer')
172
- .join(' '),
173
- () => {
174
- if (
175
- this.startValue.html ===
176
- this.j.getNativeEditorValue()
177
- ) {
178
- this.startValue = this.snapshot.make();
179
- }
180
- }
181
- )
182
- .on(this, 'change.observer', this.onChange);
183
- });
184
- }
185
-
186
224
  override destruct(): void {
225
+ if (this.isInDestruct) {
226
+ return;
227
+ }
228
+
187
229
  if (this.j.events) {
188
- this.j.e.off('.observer');
230
+ this.j.e.off('.history');
189
231
  }
190
232
 
191
233
  this.snapshot.destruct();
@@ -5,20 +5,19 @@
5
5
  */
6
6
 
7
7
  /**
8
- * @module modules/observer
8
+ * @module modules/history
9
9
  */
10
10
 
11
11
  import type { IJodit, ISnapshot, SnapshotType } from 'jodit/types';
12
12
  import { ViewComponent } from 'jodit/core/component';
13
13
  import { Dom } from 'jodit/core/dom';
14
14
 
15
- // declare const isProd: boolean;
16
15
  /**
17
16
  * Module for creating snapshot of editor which includes html content and the current selection
18
17
  */
19
18
  export class Snapshot extends ViewComponent<IJodit> implements ISnapshot {
20
19
  /** @override */
21
- className(): string {
20
+ override className(): string {
22
21
  return 'Snapshot';
23
22
  }
24
23
 
@@ -186,7 +185,7 @@ export class Snapshot extends ViewComponent<IJodit> implements ISnapshot {
186
185
 
187
186
  const value = this.j.getNativeEditorValue();
188
187
  if (value !== snapshot.html) {
189
- this.j.setEditorValue(snapshot.html);
188
+ this.j.value = snapshot.html;
190
189
  }
191
190
 
192
191
  this.restoreOnlySelection(snapshot);
@@ -5,23 +5,23 @@
5
5
  */
6
6
 
7
7
  /**
8
- * @module modules/observer
8
+ * @module modules/history
9
9
  */
10
10
 
11
11
  import type { CanUndef, IStack } from 'jodit/types';
12
12
  import type { Command } from './command';
13
13
 
14
14
  export class Stack implements IStack {
15
- private commands: Command[] = [];
15
+ private readonly commands: Command[] = [];
16
16
  private stackPosition: number = -1;
17
17
 
18
- constructor(private size: number) {}
18
+ constructor(private readonly size: number) {}
19
19
 
20
20
  get length(): number {
21
21
  return this.commands.length;
22
22
  }
23
23
 
24
- private clearRedo() {
24
+ private clearRedo(): void {
25
25
  this.commands.length = this.stackPosition + 1;
26
26
  }
27
27
 
@@ -147,7 +147,7 @@ export class ImageEditor extends ViewComponent {
147
147
  return valueNbr || 0;
148
148
  };
149
149
 
150
- private calcCropBox = () => {
150
+ private calcCropBox = (): void => {
151
151
  const node = this.crop_box.parentNode as HTMLElement,
152
152
  w = node.offsetWidth * 0.8,
153
153
  h = node.offsetHeight * 0.8;
@@ -174,7 +174,7 @@ export class ImageEditor extends ViewComponent {
174
174
  });
175
175
  };
176
176
 
177
- private showCrop = () => {
177
+ private showCrop = (): void => {
178
178
  if (!this.cropImage) {
179
179
  return;
180
180
  }
@@ -213,7 +213,7 @@ export class ImageEditor extends ViewComponent {
213
213
  this.j.e.fire(this.cropHandler, 'updatesize');
214
214
  };
215
215
 
216
- private updateCropBox = () => {
216
+ private updateCropBox = (): void => {
217
217
  if (!this.cropImage) {
218
218
  return;
219
219
  }
@@ -230,12 +230,12 @@ export class ImageEditor extends ViewComponent {
230
230
  this.cropBox.w.toFixed(0) + 'x' + this.cropBox.h.toFixed(0);
231
231
  };
232
232
 
233
- private updateResizeBox = () => {
233
+ private updateResizeBox = (): void => {
234
234
  this.resizeBox.w = this.image.offsetWidth || this.naturalWidth;
235
235
  this.resizeBox.h = this.image.offsetHeight || this.naturalHeight;
236
236
  };
237
237
 
238
- private setHandlers = () => {
238
+ private setHandlers = (): void => {
239
239
  const self: ImageEditor = this;
240
240
 
241
241
  const { widthInput, heightInput } = refs<HTMLInputElement>(this.editor);
@@ -439,7 +439,7 @@ export class ImageEditor extends ViewComponent {
439
439
 
440
440
  @debounce()
441
441
  @autobind
442
- private onChangeSizeInput(e: MouseEvent) {
442
+ private onChangeSizeInput(e: MouseEvent): void {
443
443
  const self = this,
444
444
  input = e.target as HTMLInputElement,
445
445
  { widthInput, heightInput } = refs<HTMLInputElement>(this.editor),
@@ -615,7 +615,7 @@ export class ImageEditor extends ViewComponent {
615
615
  * Open image editor
616
616
  * @example
617
617
  * ```javascript
618
- * var jodit = new Jodit('.editor', {
618
+ * var jodit = Jodit.make('.editor', {
619
619
  * imageeditor: {
620
620
  * crop: false,
621
621
  * closeAfterSave: true,
@@ -674,7 +674,7 @@ export class ImageEditor extends ViewComponent {
674
674
  this.editor
675
675
  );
676
676
 
677
- const onload = () => {
677
+ const onload = (): void => {
678
678
  if (this.isDestructed) {
679
679
  return;
680
680
  }
@@ -14,7 +14,7 @@ import { Icon } from 'jodit/core/ui';
14
14
  const jie = 'jodit-image-editor';
15
15
  const gi = Icon.get.bind(Icon);
16
16
 
17
- const act = (el: boolean, className = 'jodti-image-editor_active') =>
17
+ const act = (el: boolean, className = 'jodti-image-editor_active'): string =>
18
18
  el ? className : '';
19
19
 
20
20
  export const form = (
@@ -27,7 +27,7 @@ export const form = (
27
27
  label: string,
28
28
  ref: string,
29
29
  active: boolean = true
30
- ) => `<div class="jodit-form__group">
30
+ ): string => `<div class="jodit-form__group">
31
31
  <label>${i(label)}</label>
32
32
 
33
33
  <label class='jodit-switcher'>
@@ -16,7 +16,7 @@ export * from '../core/request';
16
16
  export { Component, ViewComponent, STATUSES } from '../core/component';
17
17
  export { ContextMenu } from './context-menu/context-menu';
18
18
  export * from './dialog/';
19
- export { Dom } from '../core/dom';
19
+ export { Dom, LazyWalker } from '../core/dom';
20
20
  export { Plugin } from '../core/plugin';
21
21
  export { Create } from '../core/create';
22
22
  export {
@@ -40,9 +40,9 @@ export * from './file-browser';
40
40
  import * as Helpers from '../core/helpers/';
41
41
  export { Helpers };
42
42
  export { ImageEditor } from './image-editor/image-editor';
43
- export { Observer } from './observer/observer';
43
+ export { History } from './history/history';
44
+ export { Snapshot } from './history/snapshot';
44
45
  export { Select, CommitStyle } from '../core/selection';
45
- export { Snapshot } from './observer/snapshot';
46
46
  export { StatusBar } from './status-bar/status-bar';
47
47
  export { Table } from './table/table';
48
48
  export { ToolbarEditorCollection } from './toolbar/collection/editor-collection';
@@ -121,6 +121,10 @@ export class StatusBar extends ViewComponent<IJodit> implements IStatusBar {
121
121
  }
122
122
 
123
123
  override destruct(): void {
124
+ if (this.isInDestruct) {
125
+ return;
126
+ }
127
+
124
128
  this.setStatus(STATUSES.beforeDestruct);
125
129
  Dom.safeRemove(this.container);
126
130
  super.destruct();
@@ -922,7 +922,7 @@ export class Table extends ViewComponent<IJodit> {
922
922
  key: string,
923
923
  value: string | number | null,
924
924
  marked: HTMLTableCellElement[]
925
- ) {
925
+ ): void {
926
926
  marked.push(cell);
927
927
 
928
928
  const dict = markedValue.get(cell) ?? {};
@@ -930,7 +930,7 @@ export class Table extends ViewComponent<IJodit> {
930
930
  markedValue.set(cell, dict);
931
931
  }
932
932
 
933
- private static unmark(marked: HTMLTableCellElement[]) {
933
+ private static unmark(marked: HTMLTableCellElement[]): void {
934
934
  marked.forEach(cell => {
935
935
  const dict = markedValue.get(cell);
936
936
 
@@ -54,7 +54,7 @@ export class ToolbarButton<T extends IViewBased = IViewBased>
54
54
  return 'ToolbarButton';
55
55
  }
56
56
 
57
- override state = {
57
+ override readonly state = {
58
58
  ...UIButtonState(),
59
59
  theme: 'toolbar',
60
60
  currentValue: '',
@@ -160,7 +160,7 @@ export class ToolbarButton<T extends IViewBased = IViewBased>
160
160
  }
161
161
 
162
162
  /** @override */
163
- override onChangeTabIndex(): void {
163
+ protected override onChangeTabIndex(): void {
164
164
  attr(this.button, 'tabindex', this.state.tabIndex);
165
165
  }
166
166
 
@@ -112,7 +112,7 @@ export class ToolbarCollection<T extends IViewWithToolbar = IViewWithToolbar>
112
112
  this.initEvents();
113
113
  }
114
114
 
115
- private initEvents() {
115
+ private initEvents(): void {
116
116
  this.j.e
117
117
  .on(this.listenEvents, this.update)
118
118
  .on('afterSetMode focus', this.immediateUpdate);
@@ -34,7 +34,7 @@ export function processOldBrowserDrag(
34
34
  getContainer(self.j, self.constructor).appendChild(div);
35
35
 
36
36
  const selection = isJoditObject(self.j) ? self.j.s.save() : null,
37
- restore = () =>
37
+ restore = (): void | null | boolean =>
38
38
  selection && isJoditObject(self.j) && self.j.s.restore();
39
39
 
40
40
  div.focus();
@@ -58,7 +58,7 @@ export function sendFiles(
58
58
  promises.push(
59
59
  uploader.j.async.promise((resolve, reject) => {
60
60
  reader.onerror = reject;
61
- reader.onloadend = () => {
61
+ reader.onloadend = (): void => {
62
62
  const resp = {
63
63
  baseurl: '',
64
64
  files: [reader.result],
@@ -25,7 +25,7 @@ export function send(
25
25
  request: FormData | IDictionary<string> | string
26
26
  ): Promise<any> => {
27
27
  const ajax = new Ajax<IUploaderAnswer>(uploader.j, {
28
- xhr: () => {
28
+ xhr: (): XMLHttpRequest => {
29
29
  const xhr = new XMLHttpRequest();
30
30
 
31
31
  if (