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 plugins/print
9
9
  */
10
10
 
11
- import type { IJodit } from 'jodit/types';
11
+ import type { IJodit, Nullable } from 'jodit/types';
12
12
  import { $$, attr, css, isString } from 'jodit/core/helpers';
13
13
  import { Dom } from 'jodit/core/dom';
14
14
 
@@ -67,7 +67,8 @@ function fixedAssetsSizeAndAbsoluteLinks(
67
67
  export function previewBox(
68
68
  editor: IJodit,
69
69
  defaultValue?: string,
70
- points: 'pt' | 'px' | '' = 'px'
70
+ points: 'pt' | 'px' | '' = 'px',
71
+ container: Nullable<HTMLElement> = null
71
72
  ): HTMLElement {
72
73
  const restoreAttributes = fixedAssetsSizeAndAbsoluteLinks(editor, points);
73
74
 
@@ -77,7 +78,11 @@ export function previewBox(
77
78
  return res;
78
79
  }
79
80
 
80
- const div = editor.c.div('jodit__preview-box');
81
+ let div: HTMLElement = editor.c.div('jodit__preview-box');
82
+ if (container) {
83
+ container.appendChild(div);
84
+ }
85
+
81
86
  css(div, {
82
87
  position: 'relative',
83
88
  padding: 16
@@ -100,14 +105,16 @@ export function previewBox(
100
105
 
101
106
  div.appendChild(iframe);
102
107
 
103
- const mywindow = iframe.contentWindow;
108
+ const myWindow = iframe.contentWindow;
104
109
 
105
- if (mywindow) {
110
+ if (myWindow) {
106
111
  editor.e.fire(
107
112
  'generateDocumentStructure.iframe',
108
- mywindow.document,
113
+ myWindow.document,
109
114
  editor
110
115
  );
116
+
117
+ div = myWindow.document.body;
111
118
  }
112
119
  } else {
113
120
  css(div, {
@@ -127,7 +134,7 @@ export function previewBox(
127
134
  for (let i = 0; i < dv.children.length; i += 1) {
128
135
  const c = dv.children[i];
129
136
 
130
- const newNode = document.createElement(c.nodeName);
137
+ const newNode = box.ownerDocument.createElement(c.nodeName);
131
138
 
132
139
  for (let j = 0; j < c.attributes.length; j += 1) {
133
140
  attr(
@@ -8,5 +8,5 @@
8
8
  * @module plugins/print
9
9
  */
10
10
 
11
- export * from './preview';
11
+ export * from './preview/preview';
12
12
  export * from './print';
@@ -1,4 +1,4 @@
1
- @import (reference) '../../styles/mixins';
1
+ @import (reference) '../../../styles/mixins';
2
2
 
3
3
  .jodit__preview-box {
4
4
  table {
@@ -5,20 +5,21 @@
5
5
  */
6
6
 
7
7
  /**
8
- * @module plugins/print
8
+ * @module plugins/print/preview
9
9
  */
10
10
 
11
11
  import './preview.less';
12
12
 
13
- import type { IControlType, IDialog, IJodit } from 'jodit/types';
13
+ import type { IControlType, IJodit } from 'jodit/types';
14
14
  import { Config } from 'jodit/config';
15
- import * as consts from 'jodit/core/constants';
15
+ import { MODE_SOURCE, MODE_WYSIWYG } from 'jodit/core/constants';
16
16
  import { previewBox } from 'jodit/plugins/print/helpers';
17
+ import { Dialog } from 'jodit/modules/dialog/dialog';
17
18
 
18
19
  Config.prototype.controls.preview = {
19
20
  icon: 'eye',
20
21
  command: 'preview',
21
- mode: consts.MODE_SOURCE + consts.MODE_WYSIWYG,
22
+ mode: MODE_SOURCE + MODE_WYSIWYG,
22
23
  tooltip: 'Preview'
23
24
  } as IControlType;
24
25
 
@@ -30,17 +31,17 @@ export function preview(editor: IJodit): void {
30
31
  editor.registerCommand(
31
32
  'preview',
32
33
  (_: any, _1: any, defaultValue: string) => {
33
- const dialog = <IDialog>editor.getInstance('Dialog', {
34
+ const dialog = new Dialog({
34
35
  language: editor.o.language,
35
36
  theme: editor.o.theme
36
37
  });
37
38
 
38
- const div = previewBox(editor, defaultValue);
39
-
40
39
  dialog
41
40
  .setSize(1024, 600)
42
- .open(div, editor.i18n('Preview'))
41
+ .open('', editor.i18n('Preview'))
43
42
  .setModal(true);
43
+
44
+ previewBox(editor, defaultValue, 'px', dialog.getElm('content'));
44
45
  }
45
46
  );
46
47
  }
@@ -30,27 +30,27 @@ Config.prototype.controls.print = {
30
30
 
31
31
  getContainer(editor, Config).appendChild(iframe);
32
32
 
33
- const afterFinishPrint = () => {
33
+ const afterFinishPrint = (): void => {
34
34
  editor.e.off(editor.ow, 'mousemove', afterFinishPrint);
35
35
  Dom.safeRemove(iframe);
36
36
  };
37
37
 
38
- const mywindow = iframe.contentWindow;
39
- if (mywindow) {
38
+ const myWindow = iframe.contentWindow;
39
+ if (myWindow) {
40
40
  editor.e
41
- .on(mywindow, 'onbeforeunload onafterprint', afterFinishPrint)
41
+ .on(myWindow, 'onbeforeunload onafterprint', afterFinishPrint)
42
42
  .on(editor.ow, 'mousemove', afterFinishPrint);
43
43
 
44
44
  if (editor.o.iframe) {
45
45
  editor.e.fire(
46
46
  'generateDocumentStructure.iframe',
47
- mywindow.document,
47
+ myWindow.document,
48
48
  editor
49
49
  );
50
50
 
51
- mywindow.document.body.innerHTML = editor.value;
51
+ myWindow.document.body.innerHTML = editor.value;
52
52
  } else {
53
- mywindow.document.write(
53
+ myWindow.document.write(
54
54
  '<!doctype html><html lang="' +
55
55
  defaultLanguage(editor.o.language) +
56
56
  '"><head><title></title></head>' +
@@ -58,11 +58,20 @@ Config.prototype.controls.print = {
58
58
  editor.value +
59
59
  '</body></html>'
60
60
  );
61
- mywindow.document.close();
61
+ myWindow.document.close();
62
62
  }
63
63
 
64
- mywindow.focus();
65
- mywindow.print();
64
+ const style = myWindow.document.createElement('style');
65
+ style.innerHTML = `@media print {
66
+ body {
67
+ -webkit-print-color-adjust: exact;
68
+ }
69
+ }`;
70
+
71
+ myWindow.document.head.appendChild(style);
72
+
73
+ myWindow.focus();
74
+ myWindow.print();
66
75
  }
67
76
  },
68
77
  mode: consts.MODE_SOURCE + consts.MODE_WYSIWYG,
@@ -15,13 +15,13 @@ import { Plugin } from 'jodit/core/plugin';
15
15
 
16
16
  Config.prototype.controls.redo = {
17
17
  mode: consts.MODE_SPLIT,
18
- isDisabled: (editor: IJodit): boolean => !editor.observer.stack.canRedo(),
18
+ isDisabled: (editor: IJodit): boolean => !editor.history.canRedo(),
19
19
  tooltip: 'Redo'
20
20
  } as IControlType;
21
21
 
22
22
  Config.prototype.controls.undo = {
23
23
  mode: consts.MODE_SPLIT,
24
- isDisabled: (editor: IJodit): boolean => !editor.observer.stack.canUndo(),
24
+ isDisabled: (editor: IJodit): boolean => !editor.history.canUndo(),
25
25
  tooltip: 'Undo'
26
26
  } as IControlType;
27
27
 
@@ -47,7 +47,7 @@ export class redoUndo extends Plugin {
47
47
 
48
48
  protected override afterInit(editor: IJodit): void {
49
49
  const callback = (command: string): void | false => {
50
- editor.observer[command as 'redo' | 'undo']();
50
+ editor.history[command as 'redo' | 'undo']();
51
51
 
52
52
  return false;
53
53
  };
@@ -121,7 +121,7 @@ export class resizer extends Plugin {
121
121
  }
122
122
  }
123
123
 
124
- private addEventListeners() {
124
+ private addEventListeners(): void {
125
125
  const editor = this.j;
126
126
 
127
127
  editor.e
@@ -197,7 +197,7 @@ export class resizer extends Plugin {
197
197
  );
198
198
  }
199
199
 
200
- private onResize = (e: MouseEvent) => {
200
+ private onResize = (e: MouseEvent): void => {
201
201
  if (this.isResized) {
202
202
  if (!this.element) {
203
203
  return;
@@ -283,12 +283,12 @@ export class resizer extends Plugin {
283
283
  }
284
284
  }
285
285
 
286
- private onClickOutside = (e: MouseEvent) => {
286
+ private onClickOutside = (e: MouseEvent): void => {
287
287
  if (this.isShown) {
288
288
  if (this.isResized) {
289
289
  this.j.unlock();
290
290
  this.isResized = false;
291
- this.j.setEditorValue();
291
+ this.j.synchronizeValues();
292
292
  e.stopImmediatePropagation();
293
293
 
294
294
  this.j.e.off(
@@ -302,7 +302,7 @@ export class resizer extends Plugin {
302
302
  }
303
303
  };
304
304
 
305
- private onDelete(e: KeyboardEvent) {
305
+ private onDelete(e: KeyboardEvent): void {
306
306
  if (!this.element) {
307
307
  return;
308
308
  }
@@ -317,7 +317,7 @@ export class resizer extends Plugin {
317
317
  }
318
318
 
319
319
  @debounce()
320
- private onChangeEditor() {
320
+ private onChangeEditor(): void {
321
321
  if (this.isShown) {
322
322
  if (!this.element || !this.element.parentNode) {
323
323
  this.hide();
@@ -404,7 +404,7 @@ export class resizer extends Plugin {
404
404
  }
405
405
  }
406
406
 
407
- private onClickElement = (element: HTMLElement) => {
407
+ private onClickElement = (element: HTMLElement): void => {
408
408
  if (this.isResized) {
409
409
  return;
410
410
  }
@@ -420,7 +420,7 @@ export class resizer extends Plugin {
420
420
  }
421
421
  };
422
422
 
423
- private updateSize = () => {
423
+ private updateSize = (): void => {
424
424
  if (this.isInDestruct || !this.isShown) {
425
425
  return;
426
426
  }
@@ -462,7 +462,7 @@ export class resizer extends Plugin {
462
462
  }
463
463
  };
464
464
 
465
- private showSizeViewer(w: number, h: number) {
465
+ private showSizeViewer(w: number, h: number): void {
466
466
  if (!this.j.o.resizer.showSize) {
467
467
  return;
468
468
  }
@@ -487,7 +487,7 @@ export class resizer extends Plugin {
487
487
  /**
488
488
  * Show resizer
489
489
  */
490
- private show() {
490
+ private show(): void {
491
491
  if (this.j.o.readonly || this.isShown) {
492
492
  return;
493
493
  }
@@ -519,7 +519,7 @@ export class resizer extends Plugin {
519
519
  }
520
520
  }
521
521
 
522
- private hideSizeViewer = () => {
522
+ private hideSizeViewer = (): void => {
523
523
  this.sizeViewer.style.opacity = '0';
524
524
  };
525
525
 
@@ -0,0 +1,38 @@
1
+ Search plugin. it is used for custom search in text
2
+ ![search](https://user-images.githubusercontent.com/794318/34545433-cd0a9220-f10e-11e7-8d26-7e22f66e266d.gif)
3
+
4
+ Disable plugin:
5
+ ```js
6
+ Jodit.make('#editor', {
7
+ useSearch: false
8
+ });
9
+ ```
10
+ or
11
+ ```js
12
+ Jodit.make('#editor', {
13
+ disablePlugins: 'search'
14
+ });
15
+ ```
16
+
17
+ ## JS API
18
+
19
+ ### Find and select some text
20
+
21
+ ```js
22
+ const editor = Jodit.make('#editor');
23
+ editor.value = '<p>this text contains some text</p>';
24
+ editor.e.fire('search', 'some text').then(() => {
25
+ console.log('Selected!');
26
+ })
27
+ ```
28
+
29
+ ### Find next fragment
30
+
31
+ ```js
32
+ const editor = Jodit.make('#editor');
33
+ editor.value = '<p>this text thow times contains some text and some text</p>';
34
+ editor.e.fire('searchNext', 'some text').then(() => {
35
+ console.log('Selected!');
36
+ editor.e.fire('searchNext', 'some text');
37
+ })
38
+ ```
@@ -0,0 +1,82 @@
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/search
9
+ */
10
+
11
+ import type { FuzzySearch, IControlType, IJodit } from 'jodit/types';
12
+ import { Config } from 'jodit/config';
13
+
14
+ declare module 'jodit/config' {
15
+ interface Config {
16
+ /**
17
+ * Enable custom search plugin
18
+ * ![search](https://user-images.githubusercontent.com/794318/34545433-cd0a9220-f10e-11e7-8d26-7e22f66e266d.gif)
19
+ */
20
+ useSearch: boolean;
21
+
22
+ search: {
23
+ lazyIdleTimeout: number;
24
+
25
+ /**
26
+ * Function to search for a string within a substring. The default implementation is [[fuzzySearchIndex]]
27
+ * But you can write your own. It must implement the [[FuzzySearch]] interface.
28
+ *
29
+ * ```ts
30
+ * Jodit.make('#editor', {
31
+ * search: {
32
+ * fuzzySearch: (needle, haystack, offset) => {
33
+ * return [haystack.indexOf(needle, offset), needle.length];
34
+ * }
35
+ * }
36
+ * })
37
+ * ```
38
+ */
39
+ fuzzySearch?: FuzzySearch;
40
+ };
41
+ }
42
+ }
43
+
44
+ Config.prototype.useSearch = true;
45
+ Config.prototype.search = {
46
+ lazyIdleTimeout: 0
47
+ };
48
+
49
+ Config.prototype.controls.find = {
50
+ tooltip: 'Find',
51
+ icon: 'search',
52
+
53
+ exec(jodit: IJodit, _, { control }) {
54
+ const value = control.args && control.args[0];
55
+
56
+ switch (value) {
57
+ case 'findPrevious':
58
+ jodit.e.fire('searchPrevious');
59
+ break;
60
+
61
+ case 'findNext':
62
+ jodit.e.fire('searchNext');
63
+ break;
64
+
65
+ case 'replace':
66
+ jodit.execCommand('openReplaceDialog');
67
+ break;
68
+
69
+ default:
70
+ jodit.execCommand('openSearchDialog');
71
+ }
72
+ },
73
+
74
+ list: {
75
+ search: 'Find',
76
+ findNext: 'Find Next',
77
+ findPrevious: 'Find Previous',
78
+ replace: 'Replace'
79
+ },
80
+
81
+ childTemplate: (_, k, v) => v
82
+ } as IControlType;
@@ -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/search
9
+ */
10
+
11
+ export * from './sentence-finder';
12
+ export * from './wrap-ranges-texts-in-tmp-span';
@@ -0,0 +1,103 @@
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/search
9
+ */
10
+
11
+ import type {
12
+ CanUndef,
13
+ FuzzySearch,
14
+ ISelectionRange,
15
+ Nullable
16
+ } from 'jodit/types';
17
+ import { fuzzySearchIndex } from 'jodit/src/core/helpers/string/fuzzy-search-index';
18
+
19
+ export interface State {
20
+ query: string;
21
+ sentence: SentenceFinder;
22
+ }
23
+
24
+ interface QueueItem {
25
+ startIndex: number;
26
+ endIndex: number;
27
+ node: Text;
28
+ }
29
+
30
+ export class SentenceFinder {
31
+ private queue: QueueItem[] = [];
32
+ private value: string = '';
33
+
34
+ constructor(private readonly searchIndex: FuzzySearch = fuzzySearchIndex) {}
35
+
36
+ add(node: Text): void {
37
+ const value = (node.nodeValue ?? '').toLowerCase();
38
+
39
+ if (!value.length) {
40
+ return;
41
+ }
42
+
43
+ const index = this.value.length;
44
+
45
+ this.queue.push({
46
+ startIndex: index,
47
+ endIndex: index + value.length,
48
+ node
49
+ });
50
+
51
+ this.value += value;
52
+ }
53
+
54
+ ranges(needle: string, position: number = 0): Nullable<ISelectionRange[]> {
55
+ const results: ISelectionRange[] = [];
56
+
57
+ let index = position,
58
+ len = 0,
59
+ startQueueIndex = 0;
60
+
61
+ // Find all ranges in substring
62
+ do {
63
+ [index, len] = this.searchIndex(needle, this.value, index);
64
+
65
+ if (index !== -1) {
66
+ let startContainer: CanUndef<Text>,
67
+ startOffset: number = 0,
68
+ endContainer: CanUndef<Text>,
69
+ endOffset: number = 0;
70
+
71
+ for (let i = startQueueIndex; i < this.queue.length; i += 1) {
72
+ if (!startContainer && this.queue[i].endIndex > index) {
73
+ startContainer = this.queue[i].node;
74
+ startOffset = index - this.queue[i].startIndex;
75
+ }
76
+
77
+ if (
78
+ startContainer &&
79
+ this.queue[i].endIndex >= index + len
80
+ ) {
81
+ endContainer = this.queue[i].node;
82
+ endOffset = index + len - this.queue[i].startIndex;
83
+ startQueueIndex = i;
84
+ break;
85
+ }
86
+ }
87
+
88
+ if (startContainer && endContainer) {
89
+ results.push({
90
+ startContainer,
91
+ startOffset,
92
+ endContainer,
93
+ endOffset
94
+ });
95
+ }
96
+
97
+ index += len;
98
+ }
99
+ } while (index !== -1);
100
+
101
+ return results.length === 0 ? null : results;
102
+ }
103
+ }
@@ -0,0 +1,120 @@
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/search
9
+ */
10
+
11
+ import type { CanUndef, ICreate, ISelectionRange, Nullable } from 'jodit/types';
12
+ import { Dom } from 'jodit/core/dom';
13
+ import { $$ } from 'jodit/src/core/helpers/utils/selector';
14
+
15
+ const TMP_ATTR = 'jd-tmp-selection';
16
+
17
+ export function wrapRangesTextsInTmpSpan(
18
+ rng: ISelectionRange,
19
+ restRanges: ISelectionRange[],
20
+ ci: ICreate,
21
+ root: HTMLElement
22
+ ): void {
23
+ if (
24
+ rng.startContainer.nodeValue == null ||
25
+ rng.endContainer.nodeValue == null
26
+ ) {
27
+ return;
28
+ }
29
+
30
+ const span = ci.element('span', {
31
+ [TMP_ATTR]: true
32
+ });
33
+
34
+ const startText = rng.startContainer.nodeValue;
35
+
36
+ let diff = 0;
37
+ if (rng.startOffset !== 0) {
38
+ const text = ci.text(startText.substring(0, rng.startOffset));
39
+ rng.startContainer.nodeValue = startText.substring(rng.startOffset);
40
+ Dom.before(rng.startContainer, text);
41
+
42
+ if (rng.startContainer === rng.endContainer) {
43
+ diff = rng.startOffset;
44
+ rng.endOffset -= diff;
45
+ }
46
+
47
+ rng.startOffset = 0;
48
+ }
49
+
50
+ const endText = rng.endContainer.nodeValue;
51
+
52
+ if (rng.endOffset !== endText.length) {
53
+ const text = ci.text(endText.substring(rng.endOffset));
54
+ rng.endContainer.nodeValue = endText.substring(0, rng.endOffset);
55
+ Dom.after(rng.endContainer, text);
56
+
57
+ for (const range of restRanges) {
58
+ if (range.startContainer === rng.endContainer) {
59
+ range.startContainer = text;
60
+ range.startOffset = range.startOffset - rng.endOffset - diff;
61
+
62
+ if (range.endContainer === rng.endContainer) {
63
+ range.endContainer = text;
64
+ range.endOffset = range.endOffset - rng.endOffset - diff;
65
+ }
66
+ } else {
67
+ break;
68
+ }
69
+ }
70
+
71
+ rng.endOffset = rng.endContainer.nodeValue.length;
72
+ }
73
+
74
+ let next: CanUndef<Nullable<Node>> = rng.startContainer;
75
+
76
+ do {
77
+ if (!next) {
78
+ break;
79
+ }
80
+
81
+ if (Dom.isText(next) && !isSelectionWrapper(next.parentNode)) {
82
+ Dom.wrap(next, span.cloneNode() as HTMLElement, ci);
83
+ }
84
+
85
+ if (next === rng.endContainer) {
86
+ break;
87
+ }
88
+
89
+ let step: Nullable<Node> = next.firstChild || next.nextSibling;
90
+
91
+ if (!step) {
92
+ while (next && !next.nextSibling && next !== root) {
93
+ next = next.parentNode;
94
+ }
95
+
96
+ step = next?.nextSibling as Nullable<Node>;
97
+ }
98
+
99
+ next = step;
100
+ } while (next && next !== root);
101
+ }
102
+
103
+ export function getSelectionWrappers(root: HTMLElement): HTMLElement[] {
104
+ return $$(`[${TMP_ATTR}]`, root);
105
+ }
106
+
107
+ export function clearSelectionWrappers(root: HTMLElement): void {
108
+ getSelectionWrappers(root).forEach(span => Dom.unwrap(span));
109
+ }
110
+
111
+ export function clearSelectionWrappersFromHTML(root: string): string {
112
+ return root.replace(
113
+ RegExp(`<span[^>]+${TMP_ATTR}[^>]+>(.*?)</span>`, 'g'),
114
+ '$1'
115
+ );
116
+ }
117
+
118
+ export function isSelectionWrapper(node: unknown): boolean {
119
+ return Dom.isElement(node) && node.hasAttribute(TMP_ATTR);
120
+ }