jodit 3.23.3 → 3.24.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 (175) hide show
  1. package/README.md +4 -4
  2. package/build/jodit.css +8 -3
  3. package/build/jodit.es2018.css +7 -2
  4. package/build/jodit.es2018.en.css +7 -2
  5. package/build/jodit.es2018.en.js +8384 -7869
  6. package/build/jodit.es2018.en.min.css +1 -1
  7. package/build/jodit.es2018.en.min.js +1 -1
  8. package/build/jodit.es2018.js +8384 -7869
  9. package/build/jodit.es2018.min.css +1 -1
  10. package/build/jodit.es2018.min.js +1 -1
  11. package/build/jodit.js +2954 -2414
  12. package/build/jodit.min.css +2 -2
  13. package/build/jodit.min.js +1 -1
  14. package/build/plugins/debug/debug.es2018.en.js +8 -8
  15. package/build/plugins/debug/debug.es2018.en.min.js +1 -1
  16. package/build/plugins/debug/debug.es2018.js +8 -8
  17. package/build/plugins/debug/debug.es2018.min.js +1 -1
  18. package/build/plugins/debug/debug.js +8 -8
  19. package/build/plugins/debug/debug.min.js +1 -1
  20. package/build/plugins/speech-recognize/speech-recognize.css +1 -1
  21. package/build/plugins/speech-recognize/speech-recognize.es2018.css +1 -1
  22. package/build/plugins/speech-recognize/speech-recognize.es2018.en.css +1 -1
  23. package/build/plugins/speech-recognize/speech-recognize.es2018.en.js +38 -38
  24. package/build/plugins/speech-recognize/speech-recognize.es2018.en.min.js +1 -1
  25. package/build/plugins/speech-recognize/speech-recognize.es2018.js +38 -38
  26. package/build/plugins/speech-recognize/speech-recognize.es2018.min.js +1 -1
  27. package/build/plugins/speech-recognize/speech-recognize.js +30 -30
  28. package/build/plugins/speech-recognize/speech-recognize.min.js +1 -1
  29. package/build/vdom.css +12 -1
  30. package/build/vdom.js +1445 -41
  31. package/package.json +23 -23
  32. package/src/core/constants.ts +10 -8
  33. package/src/core/dom/dom.test.js +25 -0
  34. package/src/core/dom/dom.ts +90 -41
  35. package/src/core/helpers/checker/has-browser-color-picker.ts +2 -2
  36. package/src/core/helpers/checker/index.ts +1 -0
  37. package/src/core/helpers/checker/is-boolean.ts +1 -1
  38. package/src/core/helpers/checker/is-marker.ts +20 -0
  39. package/src/core/helpers/normalize/normalize-css-value.ts +19 -0
  40. package/src/core/helpers/normalize/normalize-node.ts +2 -2
  41. package/src/core/helpers/size/position.test.js +198 -187
  42. package/src/core/helpers/utils/css.ts +7 -14
  43. package/src/core/plugin/plugin.ts +1 -1
  44. package/src/core/selection/interface.ts +24 -0
  45. package/src/core/selection/select.ts +69 -29
  46. package/src/core/selection/selection.test.js +5 -17
  47. package/src/core/selection/style/api/extract.ts +6 -7
  48. package/src/core/selection/style/api/finite-state-machine.ts +40 -35
  49. package/src/core/selection/style/api/get-suit-child.ts +3 -4
  50. package/src/core/selection/style/api/get-suit-parent.ts +3 -4
  51. package/src/core/selection/style/api/{element-has-same-style.ts → has-same-style.ts} +25 -6
  52. package/src/core/selection/style/api/index.ts +6 -6
  53. package/src/core/selection/style/api/is-inside-invisible-element.ts +1 -1
  54. package/src/core/selection/style/api/is-normal-node.ts +3 -3
  55. package/src/core/selection/style/api/is-same-attributes.ts +56 -0
  56. package/src/core/selection/style/api/is-suit-element.ts +22 -12
  57. package/src/core/selection/style/api/list/toggle-ordered-list.ts +100 -0
  58. package/src/core/selection/style/api/list/wrap-list.ts +71 -0
  59. package/src/core/selection/style/api/toggle-attributes.ts +251 -0
  60. package/src/core/selection/style/api/unwrap-children.ts +10 -8
  61. package/src/core/selection/style/api/wrap-unwrapped-text.ts +7 -8
  62. package/src/core/selection/style/api/{wrap-and-commit-style.ts → wrap.ts} +8 -11
  63. package/src/core/selection/style/apply-style.ts +32 -181
  64. package/src/core/selection/style/commit-style.ts +79 -4
  65. package/src/core/selection/style/style.test.js +457 -128
  66. package/src/core/selection/style/transactions.ts +256 -0
  67. package/src/core/ui/button/tooltip/tooltip.test.js +95 -76
  68. package/src/core/ui/popup/popup.test.js +158 -153
  69. package/src/{plugins/backspace/interface.d.ts → core/vdom/on-demand.ts} +7 -5
  70. package/src/core/vdom/render/index.ts +2 -4
  71. package/src/core/vdom/render/patcher.ts +14 -0
  72. package/src/core/vdom/v-dom-jodit.less +17 -0
  73. package/src/core/vdom/v-dom-jodit.ts +102 -3
  74. package/src/core/view/view.ts +2 -2
  75. package/src/index.ts +2 -0
  76. package/src/jodit.ts +5 -1
  77. package/src/langs/i18n.test.js +221 -216
  78. package/src/modules/dialog/dialog.less +9 -1
  79. package/src/modules/dialog/dialog.ts +25 -16
  80. package/src/modules/file-browser/data-provider.ts +44 -12
  81. package/src/modules/file-browser/file-browser.test.js +1019 -958
  82. package/src/modules/file-browser/file-browser.ts +0 -1
  83. package/src/modules/messages/messages.ts +3 -8
  84. package/src/plugins/backspace/backspace.test.js +2 -9
  85. package/src/plugins/backspace/backspace.ts +5 -0
  86. package/src/plugins/backspace/cases/check-join-neighbors.ts +7 -1
  87. package/src/plugins/backspace/cases/check-join-two-lists.ts +2 -1
  88. package/src/plugins/backspace/helpers.ts +9 -1
  89. package/src/plugins/backspace/interface.ts +31 -0
  90. package/src/plugins/clean-html/helpers/visitor/filters/fill-empty-paragraph.ts +2 -1
  91. package/src/plugins/color/color.test.js +122 -119
  92. package/src/plugins/enter/enter.test.js +18 -5
  93. package/src/plugins/enter/enter.ts +9 -5
  94. package/src/plugins/enter/interface.ts +41 -0
  95. package/src/plugins/font/config.ts +8 -8
  96. package/src/plugins/font/font.test.js +18 -23
  97. package/src/plugins/hotkeys/hotkeys.test.js +35 -47
  98. package/src/plugins/iframe/iframe.test.js +206 -195
  99. package/src/plugins/image/image.ts +1 -1
  100. package/src/plugins/image-properties/config.ts +22 -0
  101. package/src/plugins/image-properties/image-properties.test.js +174 -93
  102. package/src/plugins/image-properties/templates/position-tab.ts +22 -1
  103. package/src/plugins/indent/indent.test.js +2 -8
  104. package/src/plugins/link/link.test.js +19 -0
  105. package/src/plugins/link/link.ts +25 -15
  106. package/src/plugins/placeholder/placeholder.ts +8 -7
  107. package/src/plugins/size/size.test.js +239 -225
  108. package/src/plugins/tab/cases/on-tab-inside-li.ts +131 -22
  109. package/src/plugins/tab/tab.test.js +95 -11
  110. package/src/plugins/tab/tab.ts +22 -2
  111. package/src/plugins/wrap-nodes/config.ts +11 -0
  112. package/src/plugins/wrap-nodes/wrap-nodes.ts +0 -1
  113. package/src/types/events.d.ts +4 -0
  114. package/src/types/file-browser.d.ts +17 -10
  115. package/src/types/select.d.ts +6 -1
  116. package/src/types/style.d.ts +72 -5
  117. package/src/types/uploader.d.ts +14 -0
  118. package/src/types/view.d.ts +2 -2
  119. package/types/core/async/async.d.ts +1 -1
  120. package/types/core/constants.d.ts +3 -3
  121. package/types/core/dom/dom.d.ts +6 -3
  122. package/types/core/helpers/checker/index.d.ts +1 -0
  123. package/types/core/helpers/checker/is-boolean.d.ts +1 -1
  124. package/types/core/helpers/checker/is-marker.d.ts +10 -0
  125. package/types/core/helpers/html/safe-html.d.ts +1 -1
  126. package/types/core/helpers/normalize/normalize-css-value.d.ts +2 -0
  127. package/types/core/helpers/normalize/normalize-node.d.ts +1 -1
  128. package/types/core/helpers/utils/append-script.d.ts +1 -1
  129. package/types/core/selection/interface.d.ts +19 -0
  130. package/types/core/selection/select.d.ts +22 -5
  131. package/types/core/selection/style/api/finite-state-machine.d.ts +10 -9
  132. package/types/core/selection/style/api/get-suit-child.d.ts +2 -3
  133. package/types/core/selection/style/api/get-suit-parent.d.ts +2 -3
  134. package/types/core/selection/style/api/{element-has-same-style.d.ts → has-same-style.d.ts} +2 -2
  135. package/types/core/selection/style/api/index.d.ts +6 -6
  136. package/types/core/selection/style/api/is-same-attributes.d.ts +12 -0
  137. package/types/core/selection/style/api/is-suit-element.d.ts +4 -4
  138. package/types/core/selection/style/api/{toggle → list}/toggle-ordered-list.d.ts +2 -3
  139. package/types/core/selection/style/api/{wrap-ordered-list.d.ts → list/wrap-list.d.ts} +2 -3
  140. package/types/core/selection/style/api/toggle-attributes.d.ts +11 -0
  141. package/types/core/selection/style/api/unwrap-children.d.ts +2 -2
  142. package/types/core/selection/style/api/wrap-unwrapped-text.d.ts +2 -3
  143. package/types/core/selection/style/api/{wrap-and-commit-style.d.ts → wrap.d.ts} +2 -3
  144. package/types/core/selection/style/apply-style.d.ts +3 -3
  145. package/types/core/selection/style/commit-style.d.ts +6 -2
  146. package/types/core/selection/style/transactions.d.ts +29 -0
  147. package/types/core/ui/popup/popup.d.ts +1 -1
  148. package/types/core/view/view.d.ts +1 -1
  149. package/types/index.d.ts +2 -0
  150. package/types/modules/file-browser/builders/elements-map.d.ts +1 -1
  151. package/types/modules/file-browser/data-provider.d.ts +5 -0
  152. package/types/modules/messages/messages.d.ts +2 -1
  153. package/types/plugins/backspace/helpers.d.ts +5 -1
  154. package/types/plugins/backspace/interface.d.ts +21 -0
  155. package/types/plugins/enter/enter.d.ts +2 -0
  156. package/types/plugins/enter/interface.d.ts +32 -0
  157. package/types/plugins/image-properties/config.d.ts +19 -0
  158. package/types/plugins/link/link.d.ts +1 -1
  159. package/types/plugins/paste/interface.d.ts +2 -2
  160. package/types/plugins/tab/cases/on-tab-inside-li.d.ts +1 -1
  161. package/types/plugins/wrap-nodes/config.d.ts +10 -0
  162. package/types/types/events.d.ts +4 -0
  163. package/types/types/file-browser.d.ts +17 -10
  164. package/types/types/select.d.ts +6 -1
  165. package/types/types/storage.d.ts +1 -1
  166. package/types/types/style.d.ts +72 -5
  167. package/types/types/uploader.d.ts +14 -0
  168. package/types/types/view.d.ts +2 -2
  169. package/vdom.html +20 -0
  170. package/src/core/selection/style/api/toggle/toggle-css.ts +0 -136
  171. package/src/core/selection/style/api/toggle/toggle-ordered-list.ts +0 -54
  172. package/src/core/selection/style/api/toggle-commit-styles.ts +0 -35
  173. package/src/core/selection/style/api/wrap-ordered-list.ts +0 -42
  174. package/types/core/selection/style/api/toggle/toggle-css.d.ts +0 -12
  175. package/types/core/selection/style/api/toggle-commit-styles.d.ts +0 -13
@@ -3,126 +3,111 @@
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
- describe('Iframe mode', function () {
7
- describe('Create editor with iframe mode', function () {
8
- it('Should create editable area in another document', function (done) {
9
- unmockPromise();
10
- Jodit.make(appendTestArea(), {
11
- iframe: true,
12
- events: {
13
- afterConstructor: function (editor) {
14
- expect(editor.ownerDocument).does.not.equal(editor.ed);
15
- expect('true').equals(
16
- editor.ed.body.getAttribute('contenteditable')
17
- );
18
- done();
19
- }
20
- }
21
- });
22
- });
23
-
24
- describe('And exec command', function () {
25
- it('Should use body like editor area', function (done) {
6
+ ('iframe' in window.skipTest ? describe.skip : describe)(
7
+ 'Iframe mode',
8
+ function () {
9
+ describe('Create editor with iframe mode', function () {
10
+ it('Should create editable area in another document', function (done) {
26
11
  unmockPromise();
27
12
  Jodit.make(appendTestArea(), {
28
13
  iframe: true,
29
14
  events: {
30
15
  afterConstructor: function (editor) {
31
- mockPromise();
32
- editor.value = 'test test stop';
33
-
34
- expect(editor.ed.body.innerHTML).equals(
35
- '<p>test test stop</p>'
16
+ expect(editor.ownerDocument).does.not.equal(
17
+ editor.ed
36
18
  );
37
-
38
- const range = editor.s.createRange();
39
- range.selectNodeContents(editor.ed.body);
40
- editor.s.selectRange(range);
41
-
42
- editor.execCommand('bold');
43
-
44
- expect(editor.ed.body.innerHTML).equals(
45
- '<p><strong>test test stop</strong></p>'
19
+ expect('true').equals(
20
+ editor.ed.body.getAttribute('contenteditable')
46
21
  );
47
-
48
22
  done();
49
23
  }
50
24
  }
51
25
  });
52
26
  });
53
- });
54
27
 
55
- describe('Set value right after construct', function () {
56
- it('Should set/get value without some trouble', function () {
57
- const area = appendTestArea();
28
+ describe('And exec command', function () {
29
+ it('Should use body like editor area', function (done) {
30
+ unmockPromise();
31
+ Jodit.make(appendTestArea(), {
32
+ iframe: true,
33
+ events: {
34
+ afterConstructor: function (editor) {
35
+ mockPromise();
36
+ editor.value = 'test test stop';
58
37
 
59
- area.value = 'stop';
38
+ expect(editor.ed.body.innerHTML).equals(
39
+ '<p>test test stop</p>'
40
+ );
60
41
 
61
- const editor = Jodit.make(area, {
62
- iframe: true
63
- });
42
+ const range = editor.s.createRange();
43
+ range.selectNodeContents(editor.ed.body);
44
+ editor.s.selectRange(range);
64
45
 
65
- expect(editor.value).equals('<p>stop</p>');
66
- editor.value = 'test1';
67
- expect(editor.value).equals('<p>test1</p>');
68
- });
69
- });
46
+ editor.execCommand('bold');
70
47
 
71
- describe('Enable editHTMLDocumentMode', function () {
72
- describe('With DIV source element', function () {
73
- it('Should throw error', function () {
74
- const div = appendTestDiv();
48
+ expect(editor.ed.body.innerHTML).equals(
49
+ '<p><strong>test test stop</strong></p>'
50
+ );
75
51
 
76
- expect(function () {
77
- Jodit.make(div, {
78
- iframe: true,
79
- editHTMLDocumentMode: true
80
- });
81
- }).throws(TypeError);
52
+ done();
53
+ }
54
+ }
55
+ });
82
56
  });
83
57
  });
84
58
 
85
- describe('With AREA source element', function () {
86
- const opt = {
87
- iframe: true,
88
- iframeTitle: 'Hi',
89
- disablePlugins: ['size'],
90
- height: 300,
91
- iframeStyle: '',
92
- iframeCSSLinks: [],
93
- editHTMLDocumentMode: true
94
- };
95
-
96
- it('Should work fine', function () {
59
+ describe('Set value right after construct', function () {
60
+ it('Should set/get value without some trouble', function () {
97
61
  const area = appendTestArea();
98
62
 
99
- expect(function () {
100
- Jodit.make(area, opt);
101
- }).does.not.throws(TypeError);
63
+ area.value = 'stop';
64
+
65
+ const editor = Jodit.make(area, {
66
+ iframe: true
67
+ });
68
+
69
+ expect(editor.value).equals('<p>stop</p>');
70
+ editor.value = 'test1';
71
+ expect(editor.value).equals('<p>test1</p>');
102
72
  });
73
+ });
103
74
 
104
- describe('editor.value', function () {
105
- it('Should return entire HTML', function () {
106
- const editor = Jodit.make(appendTestArea(), opt);
107
-
108
- expect(
109
- sortAttributes(
110
- editor.value
111
- .replace(/[\t\n]/g, '')
112
- .replace(/<br>/g, '')
113
- )
114
- ).equals(
115
- '<!DOCTYPE html><html lang="en">' +
116
- '<head><title>Hi</title></head>' +
117
- '<body spellcheck="false"></body>' +
118
- '</html>'
119
- );
75
+ describe('Enable editHTMLDocumentMode', function () {
76
+ describe('With DIV source element', function () {
77
+ it('Should throw error', function () {
78
+ const div = appendTestDiv();
79
+
80
+ expect(function () {
81
+ Jodit.make(div, {
82
+ iframe: true,
83
+ editHTMLDocumentMode: true
84
+ });
85
+ }).throws(TypeError);
120
86
  });
87
+ });
88
+
89
+ describe('With AREA source element', function () {
90
+ const opt = {
91
+ iframe: true,
92
+ iframeTitle: 'Hi',
93
+ disablePlugins: ['size'],
94
+ height: 300,
95
+ iframeStyle: '',
96
+ iframeCSSLinks: [],
97
+ editHTMLDocumentMode: true
98
+ };
121
99
 
122
- describe('Set some part of HTML', function () {
123
- it('Should insert this part inside BODY', function () {
100
+ it('Should work fine', function () {
101
+ const area = appendTestArea();
102
+
103
+ expect(function () {
104
+ Jodit.make(area, opt);
105
+ }).does.not.throws(TypeError);
106
+ });
107
+
108
+ describe('editor.value', function () {
109
+ it('Should return entire HTML', function () {
124
110
  const editor = Jodit.make(appendTestArea(), opt);
125
- editor.value = '<strong>Test</strong>';
126
111
 
127
112
  expect(
128
113
  sortAttributes(
@@ -133,58 +118,62 @@ describe('Iframe mode', function () {
133
118
  ).equals(
134
119
  '<!DOCTYPE html><html lang="en">' +
135
120
  '<head><title>Hi</title></head>' +
136
- '<body spellcheck="false">' +
137
- '<p><strong>Test</strong></p></body></html>'
121
+ '<body spellcheck="false"></body>' +
122
+ '</html>'
138
123
  );
139
124
  });
140
- });
141
125
 
142
- describe('Set entire HTML', function () {
143
- it('Should replace entire document', function () {
144
- const editor = Jodit.make(appendTestArea(), opt);
145
- editor.value =
146
- '<!DOCTYPE html><html lang="en"><head><title>Hi</title></head><body><strong>Test1</strong></body></html>';
147
-
148
- expect(
149
- sortAttributes(
150
- editor.value
151
- .replace(/[\t\n]/g, '')
152
- .replace(/ {2,}/g, ' ')
153
- .replace(/[\s]+>/g, '>')
154
- )
155
- ).equals(
156
- '<!DOCTYPE html><html lang="en"><head><title>Hi</title></head><body spellcheck="false"><p><strong>Test1</strong></p></body></html>'
157
- );
126
+ describe('Set some part of HTML', function () {
127
+ it('Should insert this part inside BODY', function () {
128
+ const editor = Jodit.make(
129
+ appendTestArea(),
130
+ opt
131
+ );
132
+ editor.value = '<strong>Test</strong>';
133
+
134
+ expect(
135
+ sortAttributes(
136
+ editor.value
137
+ .replace(/[\t\n]/g, '')
138
+ .replace(/<br>/g, '')
139
+ )
140
+ ).equals(
141
+ '<!DOCTYPE html><html lang="en">' +
142
+ '<head><title>Hi</title></head>' +
143
+ '<body spellcheck="false">' +
144
+ '<p><strong>Test</strong></p></body></html>'
145
+ );
146
+ });
158
147
  });
159
- });
160
- });
161
- });
162
148
 
163
- describe('Change event', function () {
164
- it('should work like in usual case', function () {
165
- const editor = getJodit({
166
- editHTMLDocumentMode: true,
167
- iframe: true,
168
- iframeStyle: '',
169
- iframeCSSLinks: Jodit.atom([])
149
+ describe('Set entire HTML', function () {
150
+ it('Should replace entire document', function () {
151
+ const editor = Jodit.make(
152
+ appendTestArea(),
153
+ opt
154
+ );
155
+ editor.value =
156
+ '<!DOCTYPE html><html lang="en"><head><title>Hi</title></head><body><strong>Test1</strong></body></html>';
157
+
158
+ expect(
159
+ sortAttributes(
160
+ editor.value
161
+ .replace(/[\t\n]/g, '')
162
+ .replace(/ {2,}/g, ' ')
163
+ .replace(/[\s]+>/g, '>')
164
+ )
165
+ ).equals(
166
+ '<!DOCTYPE html><html lang="en"><head><title>Hi</title></head><body spellcheck="false"><p><strong>Test1</strong></p></body></html>'
167
+ );
168
+ });
169
+ });
170
170
  });
171
- editor.value = 'Some text';
172
-
173
- let changeCounter = 0;
174
- const onChange = function () {
175
- changeCounter += 1;
176
- };
177
-
178
- editor.e.on('change', onChange);
179
- editor.value = 'Some text2';
180
- expect(changeCounter).equals(1);
181
171
  });
182
172
 
183
- describe('Change mode', function () {
173
+ describe('Change event', function () {
184
174
  it('should work like in usual case', function () {
185
175
  const editor = getJodit({
186
176
  editHTMLDocumentMode: true,
187
- sourceEdiotor: 'area',
188
177
  iframe: true,
189
178
  iframeStyle: '',
190
179
  iframeCSSLinks: Jodit.atom([])
@@ -197,81 +186,103 @@ describe('Iframe mode', function () {
197
186
  };
198
187
 
199
188
  editor.e.on('change', onChange);
200
- editor.s.insertHTML('Some text1');
201
- editor.s.insertHTML('Some text2');
189
+ editor.value = 'Some text2';
190
+ expect(changeCounter).equals(1);
191
+ });
202
192
 
203
- expect(changeCounter).equals(2);
193
+ describe('Change mode', function () {
194
+ it('should work like in usual case', function () {
195
+ const editor = getJodit({
196
+ editHTMLDocumentMode: true,
197
+ sourceEdiotor: 'area',
198
+ iframe: true,
199
+ iframeStyle: '',
200
+ iframeCSSLinks: Jodit.atom([])
201
+ });
202
+ editor.value = 'Some text';
203
+
204
+ let changeCounter = 0;
205
+ const onChange = function () {
206
+ changeCounter += 1;
207
+ };
204
208
 
205
- editor.toggleMode();
206
- expect(changeCounter).equals(3);
209
+ editor.e.on('change', onChange);
210
+ editor.s.insertHTML('Some text1');
211
+ editor.s.insertHTML('Some text2');
207
212
 
208
- editor.__plugins.source.sourceEditor.instance.value =
209
- 'Some text3';
210
- editor.e.fire(
211
- 'change',
212
- editor.__plugins.source.sourceEditor.instance
213
- );
214
- expect(changeCounter).equals(4);
213
+ expect(changeCounter).equals(2);
215
214
 
216
- editor.toggleMode();
217
- editor.editor.appendChild(
218
- editor.createInside.text('x')
219
- );
220
- simulateEvent('keydown', 'x', editor.editor);
215
+ editor.toggleMode();
216
+ expect(changeCounter).equals(3);
217
+
218
+ editor.__plugins.source.sourceEditor.instance.value =
219
+ 'Some text3';
220
+ editor.e.fire(
221
+ 'change',
222
+ editor.__plugins.source.sourceEditor.instance
223
+ );
224
+ expect(changeCounter).equals(4);
225
+
226
+ editor.toggleMode();
227
+ editor.editor.appendChild(
228
+ editor.createInside.text('x')
229
+ );
230
+ simulateEvent('keydown', 'x', editor.editor);
221
231
 
222
- expect(changeCounter).above(5);
232
+ expect(changeCounter).above(5);
233
+ });
223
234
  });
224
235
  });
225
236
  });
226
237
  });
227
- });
228
238
 
229
- describe('Define document for iframe from some site', function () {
230
- it('Should work perfect', function (done) {
231
- unmockPromise();
232
- const area = appendTestArea();
233
-
234
- area.value = '<p>start value</p>';
235
-
236
- Jodit.make(area, {
237
- iframe: true,
238
- events: {
239
- afterConstructor: function (jodit) {
240
- expect(
241
- jodit.editor.getAttribute('secret-attribute')
242
- ).equals('435'); // loaded from index.html
243
- expect(Jodit.ns.Helpers.trim(jodit.value)).equals(
244
- '<p>test 435</p>'
245
- ); // loaded from index.html
246
- done();
247
- },
248
- beforeSetValueToEditor: function () {
249
- return false;
250
- },
251
- ['generateDocumentStructure.iframe']: function (
252
- doc,
253
- jodit
254
- ) {
255
- jodit.events.stopPropagation(
256
- 'generateDocumentStructure.iframe'
257
- );
258
- return new Promise(resolve => {
259
- jodit.iframe.onload = function () {
260
- resolve();
261
- };
239
+ describe('Define document for iframe from some site', function () {
240
+ it('Should work perfect', function (done) {
241
+ unmockPromise();
242
+ const area = appendTestArea();
262
243
 
263
- setTimeout(function () {
264
- resolve();
265
- }, 4000);
244
+ area.value = '<p>start value</p>';
266
245
 
267
- jodit.iframe.src = 'test.index.html';
268
- });
246
+ Jodit.make(area, {
247
+ iframe: true,
248
+ events: {
249
+ afterConstructor: function (jodit) {
250
+ expect(
251
+ jodit.editor.getAttribute('secret-attribute')
252
+ ).equals('435'); // loaded from index.html
253
+ expect(Jodit.ns.Helpers.trim(jodit.value)).equals(
254
+ '<p>test 435</p>'
255
+ ); // loaded from index.html
256
+ done();
257
+ },
258
+ beforeSetValueToEditor: function () {
259
+ return false;
260
+ },
261
+ ['generateDocumentStructure.iframe']: function (
262
+ doc,
263
+ jodit
264
+ ) {
265
+ jodit.events.stopPropagation(
266
+ 'generateDocumentStructure.iframe'
267
+ );
268
+ return new Promise(resolve => {
269
+ jodit.iframe.onload = function () {
270
+ resolve();
271
+ };
272
+
273
+ setTimeout(function () {
274
+ resolve();
275
+ }, 4000);
276
+
277
+ jodit.iframe.src = 'test.index.html';
278
+ });
279
+ }
269
280
  }
270
- }
271
- });
272
- }).timeout(5000);
273
- });
274
- });
281
+ });
282
+ }).timeout(5000);
283
+ });
284
+ }
285
+ );
275
286
 
276
287
  describe('Editor inside iframe', function () {
277
288
  describe('In creator doc field', function () {
@@ -25,7 +25,7 @@ import { Icon } from 'jodit/core/ui/icon';
25
25
  Icon.set('image', require('./image.svg'));
26
26
 
27
27
  Config.prototype.controls.image = {
28
- popup: (editor: IJodit, current, self, close) => {
28
+ popup: (editor: IJodit, current, ignore, close) => {
29
29
  let sourceImage: HTMLImageElement | null = null;
30
30
 
31
31
  if (
@@ -61,6 +61,27 @@ declare module 'jodit/config' {
61
61
  */
62
62
  editClass: boolean;
63
63
 
64
+ /**
65
+ * Pre-define available classes to select from
66
+ *
67
+ * Classes can be provided as list of strings or as list of tuples
68
+ * `["classname", "human label"]`.
69
+ *
70
+ * @example
71
+ * ```javascript
72
+ * new Jodit('#editor', {
73
+ * image: {
74
+ * availableClasses: [
75
+ * "rte-image-width-50",
76
+ * ["rte-image-width-75", "75 % width"]
77
+ * ]
78
+ * }
79
+ * })
80
+ * ```
81
+ */
82
+
83
+ availableClasses: [string, string][] | string[];
84
+
64
85
  /**
65
86
  * Show style edit input
66
87
  */
@@ -101,6 +122,7 @@ Config.prototype.image = {
101
122
  editBorderRadius: true,
102
123
  editMargins: true,
103
124
  editClass: true,
125
+ availableClasses: [],
104
126
  editStyle: true,
105
127
  editId: true,
106
128
  editAlign: true,