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
@@ -12,24 +12,25 @@ describe('Drag and drop element inside Editor', function () {
12
12
  return item.split('|');
13
13
  })
14
14
  .forEach(function (events) {
15
+ const defaultValue =
16
+ '<p style="height: 24px;">1111</p>' +
17
+ '<p style="height: 24px;">2222</p>' +
18
+ '<p><img style="width: 100px;height: 100px;" src="tests/artio.jpg" alt=""/></p>' +
19
+ '<p style="height: 24px;">3333</p>' +
20
+ '<p style="height: 24px;">4444</p>';
15
21
  describe(
16
22
  events[0] + ' and move image inside the editor',
17
23
  function () {
18
24
  it('Should ' + events[1] + ' dom element', function () {
19
- const editor = getJodit();
20
- editor.value =
21
- '<p>1111</p>' +
22
- '<p>2222</p>' +
23
- '<img style="width: 100px" src="https://xdsoft.net/jodit/files/artio.jpg" alt="">' +
24
- '<p>3333</p>' +
25
- '<p>4444</p>';
25
+ const editor = getJodit({ disablePlugins: ['sticky'] });
26
+ editor.value = defaultValue;
26
27
 
27
28
  simulateEvent(
28
29
  events[0],
29
30
  editor.editor.getElementsByTagName('img')[0]
30
31
  );
31
32
 
32
- window.scrollTo(0, 1000000);
33
+ editor.editor.scrollIntoView();
33
34
 
34
35
  const box = position(
35
36
  editor.editor.querySelectorAll('p')[1],
@@ -47,35 +48,36 @@ describe('Drag and drop element inside Editor', function () {
47
48
  });
48
49
 
49
50
  const result =
50
- '<p>1111</p>' +
51
- '<p>22<img alt="" src="https://xdsoft.net/jodit/files/artio.jpg" style="width:100px">22</p>' +
52
- '<p>3333</p>' +
53
- '<p>4444</p>';
54
-
55
- expect(
56
- sortAttributes(editor.value).replace(/2+/g, '2')
57
- ).equals(result.replace(/2+/g, '2'));
51
+ '<p style="height:24px">1111</p>' +
52
+ '<p style="height:24px">22<img alt="" src="tests/artio.jpg" style="height:100px;width:100px">22</p>' +
53
+ '<p style="height:24px">3333</p>' +
54
+ '<p style="height:24px">4444</p>';
55
+
56
+ try {
57
+ expect(sortAttributes(editor.value)).equals(result);
58
+ } catch (e) {
59
+ drawElement(editor.editor);
60
+ throw e;
61
+ }
58
62
  });
59
63
  }
60
64
  );
61
65
 
62
66
  describe(events[1] + ' image inside anchor', function () {
63
67
  it('Should ' + events[1] + ' anchor with image', function () {
64
- const editor = getJodit();
68
+ const editor = getJodit({ disablePlugins: ['sticky'] });
65
69
 
66
- editor.value =
67
- '<p>1111</p>' +
68
- '<p>2222</p>' +
69
- '<a href="#test"><img style="width: 100px" src="https://xdsoft.net/jodit/files/artio.jpg" alt=""></a>' +
70
- '<p>3333</p>' +
71
- '<p>4444</p>';
70
+ editor.value = defaultValue.replace(
71
+ /(<img[^>]+>)/,
72
+ '<a href="#test">$1</a>'
73
+ );
72
74
 
73
75
  simulateEvent(
74
76
  events[0],
75
77
  editor.editor.getElementsByTagName('img')[0]
76
78
  );
77
79
 
78
- window.scrollTo(0, 1000000);
80
+ editor.editor.scrollIntoView();
79
81
 
80
82
  const box = position(
81
83
  editor.editor.querySelectorAll('p')[1],
@@ -88,22 +90,22 @@ describe('Drag and drop element inside Editor', function () {
88
90
  });
89
91
 
90
92
  simulateEvent(events[2], editor.editor, function (options) {
91
- options.clientX = box.left + 20;
93
+ options.clientX = box.left + 15;
92
94
  options.clientY = box.top + 5;
93
95
  });
94
96
 
95
- expect(editor.value.replace(/2+/g, '2')).equals(
96
- '<p>1111</p><p>22<a href="#test"><img style="width: 100px" src="https://xdsoft.net/jodit/files/artio.jpg" alt=""></a>22</p><p>3333</p><p>4444</p>'.replace(
97
- /2+/g,
98
- '2'
99
- )
97
+ expect(sortAttributes(editor.value)).equals(
98
+ '<p style="height:24px">1111</p>' +
99
+ '<p style="height:24px">22<a href="#test"><img alt="" src="tests/artio.jpg" style="height:100px;width:100px"></a>22</p>' +
100
+ '<p style="height:24px">3333</p>' +
101
+ '<p style="height:24px">4444</p>'
100
102
  );
101
103
  });
102
104
  });
103
105
 
104
106
  describe(events[1] + ' image inside table cell', function () {
105
107
  it('Should move only image', function () {
106
- const editor = getJodit();
108
+ const editor = getJodit({ disablePlugins: ['sticky'] });
107
109
 
108
110
  editor.value = `<table>
109
111
  <tbody>
@@ -119,7 +121,7 @@ describe('Drag and drop element inside Editor', function () {
119
121
  editor.editor.getElementsByTagName('img')[0]
120
122
  );
121
123
 
122
- window.scrollTo(0, 1000000);
124
+ editor.editor.scrollIntoView();
123
125
 
124
126
  const box = position(
125
127
  editor.editor.querySelectorAll('td')[1],
@@ -132,7 +134,7 @@ describe('Drag and drop element inside Editor', function () {
132
134
  });
133
135
 
134
136
  simulateEvent(events[2], editor.editor, function (options) {
135
- options.clientX = box.left + 20;
137
+ options.clientX = box.left + 15;
136
138
  options.clientY = box.top + 5;
137
139
  });
138
140
 
@@ -147,6 +149,7 @@ describe('Drag and drop element inside Editor', function () {
147
149
  describe('Disable dragging', function () {
148
150
  it('Should not move image', function () {
149
151
  const editor = getJodit({
152
+ disablePlugins: ['sticky'],
150
153
  draggableTags: []
151
154
  });
152
155
 
@@ -175,7 +178,7 @@ describe('Drag and drop element inside Editor', function () {
175
178
  });
176
179
 
177
180
  simulateEvent(events[2], editor.editor, function (options) {
178
- options.clientX = box.left + 20;
181
+ options.clientX = box.left + 15;
179
182
  options.clientY = box.top + 5;
180
183
  });
181
184
 
@@ -0,0 +1,52 @@
1
+ # Responsible for HTML compliance with Document Type Definition standards
2
+
3
+ For example, a TABLE block element cannot be nested inside a P block element.
4
+
5
+ ```js
6
+ Jodit.make('#editor', {
7
+ dtd: {
8
+ /**
9
+ * Remove extra br element inside block element after pasting
10
+ */
11
+ removeExtraBr: true,
12
+
13
+ /**
14
+ * Check when inserting a block element if it can be inside another block element (according `blockLimits`)
15
+ */
16
+ checkBlockNesting: true,
17
+
18
+ /**
19
+ * List of elements that contain other blocks
20
+ */
21
+ blockLimits: {
22
+ article: 1,
23
+ aside: 1,
24
+ audio: 1,
25
+ body: 1,
26
+ caption: 1,
27
+ details: 1,
28
+ dir: 1,
29
+ div: 1,
30
+ dl: 1,
31
+ fieldset: 1,
32
+ figcaption: 1,
33
+ figure: 1,
34
+ footer: 1,
35
+ form: 1,
36
+ header: 1,
37
+ hgroup: 1,
38
+ main: 1,
39
+ menu: 1,
40
+ nav: 1,
41
+ ol: 1,
42
+ section: 1,
43
+ table: 1,
44
+ td: 1,
45
+ th: 1,
46
+ tr: 1,
47
+ ul: 1,
48
+ video: 1
49
+ }
50
+ }
51
+ });
52
+ ```
@@ -3,9 +3,10 @@
3
3
  * Released under MIT see LICENSE.txt in the project root for license information.
4
4
  * Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
5
  */
6
+
6
7
  /**
7
- * [[include:plugins/tooltip/README.md]]
8
- * @packageDocumentation
9
- * @module plugins/tooltip
8
+ * @module plugins/dtd
9
+ * @internal
10
10
  */
11
- import './tooltip.less';
11
+
12
+ export * from './remove-extra-br';
@@ -0,0 +1,39 @@
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/dtd
9
+ * @internal
10
+ */
11
+
12
+ import type { IJodit } from 'jodit/types';
13
+ import { Dom } from 'jodit/core/dom/dom';
14
+
15
+ /**
16
+ * Checks if there is a tag in the block element after the inserted br node,
17
+ * if so, removes it
18
+ * @internal
19
+ */
20
+ export function removeExtraBr(jodit: IJodit, node: Node): void {
21
+ if (!jodit.o.dtd.removeExtraBr || Dom.isTag(node, 'br')) {
22
+ return;
23
+ }
24
+
25
+ const parent = Dom.furthest(node, Dom.isBlock, jodit.editor);
26
+
27
+ if (parent && !Dom.isTag(parent, ['table', 'pre', 'blockquote', 'code'])) {
28
+ const br = Dom.isTag(node, 'br')
29
+ ? node
30
+ : Dom.findNotEmptySibling(node, false);
31
+
32
+ if (!Dom.isTag(br, 'br')) {
33
+ return;
34
+ }
35
+
36
+ jodit.s.setCursorBefore(br);
37
+ Dom.safeRemove(br);
38
+ }
39
+ }
@@ -0,0 +1,40 @@
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/dtd
9
+ * @internal
10
+ */
11
+
12
+ import type { IJodit, Nullable } from 'jodit/types';
13
+ import { Dom } from 'jodit/core/dom/dom';
14
+
15
+ /**
16
+ * Checks whether the insertion of an element at the current location is allowed,
17
+ * if it is not allowed, it deletes an empty block element or moves the cursor after it
18
+ * @internal
19
+ */
20
+ export function checkBlockNesting(jodit: IJodit, node: Nullable<Node>): void {
21
+ if (Dom.isFragment(node)) {
22
+ node = node.firstChild;
23
+ }
24
+
25
+ if (jodit.o.dtd.checkBlockNesting && Dom.isBlock(node)) {
26
+ const parent = Dom.furthest(
27
+ jodit.s.current(),
28
+ Dom.isBlock,
29
+ jodit.editor
30
+ );
31
+
32
+ if (parent && !jodit.o.dtd.blockLimits[parent.tagName.toLowerCase()]) {
33
+ jodit.s.setCursorAfter(parent);
34
+
35
+ if (Dom.isEmpty(parent)) {
36
+ Dom.safeRemove(parent);
37
+ }
38
+ }
39
+ }
40
+ }
@@ -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/dtd
9
+ * @internal
10
+ */
11
+
12
+ export * from './check-block-nesting';
@@ -0,0 +1,67 @@
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/dtd
9
+ */
10
+
11
+ import type { IDictionary } from 'jodit/types';
12
+ import { Config } from 'jodit/config';
13
+
14
+ declare module 'jodit/config' {
15
+ interface Config {
16
+ dtd: {
17
+ /**
18
+ * Remove extra br element inside block element after pasting
19
+ */
20
+ removeExtraBr: boolean;
21
+
22
+ /**
23
+ * Check when inserting a block element if it can be inside another block element (according `blockLimits`)
24
+ */
25
+ checkBlockNesting: boolean;
26
+
27
+ /**
28
+ * List of elements that contain other blocks
29
+ */
30
+ blockLimits: IDictionary<1>;
31
+ };
32
+ }
33
+ }
34
+
35
+ Config.prototype.dtd = {
36
+ removeExtraBr: true,
37
+ checkBlockNesting: true,
38
+ blockLimits: {
39
+ article: 1,
40
+ aside: 1,
41
+ audio: 1,
42
+ body: 1,
43
+ caption: 1,
44
+ details: 1,
45
+ dir: 1,
46
+ div: 1,
47
+ dl: 1,
48
+ fieldset: 1,
49
+ figcaption: 1,
50
+ figure: 1,
51
+ footer: 1,
52
+ form: 1,
53
+ header: 1,
54
+ hgroup: 1,
55
+ main: 1,
56
+ menu: 1,
57
+ nav: 1,
58
+ ol: 1,
59
+ section: 1,
60
+ table: 1,
61
+ td: 1,
62
+ th: 1,
63
+ tr: 1,
64
+ ul: 1,
65
+ video: 1
66
+ }
67
+ };
@@ -0,0 +1,128 @@
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
+ describe('Test dtd plugin', () => {
8
+ describe('Before insertNode', () => {
9
+ describe('Enable dtd.checkBlockNesting', () => {
10
+ describe('Not empty parent block', () => {
11
+ it('should move new block after parent', () => {
12
+ const editor = getJodit();
13
+ editor.value = '<p>test|</p>';
14
+ setCursorToChar(editor);
15
+ editor.s.insertHTML(
16
+ '<table><tbody><tr><td>1</td></tr></tbody></table>'
17
+ );
18
+ expect(sortAttributes(editor.value)).eq(
19
+ '<p>test</p><table><tbody><tr><td>1</td></tr></tbody></table>'
20
+ );
21
+ });
22
+ });
23
+
24
+ describe('Empty parent block', () => {
25
+ it('should replace parent block', () => {
26
+ const editor = getJodit();
27
+ editor.value = '<p>|<br></p>';
28
+ setCursorToChar(editor);
29
+ editor.s.insertHTML(
30
+ '<table><tbody><tr><td>1</td></tr></tbody></table>'
31
+ );
32
+ expect(sortAttributes(editor.value)).eq(
33
+ '<table><tbody><tr><td>1</td></tr></tbody></table>'
34
+ );
35
+ });
36
+ });
37
+ });
38
+
39
+ describe('Disable dtd.checkBlockNesting', () => {
40
+ it('should not check nesting', () => {
41
+ const editor = getJodit({
42
+ dtd: {
43
+ checkBlockNesting: false
44
+ }
45
+ });
46
+ editor.value = '<p>test|</p>';
47
+ setCursorToChar(editor);
48
+ editor.s.insertHTML(
49
+ '<table><tbody><tr><td>1</td></tr></tbody></table>'
50
+ );
51
+ expect(sortAttributes(editor.value)).eq(
52
+ '<p>test<table><tbody><tr><td>1</td></tr></tbody></table></p>'
53
+ );
54
+ });
55
+ });
56
+
57
+ describe('Add to dtd.blockLimits', () => {
58
+ it('should not check nesting', () => {
59
+ const editor = getJodit({
60
+ dtd: {
61
+ blockLimits: {
62
+ p: 1
63
+ }
64
+ }
65
+ });
66
+ editor.value = '<p>test|</p>';
67
+ setCursorToChar(editor);
68
+ editor.s.insertHTML(
69
+ '<table><tbody><tr><td>1</td></tr></tbody></table>'
70
+ );
71
+ expect(sortAttributes(editor.value)).eq(
72
+ '<p>test<table><tbody><tr><td>1</td></tr></tbody></table></p>'
73
+ );
74
+ });
75
+ });
76
+ });
77
+
78
+ describe('After insertNode', () => {
79
+ describe('Enable dtd.removeExtraBr', () => {
80
+ [
81
+ [
82
+ '<p>test|<br></p>',
83
+ '<img src="tests/artio.jpg">',
84
+ '<p>test<img src="tests/artio.jpg">|</p>',
85
+ '<p>test<img src="tests/artio.jpg">|<br></p>'
86
+ ],
87
+ [
88
+ '<p>|<br></p>',
89
+ '<img src="tests/artio.jpg">',
90
+ '<p><img src="tests/artio.jpg">|</p>',
91
+ '<p><img src="tests/artio.jpg">|<br></p>'
92
+ ]
93
+ ].forEach(([value, insert, result1, result2]) => {
94
+ describe(`for value ${value} and inserting ${insert}`, () => {
95
+ describe('Enable removeExtraBr', () => {
96
+ it('should move new block after parent', () => {
97
+ const editor = getJodit({
98
+ dtd: {
99
+ removeExtraBr: true
100
+ }
101
+ });
102
+ editor.value = value;
103
+ setCursorToChar(editor);
104
+ editor.s.insertHTML(insert);
105
+ replaceCursorToChar(editor);
106
+ expect(sortAttributes(editor.value)).eq(result1);
107
+ });
108
+ });
109
+
110
+ describe('Disable removeExtraBr', () => {
111
+ it('should move new block after parent', () => {
112
+ const editor = getJodit({
113
+ dtd: {
114
+ removeExtraBr: false
115
+ }
116
+ });
117
+ editor.value = value;
118
+ setCursorToChar(editor);
119
+ editor.s.insertHTML(insert);
120
+ replaceCursorToChar(editor);
121
+ expect(sortAttributes(editor.value)).eq(result2);
122
+ });
123
+ });
124
+ });
125
+ });
126
+ });
127
+ });
128
+ });
@@ -0,0 +1,48 @@
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
+ * [[include:plugins/dtd/README.md]]
9
+ * @packageDocumentation
10
+ * @module plugins/dtd
11
+ */
12
+
13
+ import type { IJodit } from 'jodit/types';
14
+ import { Plugin } from 'jodit/core/plugin';
15
+ import { pluginSystem } from 'jodit/core/global';
16
+ import { watch } from 'jodit/core/decorators/watch/watch';
17
+
18
+ import './config';
19
+ import * as beforeInsertCases from './before-insert';
20
+ import * as afterInsertCases from './after-insert';
21
+
22
+ class dtd extends Plugin {
23
+ protected afterInit(jodit: IJodit): void {}
24
+
25
+ protected beforeDestruct(jodit: IJodit): void {}
26
+
27
+ @watch(':beforeInsertNode')
28
+ protected __onBeforeInsertNode(node: Node): void {
29
+ const casesKeys = Object.keys(beforeInsertCases) as Array<
30
+ keyof typeof beforeInsertCases
31
+ >;
32
+ casesKeys.forEach(key => {
33
+ beforeInsertCases[key](this.j, node);
34
+ });
35
+ }
36
+
37
+ @watch(':afterInsertNode')
38
+ protected __onAfterInsertNode(node: Node): void {
39
+ const casesKeys = Object.keys(afterInsertCases) as Array<
40
+ keyof typeof afterInsertCases
41
+ >;
42
+ casesKeys.forEach(key => {
43
+ afterInsertCases[key](this.j, node);
44
+ });
45
+ }
46
+ }
47
+
48
+ pluginSystem.add('dtd', dtd);