jodit 3.19.4 → 3.20.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 (217) hide show
  1. package/build/jodit.css +45 -42
  2. package/build/jodit.es2018.css +38 -36
  3. package/build/jodit.es2018.en.css +38 -36
  4. package/build/jodit.es2018.en.js +22562 -25637
  5. package/build/jodit.es2018.en.min.css +1 -1
  6. package/build/jodit.es2018.en.min.js +1 -1
  7. package/build/jodit.es2018.js +23105 -26181
  8. package/build/jodit.es2018.min.css +1 -1
  9. package/build/jodit.es2018.min.js +1 -1
  10. package/build/jodit.js +797 -386
  11. package/build/jodit.min.css +2 -2
  12. package/build/jodit.min.js +1 -1
  13. package/build/plugins/debug/debug.es2018.en.js +97 -0
  14. package/build/plugins/debug/debug.es2018.en.min.js +1 -0
  15. package/build/plugins/debug/debug.es2018.js +97 -0
  16. package/build/plugins/debug/debug.es2018.min.js +1 -0
  17. package/build/plugins/debug/debug.js +96 -0
  18. package/build/plugins/debug/debug.min.js +1 -0
  19. package/build/plugins/speech-recognize/speech-recognize.css +1 -1
  20. package/build/plugins/speech-recognize/speech-recognize.es2018.css +1 -1
  21. package/build/plugins/speech-recognize/speech-recognize.es2018.en.css +1 -1
  22. package/build/plugins/speech-recognize/speech-recognize.es2018.en.js +331 -398
  23. package/build/plugins/speech-recognize/speech-recognize.es2018.en.min.js +1 -1
  24. package/build/plugins/speech-recognize/speech-recognize.es2018.js +331 -398
  25. package/build/plugins/speech-recognize/speech-recognize.es2018.min.js +1 -1
  26. package/build/plugins/speech-recognize/speech-recognize.js +1 -1
  27. package/build/vdom.css +1 -1
  28. package/build/vdom.js +1 -1
  29. package/index.html +2 -2
  30. package/package.json +9 -4
  31. package/src/config.ts +4 -2
  32. package/src/core/constants.ts +7 -7
  33. package/src/core/decorators/derive/README.md +71 -0
  34. package/src/core/decorators/derive/derive.ts +48 -0
  35. package/src/core/decorators/index.ts +1 -0
  36. package/src/core/decorators/spy/spy.ts +5 -0
  37. package/src/core/dom/dom.test.js +0 -1
  38. package/src/core/dom/dom.ts +28 -13
  39. package/src/core/event-emitter/observable.ts +3 -3
  40. package/src/core/helpers/helpers.test.js +0 -170
  41. package/src/core/plugin/plugin-system.ts +20 -0
  42. package/src/core/selection/select.ts +27 -9
  43. package/src/core/selection/style/api/toggle/toggle-ordered-list.ts +5 -1
  44. package/src/core/selection/style/api/wrap-ordered-list.ts +5 -1
  45. package/src/core/selection/style/api/wrap-unwrapped-text.ts +1 -1
  46. package/src/core/selection/style/style.test.js +1 -1
  47. package/src/core/{view/panel.ts → traits/dlgs.ts} +17 -9
  48. package/src/core/traits/elms.ts +4 -8
  49. package/src/core/traits/index.ts +1 -0
  50. package/src/core/traits/mods.ts +17 -10
  51. package/src/core/ui/button/index.ts +1 -0
  52. package/src/{plugins → core/ui/button}/tooltip/README.md +0 -0
  53. package/src/{plugins → core/ui/button}/tooltip/tooltip.less +4 -4
  54. package/src/{plugins → core/ui/button}/tooltip/tooltip.test.js +3 -2
  55. package/src/core/ui/button/tooltip/tooltip.ts +132 -0
  56. package/src/core/ui/element.ts +5 -27
  57. package/src/core/ui/group/group.test.js +44 -0
  58. package/src/core/ui/group/group.ts +4 -4
  59. package/src/core/view/view-with-toolbar.ts +2 -2
  60. package/src/core/view/view.ts +11 -33
  61. package/src/jodit.ts +20 -8
  62. package/src/langs/ar.js +1 -1
  63. package/src/langs/cs_cz.js +1 -1
  64. package/src/langs/de.js +1 -1
  65. package/src/langs/es.js +1 -1
  66. package/src/langs/fa.js +1 -1
  67. package/src/langs/fr.js +1 -1
  68. package/src/langs/he.js +1 -1
  69. package/src/langs/hu.js +1 -1
  70. package/src/langs/i18n.test.js +170 -0
  71. package/src/langs/id.js +1 -1
  72. package/src/langs/it.js +1 -1
  73. package/src/langs/ja.js +1 -1
  74. package/src/langs/ko.js +1 -1
  75. package/src/langs/nl.js +1 -1
  76. package/src/langs/pl.js +1 -1
  77. package/src/langs/pt_br.js +1 -1
  78. package/src/langs/ru.js +1 -1
  79. package/src/langs/tr.js +1 -1
  80. package/src/langs/zh_cn.js +1 -1
  81. package/src/langs/zh_tw.js +1 -1
  82. package/src/modules/dialog/dialog.less +2 -0
  83. package/src/modules/dialog/dialog.ts +27 -50
  84. package/src/modules/file-browser/README.md +10 -10
  85. package/src/modules/file-browser/__image_snapshots__/file-browser-test-screenshot-js-filebrowser-screenshot-testing-open-filebrowser-works-1-snap.png +0 -0
  86. package/src/modules/file-browser/builders/context-menu.ts +1 -1
  87. package/src/modules/file-browser/file-browser.test.js +26 -13
  88. package/src/modules/file-browser/file-browser.test.screenshot.js +23 -0
  89. package/src/modules/file-browser/file-browser.ts +9 -5
  90. package/src/modules/history/snapshot.ts +12 -3
  91. package/src/modules/image-editor/__image_snapshots__/image-editor-test-screenshot-js-image-editor-screenshot-testing-open-image-editor-works-1-snap.png +0 -0
  92. package/src/modules/image-editor/image-editor.test.screenshot.js +25 -0
  93. package/src/modules/image-editor/image-editor.ts +7 -6
  94. package/src/modules/status-bar/status-bar.ts +5 -16
  95. package/src/modules/table/table.test.js +2 -1
  96. package/src/modules/toolbar/collection/collection.ts +6 -1
  97. package/src/modules/uploader/README.md +1 -1
  98. package/src/modules/uploader/config.ts +1 -1
  99. package/src/modules/uploader/uploader.test.js +96 -46
  100. package/src/plugins/about/about.ts +1 -1
  101. package/src/plugins/add-new-line/add-new-line.ts +5 -4
  102. package/src/plugins/backspace/backspace.test.js +33 -39
  103. package/src/plugins/backspace/backspace.ts +10 -4
  104. package/src/plugins/backspace/cases/check-remove-char.ts +36 -14
  105. package/src/plugins/backspace/cases/check-remove-unbreakable-element.ts +8 -0
  106. package/src/plugins/backspace/config.ts +1 -1
  107. package/src/plugins/backspace/interface.d.ts +1 -1
  108. package/src/plugins/clean-html/clean-html.test.js +240 -164
  109. package/src/plugins/clean-html/config.ts +10 -2
  110. package/src/plugins/clean-html/helpers/remove-format/remove-format-for-collapsed-selection.ts +3 -2
  111. package/src/plugins/clean-html/helpers/remove-format/remove-format-for-selection.ts +2 -2
  112. package/src/plugins/clean-html/helpers/visitor/filters/index.ts +1 -0
  113. package/src/plugins/clean-html/helpers/visitor/filters/remove-empty-text-node.ts +35 -0
  114. package/src/plugins/clean-html/helpers/visitor/filters/remove-inv-text-nodes.ts +2 -6
  115. package/src/plugins/clean-html/helpers/visitor/visit-node-walker.ts +5 -0
  116. package/src/plugins/debug/debug.ts +68 -0
  117. package/src/plugins/drag-and-drop/drag-and-drop.ts +0 -1
  118. package/src/plugins/drag-and-drop-element/drag-and-drop-element.test.js +37 -34
  119. package/src/plugins/dtd/README.md +52 -0
  120. package/{types/plugins/tooltip/tooltip.d.ts → src/plugins/dtd/after-insert/index.ts} +5 -4
  121. package/src/plugins/dtd/after-insert/remove-extra-br.ts +39 -0
  122. package/src/plugins/dtd/before-insert/check-block-nesting.ts +40 -0
  123. package/src/plugins/dtd/before-insert/index.ts +12 -0
  124. package/src/plugins/dtd/config.ts +67 -0
  125. package/src/plugins/dtd/dtd.test.js +128 -0
  126. package/src/plugins/dtd/dtd.ts +48 -0
  127. package/src/plugins/enter/enter.test.js +89 -193
  128. package/src/plugins/enter/enter.ts +14 -11
  129. package/src/plugins/enter/helpers/check-br.ts +11 -1
  130. package/src/plugins/enter/helpers/index.ts +1 -0
  131. package/src/plugins/enter/helpers/move-cursor-out-from-specal-tags.ts +32 -0
  132. package/src/plugins/enter/helpers/split-fragment.ts +1 -0
  133. package/src/plugins/fullsize/config.ts +1 -1
  134. package/src/plugins/fullsize/fullsize.test.js +77 -12
  135. package/src/plugins/fullsize/fullsize.ts +12 -1
  136. package/src/plugins/iframe/config.ts +1 -1
  137. package/src/plugins/image-properties/README.md +7 -0
  138. package/src/plugins/image-properties/image-properties.ts +1 -1
  139. package/src/plugins/index.ts +1 -1
  140. package/src/plugins/limit/limit.test.js +27 -0
  141. package/src/plugins/limit/limit.ts +4 -2
  142. package/src/plugins/line-height/line-height.svg +1 -1
  143. package/src/plugins/link/README.md +5 -0
  144. package/src/plugins/link/link.test.js +11 -12
  145. package/src/plugins/link/link.ts +1 -1
  146. package/src/plugins/mobile/mobile.ts +1 -1
  147. package/src/plugins/ordered-list/ordered-list.test.js +3 -14
  148. package/src/plugins/paste/config.ts +0 -7
  149. package/src/plugins/paste/paste.test.js +3 -3
  150. package/src/plugins/paste-storage/paste-storage.ts +1 -1
  151. package/src/plugins/preview/preview.ts +1 -1
  152. package/src/plugins/search/search.ts +1 -1
  153. package/src/plugins/select/config.ts +1 -1
  154. package/src/plugins/spellcheck/config.ts +1 -1
  155. package/src/plugins/symbols/symbols.test.js +5 -4
  156. package/src/plugins/table/config.ts +4 -17
  157. package/src/plugins/table/table.test.js +2 -2
  158. package/src/plugins/wrap-nodes/wrap-nodes.test.js +34 -5
  159. package/src/plugins/wrap-nodes/wrap-nodes.ts +59 -16
  160. package/src/styles/variables.less +1 -1
  161. package/src/types/ajax.d.ts +2 -2
  162. package/src/types/file-browser.d.ts +4 -2
  163. package/src/types/jodit.d.ts +3 -2
  164. package/src/types/plugin.d.ts +1 -0
  165. package/src/types/toolbar.d.ts +12 -6
  166. package/src/types/traits.d.ts +30 -1
  167. package/src/types/types.d.ts +1 -0
  168. package/src/types/view.d.ts +9 -34
  169. package/src/typings.d.ts +1 -0
  170. package/types/config.d.ts +3 -2
  171. package/types/core/constants.d.ts +7 -7
  172. package/types/core/decorators/derive/derive.d.ts +6 -0
  173. package/types/core/decorators/index.d.ts +1 -0
  174. package/types/core/dom/dom.d.ts +5 -4
  175. package/types/core/plugin/plugin-system.d.ts +4 -0
  176. package/types/core/traits/dlgs.d.ts +15 -0
  177. package/types/core/traits/elms.d.ts +2 -4
  178. package/types/core/traits/index.d.ts +1 -0
  179. package/types/core/traits/mods.d.ts +5 -8
  180. package/types/core/ui/button/index.d.ts +1 -0
  181. package/types/core/ui/button/tooltip/tooltip.d.ts +29 -0
  182. package/types/core/ui/element.d.ts +3 -9
  183. package/types/core/ui/group/group.d.ts +2 -2
  184. package/types/core/view/view-with-toolbar.d.ts +2 -2
  185. package/types/core/view/view.d.ts +5 -10
  186. package/types/jodit.d.ts +7 -4
  187. package/types/modules/dialog/dialog.d.ts +8 -10
  188. package/types/modules/file-browser/file-browser.d.ts +5 -2
  189. package/types/modules/history/snapshot.d.ts +3 -2
  190. package/types/modules/image-editor/image-editor.d.ts +4 -4
  191. package/types/modules/status-bar/status-bar.d.ts +3 -4
  192. package/types/modules/toolbar/collection/collection.d.ts +1 -0
  193. package/types/plugins/clean-html/config.d.ts +7 -1
  194. package/types/plugins/clean-html/helpers/visitor/filters/index.d.ts +1 -0
  195. package/types/plugins/clean-html/helpers/visitor/filters/remove-empty-text-node.d.ts +13 -0
  196. package/types/plugins/dtd/after-insert/index.d.ts +10 -0
  197. package/types/plugins/dtd/after-insert/remove-extra-br.d.ts +16 -0
  198. package/types/plugins/dtd/before-insert/check-block-nesting.d.ts +16 -0
  199. package/types/plugins/dtd/before-insert/index.d.ts +10 -0
  200. package/types/plugins/dtd/config.d.ts +27 -0
  201. package/types/plugins/dtd/dtd.d.ts +6 -0
  202. package/types/plugins/enter/helpers/index.d.ts +1 -0
  203. package/types/plugins/enter/helpers/move-cursor-out-from-specal-tags.d.ts +13 -0
  204. package/types/plugins/iframe/config.d.ts +1 -1
  205. package/types/plugins/index.d.ts +1 -1
  206. package/types/plugins/paste/config.d.ts +0 -4
  207. package/types/plugins/spellcheck/config.d.ts +1 -1
  208. package/types/types/ajax.d.ts +2 -2
  209. package/types/types/file-browser.d.ts +4 -2
  210. package/types/types/jodit.d.ts +3 -2
  211. package/types/types/plugin.d.ts +1 -0
  212. package/types/types/toolbar.d.ts +12 -6
  213. package/types/types/traits.d.ts +30 -1
  214. package/types/types/types.d.ts +1 -0
  215. package/types/types/view.d.ts +9 -34
  216. package/src/plugins/tooltip/tooltip.ts +0 -114
  217. package/types/core/view/panel.d.ts +0 -13
@@ -16,3 +16,4 @@ export * from './has-previous-block';
16
16
  export * from './insert-paragraph';
17
17
  export * from './split-fragment';
18
18
  export * from './wrap-text';
19
+ export * from './move-cursor-out-from-specal-tags';
@@ -0,0 +1,32 @@
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/enter
9
+ */
10
+
11
+ import type { IJodit, Nullable, HTMLTagNames } from 'jodit/types';
12
+ import { Dom } from 'jodit/core/dom/dom';
13
+
14
+ /**
15
+ * Checks if the cursor is on the edge of a special tag and exits if so
16
+ */
17
+ export function moveCursorOutFromSpecialTags(
18
+ jodit: IJodit,
19
+ current: Nullable<Node>,
20
+ tags: HTMLTagNames[]
21
+ ): void {
22
+ const { s } = jodit;
23
+
24
+ const link = Dom.closest(current, tags, jodit.editor);
25
+ if (link) {
26
+ if (s.cursorOnTheRight(link)) {
27
+ s.setCursorAfter(link);
28
+ } else if (s.cursorOnTheLeft(link)) {
29
+ s.setCursorBefore(link);
30
+ }
31
+ }
32
+ }
@@ -49,5 +49,6 @@ export function splitFragment(jodit: IJodit, currentBox: HTMLElement): void {
49
49
  }
50
50
 
51
51
  const newP = sel.splitSelection(currentBox);
52
+
52
53
  scrollIntoViewIfNeeded(newP, jodit.editor, jodit.ed);
53
54
  }
@@ -67,7 +67,7 @@ Config.prototype.controls.fullsize = {
67
67
  }
68
68
  },
69
69
 
70
- tooltip: 'Open editor in fullsize',
70
+ tooltip: 'Open in fullsize',
71
71
 
72
72
  mode: consts.MODE_SOURCE + consts.MODE_WYSIWYG
73
73
  } as IControlType;
@@ -6,29 +6,94 @@
6
6
 
7
7
  describe('Fullsize plugin', function () {
8
8
  describe('Toggle fullsize', function () {
9
- it('Should resize all boxes to first state', function () {
9
+ it('Should resize all boxes to first state', () => {
10
10
  const editor = getJodit({
11
11
  history: {
12
12
  timeout: 0
13
13
  }
14
14
  });
15
- const chacksizes = ['container', 'workplace', 'editor'];
16
- const sizes = chacksizes.map(function (key) {
17
- return editor[key].offsetHeight;
18
- }),
19
- equal = function (a, b) {
20
- return Math.abs(a - b) <= 2;
21
- };
15
+
16
+ const checkSizes = ['container', 'workplace', 'editor'];
17
+
18
+ const initialSizes = checkSizes.map(
19
+ key => editor[key].offsetHeight
20
+ ),
21
+ equal = (a, b) => Math.abs(a - b) <= 2;
22
22
 
23
23
  editor.toggleFullSize(true);
24
- chacksizes.map(function (key, index) {
25
- expect(equal(editor[key].offsetHeight, sizes[index])).is.false;
24
+ checkSizes.map((key, index) => {
25
+ expect(equal(editor[key].offsetHeight, initialSizes[index])).is
26
+ .false;
26
27
  });
27
28
 
28
29
  editor.toggleFullSize(false);
29
30
 
30
- chacksizes.map(function (key, index) {
31
- expect(equal(editor[key].offsetHeight, sizes[index])).is.true;
31
+ checkSizes.map(function (key, index) {
32
+ expect(
33
+ equal(editor[key].offsetHeight, initialSizes[index])
34
+ ).is.true;
35
+ });
36
+ });
37
+
38
+ function checkAllParents(editor, enabled) {
39
+ let parent = editor.container.parentNode;
40
+
41
+ while (parent && parent.nodeType === Node.ELEMENT_NODE) {
42
+ expect(
43
+ parent.classList.contains('jodit_fullsize-box_true')
44
+ ).equals(enabled);
45
+ parent = parent.parentNode;
46
+ }
47
+ }
48
+
49
+ describe('globalFullSize', () => {
50
+ describe('set fullsize', () => {
51
+ it('Should set special class for all parents', () => {
52
+ const editor = getJodit();
53
+ editor.toggleFullSize(true);
54
+ checkAllParents(editor, true);
55
+ });
56
+ });
57
+
58
+ describe('remove fullsize', () => {
59
+ it('Should remove special class for all parents', () => {
60
+ const editor = getJodit();
61
+ editor.toggleFullSize(true);
62
+ editor.toggleFullSize(false);
63
+ checkAllParents(editor, false);
64
+ });
65
+
66
+ describe('Several fullsize blocks', () => {
67
+ it('Should remove special class for all parents only for latest block', () => {
68
+ const editor = getJodit();
69
+ editor.toggleFullSize(true);
70
+ const dialog = editor.dlg();
71
+ dialog.open('test');
72
+ dialog.toggleFullSize(true);
73
+
74
+ checkAllParents(editor, true);
75
+
76
+ dialog.toggleFullSize(false);
77
+ checkAllParents(editor, true);
78
+
79
+ editor.toggleFullSize(false);
80
+ checkAllParents(editor, false);
81
+ });
82
+ });
83
+
84
+ describe('Close dialog', () => {
85
+ it('Should work same way', () => {
86
+ const editor = getJodit();
87
+ const dialog = editor.dlg();
88
+ dialog.open('test');
89
+ dialog.toggleFullSize(true);
90
+
91
+ checkAllParents(dialog, true);
92
+
93
+ dialog.close();
94
+ checkAllParents(dialog, false);
95
+ });
96
+ });
32
97
  });
33
98
  });
34
99
  });
@@ -19,6 +19,8 @@ import { pluginSystem } from 'jodit/core/global';
19
19
 
20
20
  import './config';
21
21
 
22
+ const fullsizeStack = new Set();
23
+
22
24
  /**
23
25
  * Process `toggleFullSize` event, and behavior - set/unset fullsize mode
24
26
  */
@@ -84,7 +86,16 @@ export function fullsize(editor: IViewWithToolbar): void {
84
86
  css(editor.toolbar.container, 'width', 'auto');
85
87
  }
86
88
 
87
- if (editor.o.globalFullSize) {
89
+ enable
90
+ ? fullsizeStack.add(container)
91
+ : fullsizeStack.delete(container);
92
+
93
+ const shouldToggleGlobalFullsize =
94
+ editor.o.globalFullSize &&
95
+ ((fullsizeStack.size === 1 && enable) ||
96
+ (fullsizeStack.size === 0 && !enable));
97
+
98
+ if (shouldToggleGlobalFullsize) {
88
99
  let node = container.parentNode as HTMLElement;
89
100
 
90
101
  while (
@@ -26,7 +26,7 @@ declare module 'jodit/config' {
26
26
  iframeDefaultSrc: string;
27
27
 
28
28
  /**
29
- * Base URL where the root directory for {@link Jodit.defaultOptions.iframe|iframe} mode
29
+ * Base URL where the root directory for [[Config.iframe]] mode
30
30
  *
31
31
  * @example
32
32
  * ```javascript
@@ -1,3 +1,10 @@
1
1
  # Image properties dialog
2
2
 
3
3
  After double-clicking on a photo in the editor, it opens the photo editing dialog.
4
+
5
+ ## Known Issues
6
+
7
+ - When opening an editor in a [mui](https://mui.com/material-ui/api/modal) dialog box and opening the image dialog box in it,
8
+ the mui dialog does not allow focus to be passed out. As a result, no field inside image properties can be focused.
9
+ Just enable the [disableEnforceFocus](https://mui.com/material-ui/api/modal/#props) option.
10
+ [Image properties - Input fields are not clickable ( react + material ui ) #879](https://github.com/xdan/jodit/issues/879)
@@ -185,7 +185,7 @@ export class imageProperties extends Plugin {
185
185
  return;
186
186
  }
187
187
 
188
- this.dialog = this.j.dialog({
188
+ this.dialog = this.j.dlg({
189
189
  minWidth: Math.min(400, screen.width),
190
190
  minHeight: 590,
191
191
  buttons: ['fullsize', 'dialog.close']
@@ -67,7 +67,7 @@ import 'jodit/plugins/symbols/symbols';
67
67
  import 'jodit/plugins/tab/tab';
68
68
  import 'jodit/plugins/table/table';
69
69
  import 'jodit/plugins/table-keyboard-navigation/table-keyboard-navigation';
70
- import 'jodit/plugins/tooltip/tooltip';
71
70
  import 'jodit/plugins/video/video';
72
71
  import 'jodit/plugins/wrap-nodes/wrap-nodes';
72
+ import 'jodit/plugins/dtd/dtd';
73
73
  import 'jodit/plugins/xpath/xpath';
@@ -23,6 +23,33 @@ describe('Limit plugin', function () {
23
23
  }, 200);
24
24
  });
25
25
 
26
+ describe('For special keys (ctrl + c etc.)', function () {
27
+ it('should allow press them', done => {
28
+ const editor = getJodit({
29
+ limitChars: 5
30
+ });
31
+
32
+ editor.value = '<p>11111</p>';
33
+ setCursorToChar(editor);
34
+
35
+ editor.e.on('keyup.limit', e => {
36
+ setTimeout(() => {
37
+ try {
38
+ expect(e.ctrlKey).is.true;
39
+ expect(e.defaultPrevented).is.false;
40
+ done();
41
+ } catch (e) {
42
+ done(e);
43
+ }
44
+ });
45
+ });
46
+
47
+ simulateEvent('keyup', 'c', editor, opts => {
48
+ opts.ctrlKey = true;
49
+ });
50
+ });
51
+ });
52
+
26
53
  describe('Stat plugin', function () {
27
54
  it('should show chars count', function (done) {
28
55
  const editor = getJodit({
@@ -33,7 +33,6 @@ export class limit extends Plugin {
33
33
 
34
34
  if (jodit && (limitWords || limitChars)) {
35
35
  let snapshot: SnapshotType | null = null;
36
-
37
36
  jodit.e
38
37
  .off('.limit')
39
38
  .on('beforePaste.limit', () => {
@@ -60,7 +59,10 @@ export class limit extends Plugin {
60
59
  event: KeyboardEvent | null = null,
61
60
  inputText: string = ''
62
61
  ): boolean {
63
- if (event && COMMAND_KEYS.includes(event.key)) {
62
+ if (
63
+ event &&
64
+ (COMMAND_KEYS.includes(event.key) || event.ctrlKey || event.metaKey)
65
+ ) {
64
66
  return false;
65
67
  }
66
68
 
@@ -1,4 +1,4 @@
1
- <svg fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
1
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
2
2
  <path
3
3
  d="M5.09668 6.99707H7.17358L4.17358 3.99707L1.17358 6.99707H3.09668V17.0031H1.15881L4.15881 20.0031L7.15881 17.0031H5.09668V6.99707Z"/>
4
4
  <path d="M22.8412 7H8.84119V5H22.8412V7Z"/>
@@ -61,4 +61,9 @@ Jodit.make('#editor', {
61
61
  });
62
62
  ```
63
63
 
64
+ ## Known Issues
64
65
 
66
+ - When opening an editor in a [mui](https://mui.com/material-ui/api/modal) dialog box and opening the link popup in it,
67
+ the mui dialog does not allow focus to be passed out. As a result, no field inside form can be focused.
68
+ Just enable the [disableEnforceFocus](https://mui.com/material-ui/api/modal/#props) option.
69
+ [Image properties - Input fields are not clickable ( react + material ui ) #879](https://github.com/xdan/jodit/issues/879)
@@ -540,7 +540,8 @@ describe('Link plugin', function () {
540
540
  }
541
541
  });
542
542
 
543
- editor.value = '';
543
+ editor.value = '<p>|<br></p>';
544
+ setCursorToChar(editor);
544
545
 
545
546
  clickButton('link', editor);
546
547
 
@@ -570,13 +571,13 @@ describe('Link plugin', function () {
570
571
 
571
572
  url.focus();
572
573
  url.value = 'tests/artio.jpg';
573
- simulateEvent('submit', 0, list.querySelector('form'));
574
+ simulateEvent('submit', list.querySelector('form'));
574
575
 
575
576
  expect(sortAttributes(editor.value)).equals(
576
577
  '<p><a href="tests/artio.jpg">123</a></p>'
577
578
  );
578
579
 
579
- simulateEvent('mousedown', 0, editor.editor);
580
+ simulateEvent('mousedown', editor.editor);
580
581
 
581
582
  expect(list.parentNode).is.null;
582
583
  });
@@ -584,22 +585,20 @@ describe('Link plugin', function () {
584
585
  it('Should fire change event', function () {
585
586
  let change = 0;
586
587
 
587
- const editor = getJodit({
588
- events: {
589
- change: function () {
590
- change += 1;
591
- }
592
- }
593
- });
588
+ const editor = getJodit();
594
589
 
595
- editor.value = '';
590
+ editor.value = '<p>|<br></p>';
591
+ setCursorToChar(editor);
592
+ editor.events.on('change', function () {
593
+ change += 1;
594
+ });
596
595
 
597
596
  clickButton('link', editor);
598
597
 
599
598
  const list = getOpenedPopup(editor);
600
599
  const url = list.querySelector('input[ref=url_input]');
601
600
  url.value = 'tests/artio.jpg';
602
- simulateEvent('submit', 0, list.querySelector('form'));
601
+ simulateEvent('submit', list.querySelector('form'));
603
602
 
604
603
  expect(sortAttributes(editor.value)).equals(
605
604
  '<p><a href="tests/artio.jpg">tests/artio.jpg</a></p>'
@@ -53,7 +53,7 @@ export class link extends Plugin {
53
53
 
54
54
  jodit.registerCommand('openLinkDialog', {
55
55
  exec: () => {
56
- const dialog = jodit.dialog({
56
+ const dialog = jodit.dlg({
57
57
  resizable: false
58
58
  });
59
59
 
@@ -77,7 +77,7 @@ export function mobile(editor: IJodit): void {
77
77
  ).offsetWidth;
78
78
 
79
79
  const newStore = ((): ReturnType<typeof splitArray> => {
80
- if (width >= editor.o.sizeLG) {
80
+ if (editor.isFullSize || width >= editor.o.sizeLG) {
81
81
  return splitArray(editor.o.buttons);
82
82
  }
83
83
 
@@ -22,26 +22,15 @@ describe('Test orderedList plugin', function () {
22
22
 
23
23
  it('If press Enter inside <li> in the end it should create new <li> and cursor must be in it', function () {
24
24
  const editor = getJodit();
25
- editor.value = '<ul><li>test</li></ul>';
26
-
27
- const sel = editor.s.sel,
28
- range = editor.s.createRange();
29
-
30
- range.setStart(
31
- editor.editor.firstChild.firstChild.firstChild,
32
- 4
33
- );
34
- range.collapse(true);
35
-
36
- sel.removeAllRanges();
37
- sel.addRange(range);
25
+ editor.value = '<ul><li>test|</li></ul>';
26
+ setCursorToChar(editor);
38
27
 
39
28
  simulateEvent('keydown', Jodit.KEY_ENTER, editor.editor);
40
29
 
41
30
  editor.s.insertNode(editor.createInside.text(' a '));
42
31
 
43
32
  expect(editor.value).equals(
44
- '<ul><li>test</li><li> a <br></li></ul>'
33
+ '<ul><li>test</li><li> a </li></ul>'
45
34
  );
46
35
  });
47
36
 
@@ -43,11 +43,6 @@ declare module 'jodit/config' {
43
43
  */
44
44
  nl2brInPlainText: boolean;
45
45
 
46
- /**
47
- * Draggable elements
48
- */
49
- draggableTags: string | string[];
50
-
51
46
  /**
52
47
  * Options when inserting HTML string
53
48
  */
@@ -68,8 +63,6 @@ Config.prototype.memorizeChoiceWhenPasteFragment = false;
68
63
 
69
64
  Config.prototype.nl2brInPlainText = true;
70
65
 
71
- Config.prototype.draggableTags = ['img', 'jodit-media', 'jodit'];
72
-
73
66
  const psKey = 'pasteStorage';
74
67
 
75
68
  Config.prototype.controls.paste = {
@@ -1050,7 +1050,7 @@ describe('Test paste plugin', () => {
1050
1050
  };
1051
1051
  };
1052
1052
 
1053
- simulateEvent('paste', 0, editor.editor, emulatePasteEvent);
1053
+ simulateEvent('paste', editor.editor, emulatePasteEvent);
1054
1054
 
1055
1055
  expect(editor.value).equals('<p>test</p>');
1056
1056
 
@@ -1077,7 +1077,7 @@ describe('Test paste plugin', () => {
1077
1077
  });
1078
1078
 
1079
1079
  expect(editor.value).equals(
1080
- '<p>test</p><br><p>test</p><br><p>test</p>'
1080
+ '<p>test<br>test<br>test<br></p>'
1081
1081
  );
1082
1082
  });
1083
1083
  });
@@ -1255,7 +1255,7 @@ describe('Test paste plugin', () => {
1255
1255
  simulateEvent('paste', editor.editor, emulatePasteEvent);
1256
1256
 
1257
1257
  expect(editor.value).equals(
1258
- '<p>test</p><br><p>test</p><br><p>test</p><br><p>test</p><br><p>test</p><br>'
1258
+ '<p>test<br>test<br>test<br>test<br>test<br><br></p>'
1259
1259
  );
1260
1260
  });
1261
1261
  });
@@ -144,7 +144,7 @@ export class pasteStorage extends Plugin {
144
144
  };
145
145
 
146
146
  private createDialog(): void {
147
- this.dialog = this.j.dialog();
147
+ this.dialog = this.j.dlg();
148
148
 
149
149
  const pasteButton = Button(this.j, 'paste', 'Paste', 'primary');
150
150
 
@@ -33,7 +33,7 @@ export function preview(editor: IJodit): void {
33
33
  editor.registerCommand(
34
34
  'preview',
35
35
  (_: any, _1: any, defaultValue: string) => {
36
- const dialog = editor.dialog();
36
+ const dialog = editor.dlg();
37
37
 
38
38
  dialog
39
39
  .setSize(1024, 600)
@@ -144,7 +144,7 @@ export class search extends Plugin {
144
144
 
145
145
  const textNode = this.j.createInside.text(this.ui.replace);
146
146
 
147
- rng.insertNode(textNode);
147
+ Dom.safeInsertNode(rng, textNode);
148
148
  this.j.s.select(textNode);
149
149
  this.tryScrollToElement(textNode);
150
150
  this.cache = {};
@@ -27,5 +27,5 @@ declare module 'jodit/config' {
27
27
  }
28
28
 
29
29
  Config.prototype.select = {
30
- normalizeSelectionBeforeCutAndCopy: true
30
+ normalizeSelectionBeforeCutAndCopy: false
31
31
  };
@@ -16,7 +16,7 @@ declare module 'jodit/config' {
16
16
  interface Config {
17
17
  /**
18
18
  * Options specifies whether the editor is to have its spelling and grammar checked or not
19
- * @see {@link http://www.w3schools.com/tags/att_global_spellcheck.asp}
19
+ * @see http://www.w3schools.com/tags/att_global_spellcheck.asp
20
20
  */
21
21
  spellcheck: boolean;
22
22
  }
@@ -214,7 +214,8 @@ describe('Symbols plugin', function () {
214
214
  buttons: 'symbols'
215
215
  });
216
216
 
217
- editor.value = '';
217
+ editor.value = '<p>test|</p>';
218
+ setCursorToChar(editor);
218
219
 
219
220
  const btn = getButton('symbols', editor);
220
221
 
@@ -227,7 +228,7 @@ describe('Symbols plugin', function () {
227
228
 
228
229
  simulateEvent('keydown', Jodit.KEY_ENTER, currentActive);
229
230
 
230
- expect(editor.value).equals('<p>&amp;</p>');
231
+ expect(editor.value).equals('<p>test&amp;</p>');
231
232
 
232
233
  simulateEvent('click', btn); // close previous
233
234
  simulateEvent('click', btn);
@@ -237,9 +238,9 @@ describe('Symbols plugin', function () {
237
238
 
238
239
  const currentActive2 = dialog.getElementsByTagName('a')[125];
239
240
 
240
- simulateEvent('mousedown', 0, currentActive2);
241
+ simulateEvent('mousedown', currentActive2);
241
242
 
242
- expect(editor.value).equals('<p>&amp;½</p>');
243
+ expect(editor.value).equals('<p>test&amp;½</p>');
243
244
  });
244
245
  });
245
246
  });
@@ -180,22 +180,6 @@ Config.prototype.controls.table = {
180
180
  tbody.appendChild(tr);
181
181
  }
182
182
 
183
- const crnt = editor.s.current();
184
-
185
- if (crnt && editor.s.isCollapsed()) {
186
- const block = Dom.closest(crnt, Dom.isBlock, editor.editor);
187
-
188
- if (
189
- block &&
190
- block !== editor.editor &&
191
- !block.nodeName.match(
192
- /^TD|TH|TBODY|TABLE|THEADER|TFOOTER$/
193
- )
194
- ) {
195
- editor.s.setCursorAfter(block);
196
- }
197
- }
198
-
199
183
  $$('input[type=checkbox]:checked', options).forEach(
200
184
  (input: HTMLElement) => {
201
185
  (input as HTMLInputElement).value
@@ -206,7 +190,10 @@ Config.prototype.controls.table = {
206
190
  }
207
191
  );
208
192
 
209
- editor.s.insertNode(crt.text('\n'));
193
+ if (editor.editor.firstChild) {
194
+ editor.s.insertNode(crt.text('\n'), false, false);
195
+ }
196
+
210
197
  editor.s.insertNode(table, false);
211
198
 
212
199
  if (first_td) {
@@ -15,7 +15,7 @@ describe('Test table plugin', () => {
15
15
  popup.querySelector('span[data-index="6"]')
16
16
  );
17
17
  expect(sortAttributes(editor.value)).eq(
18
- '\n<table style="border-collapse:collapse;width:100%"><tbody>\n<tr>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td></tr></tbody></table>'
18
+ '<table style="border-collapse:collapse;width:100%"><tbody>\n<tr>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td>\n\t<td style="width:14.28%"><br></td></tr></tbody></table>'
19
19
  );
20
20
  });
21
21
  });
@@ -36,7 +36,7 @@ describe('Test table plugin', () => {
36
36
  popup.querySelector('span[data-index="2"]')
37
37
  );
38
38
  expect(sortAttributes(editor.value)).eq(
39
- '\n<table style="border-collapse:collapse;width:100%"><tbody>\n<tr>\n\t<td style="color:red;width:33.33%"><br></td>\n\t<td style="color:red;width:33.33%"><br></td>\n\t<td style="color:red;width:33.33%"><br></td></tr></tbody></table>'
39
+ '<table style="border-collapse:collapse;width:100%"><tbody>\n<tr>\n\t<td style="color:red;width:33.33%"><br></td>\n\t<td style="color:red;width:33.33%"><br></td>\n\t<td style="color:red;width:33.33%"><br></td></tr></tbody></table>'
40
40
  );
41
41
  });
42
42
  });
@@ -12,10 +12,39 @@ describe('WrapNodes plugin test', function () {
12
12
  expect(editor.value).equals('<p>test</p>');
13
13
  });
14
14
 
15
- it('Should wrap alone LI element', function () {
16
- const editor = getJodit();
17
- editor.value = '<li>test</li>';
18
- expect(editor.value).equals('<ul><li>test</li></ul>');
15
+ describe('Use Japanese keyboard', function () {
16
+ it('Should right wrap text', async function () {
17
+ const editor = getJodit({
18
+ language: 'ja'
19
+ });
20
+ editor.value = '';
21
+
22
+ editor.s.insertNode(editor.createInside.text('た'));
23
+ await editor.async.requestIdlePromise();
24
+ editor.s.insertNode(editor.createInside.text('て'));
25
+ await editor.async.requestIdlePromise();
26
+ editor.s.insertNode(editor.createInside.text('い'));
27
+ await editor.async.requestIdlePromise();
28
+
29
+ expect(editor.value).equals('<p>たてい</p>');
30
+ });
31
+ });
32
+
33
+ describe('Wrap leafs', function () {
34
+ it('Should wrap alone LI element', function () {
35
+ const editor = getJodit();
36
+ editor.value = '<li>test</li>';
37
+ expect(editor.value).equals('<ul><li>test</li></ul>');
38
+ });
39
+
40
+ it('Should wrap several LI elements', function () {
41
+ const editor = getJodit();
42
+ editor.value =
43
+ '<li>test</li><li>test</li><p>test</p>test<li>test</li> <li>test</li>s<li>test</li>';
44
+ expect(editor.value).equals(
45
+ '<ul><li>test</li><li>test</li></ul><p>test</p><p>test</p><ul><li>test</li><li>test</li></ul> <p>s</p><ul><li>test</li></ul>'
46
+ );
47
+ });
19
48
  });
20
49
 
21
50
  describe('For STYLE/SCRIPT elements', function () {
@@ -114,7 +143,7 @@ describe('WrapNodes plugin test', function () {
114
143
  expect(editor.value).equals('<p>test</p>');
115
144
  expect(editor.history.length).equals(1);
116
145
  editor.history.undo();
117
- expect(editor.value).equals('');
146
+ expect(editor.value).equals('<p><br></p>');
118
147
  });
119
148
  });
120
149