jodit 3.9.3 → 3.10.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 (214) hide show
  1. package/.idea/workspace.xml +306 -295
  2. package/CHANGELOG.MD +349 -119
  3. package/build/jodit.css +675 -538
  4. package/build/jodit.es2018.css +536 -436
  5. package/build/jodit.es2018.en.css +536 -436
  6. package/build/jodit.es2018.en.js +1529 -738
  7. package/build/jodit.es2018.en.min.css +1 -1
  8. package/build/jodit.es2018.en.min.js +1 -1
  9. package/build/jodit.es2018.js +1533 -742
  10. package/build/jodit.es2018.min.css +1 -1
  11. package/build/jodit.es2018.min.js +1 -1
  12. package/build/jodit.js +2598 -1680
  13. package/build/jodit.min.css +2 -2
  14. package/build/jodit.min.js +1 -1
  15. package/index.d.ts +10 -0
  16. package/package.json +10 -10
  17. package/src/config.ts +19 -20
  18. package/src/core/component/component.ts +16 -15
  19. package/src/core/component/statuses.ts +6 -6
  20. package/src/core/dom.ts +16 -4
  21. package/src/core/events/event-emitter.ts +4 -2
  22. package/src/core/global.ts +13 -2
  23. package/src/core/helpers/append-script.ts +14 -0
  24. package/src/core/helpers/selector.ts +8 -3
  25. package/src/core/helpers/size/index.ts +1 -0
  26. package/src/core/helpers/size/object-size.ts +22 -0
  27. package/src/core/selection/select.ts +1 -0
  28. package/src/core/selection/style/api/{get-closest-wrapper.ts → extract.ts} +26 -43
  29. package/src/core/selection/style/api/finite-state-machine.ts +66 -0
  30. package/src/core/selection/style/api/index.ts +12 -5
  31. package/src/core/selection/style/api/{check-special-elements.ts → is-inside-invisible-element.ts} +1 -1
  32. package/src/core/selection/style/api/is-suit-element.ts +12 -1
  33. package/src/core/selection/style/api/toggle/toggle-css.ts +134 -0
  34. package/src/core/selection/style/api/toggle/toggle-ordered-list.ts +49 -0
  35. package/src/core/selection/style/api/toggle-commit-styles.ts +27 -0
  36. package/src/core/selection/style/api/wrap-and-commit-style.ts +68 -0
  37. package/src/core/selection/style/api/wrap-ordered-list.ts +37 -0
  38. package/src/core/selection/style/api/wrap-unwrapped-text.ts +1 -4
  39. package/src/core/selection/style/apply-style.ts +161 -97
  40. package/src/core/selection/style/commit-style.ts +13 -0
  41. package/src/core/storage/engines/local-storage-provider.ts +9 -3
  42. package/src/core/storage/engines/memory-storage-provider.ts +6 -3
  43. package/src/core/storage/storage.ts +7 -4
  44. package/src/core/ui/button/button/button.less +10 -8
  45. package/src/core/ui/button/button/button.ts +9 -9
  46. package/src/core/ui/button/group/group.ts +2 -2
  47. package/src/core/ui/element.ts +4 -3
  48. package/src/core/ui/form/block/block.ts +1 -1
  49. package/src/core/ui/form/form.ts +8 -0
  50. package/src/core/ui/form/inputs/area/area.less +5 -0
  51. package/src/core/ui/form/inputs/area/area.ts +22 -1
  52. package/src/core/ui/form/inputs/checkbox/checkbox.less +50 -0
  53. package/src/core/ui/form/inputs/checkbox/checkbox.ts +48 -4
  54. package/src/core/ui/form/inputs/input/input.less +1 -1
  55. package/src/core/ui/form/inputs/input/input.ts +14 -4
  56. package/src/core/ui/helpers/buttons.ts +14 -6
  57. package/src/core/ui/icon.ts +3 -1
  58. package/src/core/ui/index.ts +1 -3
  59. package/src/core/ui/list/group.less +8 -2
  60. package/src/core/ui/list/group.ts +2 -2
  61. package/src/{modules/file-browser/consts.ts → core/ui/list/index.ts} +4 -4
  62. package/src/core/ui/list/list.less +10 -1
  63. package/src/core/ui/list/list.ts +20 -3
  64. package/src/core/ui/{separator.ts → list/separator.ts} +2 -2
  65. package/src/core/ui/list/spacer.ts +15 -0
  66. package/src/core/ui/popup/popup.less +5 -3
  67. package/src/core/ui/popup/popup.ts +53 -1
  68. package/src/core/view/view-with-toolbar.ts +6 -1
  69. package/src/jodit.ts +17 -14
  70. package/src/modules/dialog/dialog.less +1 -16
  71. package/src/modules/dialog/dialog.ts +10 -3
  72. package/src/modules/file-browser/builders/context-menu.ts +29 -22
  73. package/src/modules/file-browser/config.ts +10 -2
  74. package/src/modules/file-browser/file-browser.ts +50 -29
  75. package/src/modules/file-browser/listeners/native-listeners.ts +37 -19
  76. package/src/modules/file-browser/listeners/state-listeners.ts +48 -22
  77. package/src/modules/file-browser/styles/file-browser.less +4 -291
  78. package/src/modules/file-browser/styles/preview.less +11 -8
  79. package/src/modules/file-browser/ui/files/files.less +174 -0
  80. package/src/modules/file-browser/ui/files/files.ts +14 -0
  81. package/src/modules/file-browser/ui/index.ts +8 -0
  82. package/src/modules/file-browser/ui/tree/tree.less +118 -0
  83. package/src/modules/file-browser/ui/tree/tree.ts +14 -0
  84. package/src/modules/status-bar/status-bar.less +27 -1
  85. package/src/modules/status-bar/status-bar.ts +15 -1
  86. package/src/modules/toolbar/collection/collection.ts +17 -8
  87. package/src/modules/toolbar/collection/editor-collection.ts +27 -2
  88. package/src/modules/widget/file-selector/file-selector.ts +1 -1
  89. package/src/modules/widget/tabs/tabs.less +2 -1
  90. package/src/modules/widget/tabs/tabs.ts +5 -3
  91. package/src/plugins/add-new-line/add-new-line.ts +1 -0
  92. package/src/plugins/bold.ts +2 -2
  93. package/src/plugins/clipboard/drag-and-drop.ts +4 -1
  94. package/src/plugins/clipboard/paste/paste.ts +1 -1
  95. package/src/plugins/font.ts +11 -1
  96. package/src/plugins/image/image-properties/image-properties.ts +7 -0
  97. package/src/plugins/index.ts +1 -0
  98. package/src/plugins/inline-popup/config/config.ts +1 -0
  99. package/src/plugins/inline-popup/config/items/toolbar.ts +33 -0
  100. package/src/plugins/inline-popup/inline-popup.ts +17 -0
  101. package/src/plugins/keyboard/delete.ts +30 -8
  102. package/src/plugins/link/template.ts +2 -2
  103. package/src/plugins/mobile.ts +10 -14
  104. package/src/plugins/ordered-list.ts +40 -1
  105. package/src/plugins/powered-by-jodit.ts +39 -0
  106. package/src/plugins/print/preview.ts +103 -48
  107. package/src/plugins/resizer/resizer.less +10 -7
  108. package/src/plugins/resizer/resizer.ts +12 -14
  109. package/src/plugins/size/resize-handler.ts +4 -1
  110. package/src/plugins/size/size.less +2 -19
  111. package/src/plugins/size/size.ts +6 -1
  112. package/src/plugins/source/const.ts +7 -0
  113. package/src/plugins/source/editor/engines/ace.ts +5 -0
  114. package/src/plugins/source/source.ts +33 -7
  115. package/src/plugins/sticky/sticky.ts +2 -0
  116. package/src/styles/icons/index.ts +2 -0
  117. package/src/styles/icons/resize-handler.svg +4 -0
  118. package/src/styles/jodit.less +6 -0
  119. package/src/styles/mixins.less +20 -0
  120. package/src/styles/themes/dark.less +11 -1
  121. package/src/types/ajax.d.ts +0 -1
  122. package/src/types/file-browser.d.ts +13 -1
  123. package/src/types/jodit.d.ts +4 -1
  124. package/src/types/popup.d.ts +1 -0
  125. package/src/types/select.d.ts +2 -0
  126. package/src/types/storage.ts +3 -3
  127. package/src/types/style.d.ts +8 -0
  128. package/src/types/toolbar.d.ts +9 -2
  129. package/src/types/types.d.ts +1 -1
  130. package/src/types/ui.d.ts +23 -4
  131. package/src/types/view.d.ts +1 -0
  132. package/types/core/component/component.d.ts +10 -5
  133. package/types/core/component/statuses.d.ts +6 -6
  134. package/types/core/dom.d.ts +3 -2
  135. package/types/core/helpers/append-script.d.ts +1 -0
  136. package/types/core/helpers/selector.d.ts +2 -3
  137. package/types/core/helpers/size/index.d.ts +1 -0
  138. package/types/core/helpers/size/object-size.d.ts +7 -0
  139. package/types/core/selection/style/api/{get-closest-wrapper.d.ts → extract.d.ts} +6 -5
  140. package/types/core/selection/style/api/finite-state-machine.d.ts +21 -0
  141. package/types/core/selection/style/api/index.d.ts +12 -5
  142. package/types/core/selection/style/api/{check-special-elements.d.ts → is-inside-invisible-element.d.ts} +1 -1
  143. package/types/core/selection/style/api/is-suit-element.d.ts +9 -0
  144. package/types/core/selection/style/api/toggle/toggle-css.d.ts +11 -0
  145. package/types/core/selection/style/api/toggle/toggle-ordered-list.d.ts +11 -0
  146. package/types/core/selection/style/api/{toggle-styles.d.ts → toggle-commit-styles.d.ts} +1 -3
  147. package/types/core/selection/style/api/{post-process-list-element.d.ts → wrap-and-commit-style.d.ts} +3 -3
  148. package/types/core/selection/style/api/wrap-ordered-list.d.ts +12 -0
  149. package/types/core/selection/style/apply-style.d.ts +1 -4
  150. package/types/core/selection/style/commit-style.d.ts +7 -0
  151. package/types/core/storage/engines/local-storage-provider.d.ts +3 -3
  152. package/types/core/storage/engines/memory-storage-provider.d.ts +3 -3
  153. package/types/core/storage/storage.d.ts +3 -3
  154. package/types/core/ui/button/button/button.d.ts +3 -3
  155. package/types/core/ui/form/form.d.ts +1 -0
  156. package/types/core/ui/form/inputs/area/area.d.ts +7 -1
  157. package/types/core/ui/form/inputs/checkbox/checkbox.d.ts +10 -3
  158. package/types/core/ui/helpers/buttons.d.ts +2 -2
  159. package/types/core/ui/icon.d.ts +1 -1
  160. package/types/core/ui/index.d.ts +1 -3
  161. package/types/core/ui/list/group.d.ts +2 -1
  162. package/types/core/ui/list/index.d.ts +9 -0
  163. package/types/core/ui/{separator.d.ts → list/separator.d.ts} +1 -1
  164. package/types/core/ui/list/spacer.d.ts +9 -0
  165. package/types/core/ui/popup/popup.d.ts +2 -1
  166. package/types/core/view/view-with-toolbar.d.ts +4 -2
  167. package/types/jodit.d.ts +6 -6
  168. package/types/modules/file-browser/file-browser.d.ts +3 -2
  169. package/types/modules/file-browser/listeners/native-listeners.d.ts +5 -1
  170. package/types/modules/file-browser/ui/files/files.d.ts +10 -0
  171. package/types/modules/file-browser/ui/index.d.ts +7 -0
  172. package/types/modules/file-browser/ui/tree/tree.d.ts +10 -0
  173. package/types/modules/status-bar/status-bar.d.ts +6 -1
  174. package/types/modules/toolbar/button/button.d.ts +1 -1
  175. package/types/modules/toolbar/collection/collection.d.ts +5 -2
  176. package/types/modules/toolbar/collection/editor-collection.d.ts +9 -1
  177. package/types/modules/widget/tabs/tabs.d.ts +2 -1
  178. package/types/plugins/index.d.ts +1 -0
  179. package/types/plugins/inline-popup/inline-popup.d.ts +4 -0
  180. package/types/plugins/keyboard/delete.d.ts +2 -0
  181. package/types/plugins/ordered-list.d.ts +8 -1
  182. package/types/plugins/powered-by-jodit.d.ts +12 -0
  183. package/types/plugins/source/const.d.ts +6 -0
  184. package/types/plugins/source/editor/engines/ace.d.ts +1 -0
  185. package/types/plugins/source/source.d.ts +1 -0
  186. package/types/styles/icons/index.d.ts +2 -1
  187. package/types/types/storage.d.ts +3 -3
  188. package/types/types/{ajax.d.ts → types/ajax.d.ts} +0 -1
  189. package/types/types/{async.d.ts → types/async.d.ts} +0 -0
  190. package/types/types/{context.d.ts → types/context.d.ts} +0 -0
  191. package/types/types/{core.ts → types/core.ts} +0 -0
  192. package/types/types/{create.d.ts → types/create.d.ts} +0 -0
  193. package/types/types/{dialog.d.ts → types/dialog.d.ts} +0 -0
  194. package/types/types/{events.d.ts → types/events.d.ts} +0 -0
  195. package/types/types/{file-browser.d.ts → types/file-browser.d.ts} +13 -1
  196. package/types/types/{form.d.ts → types/form.d.ts} +0 -0
  197. package/types/types/{index.d.ts → types/index.d.ts} +0 -0
  198. package/types/types/{jodit.d.ts → types/jodit.d.ts} +4 -1
  199. package/types/types/{observe.d.ts → types/observe.d.ts} +0 -0
  200. package/types/types/{plugin.d.ts → types/plugin.d.ts} +0 -0
  201. package/types/types/{popup.d.ts → types/popup.d.ts} +1 -0
  202. package/types/types/{select.d.ts → types/select.d.ts} +2 -0
  203. package/types/types/{source.d.ts → types/source.d.ts} +0 -0
  204. package/types/types/{storage.ts → types/storage.ts} +3 -3
  205. package/types/types/{style.d.ts → types/style.d.ts} +8 -0
  206. package/types/types/{toolbar.d.ts → types/toolbar.d.ts} +9 -2
  207. package/types/types/{traits.d.ts → types/traits.d.ts} +0 -0
  208. package/types/types/{types.d.ts → types/types.d.ts} +1 -1
  209. package/types/types/{ui.d.ts → types/ui.d.ts} +23 -4
  210. package/types/types/{uploader.d.ts → types/uploader.d.ts} +0 -0
  211. package/types/types/{view.d.ts → types/view.d.ts} +1 -0
  212. package/src/core/selection/style/api/post-process-list-element.ts +0 -33
  213. package/src/core/selection/style/api/toggle-styles.ts +0 -74
  214. package/types/modules/file-browser/consts.d.ts +0 -8
@@ -0,0 +1,33 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ export default [
8
+ 'bold',
9
+ 'italic',
10
+ '|',
11
+ 'ul',
12
+ 'ol',
13
+ 'eraser',
14
+ '|',
15
+ 'fontsize',
16
+ 'brush',
17
+ 'paragraph',
18
+ '---',
19
+ 'image',
20
+ 'table',
21
+ '\n',
22
+ 'link',
23
+ '|',
24
+ 'align',
25
+ '|',
26
+ 'undo',
27
+ 'redo',
28
+ '|',
29
+ 'copyformat',
30
+ 'fullsize',
31
+ '---',
32
+ 'dots'
33
+ ];
@@ -181,6 +181,7 @@ export class inlinePopup extends Plugin {
181
181
  }
182
182
  )
183
183
  .on('hidePopup', this.hidePopup)
184
+ .on('showInlineToolbar', this.showInlineToolbar)
184
185
  .on(
185
186
  'showPopup',
186
187
  (
@@ -327,4 +328,20 @@ export class inlinePopup extends Plugin {
327
328
  this.onClick
328
329
  );
329
330
  }
331
+
332
+ /**
333
+ * Show the inline WYSIWYG toolbar editor.
334
+ */
335
+ @autobind
336
+ private showInlineToolbar(bound?: IBound) {
337
+ this.showPopup(() => {
338
+ if (bound) {
339
+ return bound;
340
+ }
341
+
342
+ const { range } = this.j.s;
343
+
344
+ return range.getBoundingClientRect();
345
+ }, 'toolbar');
346
+ }
330
347
  }
@@ -28,8 +28,10 @@ declare module '../../config' {
28
28
  hotkeys: {
29
29
  delete: string[];
30
30
  deleteWord: string[];
31
+ deleteSentence: string[];
31
32
  backspace: string[];
32
33
  backspaceWord: string[];
34
+ backspaceSentence: string[];
33
35
  };
34
36
  };
35
37
  }
@@ -39,11 +41,15 @@ Config.prototype.delete = {
39
41
  hotkeys: {
40
42
  delete: ['delete', 'cmd+backspace'],
41
43
  deleteWord: ['ctrl+delete', 'cmd+alt+backspace', 'ctrl+alt+backspace'],
44
+ deleteSentence: ['ctrl+shift+delete', 'cmd+shift+delete'],
42
45
  backspace: ['backspace'],
43
- backspaceWord: ['ctrl+backspace']
46
+ backspaceWord: ['ctrl+backspace'],
47
+ backspaceSentence: ['ctrl+shift+backspace', 'cmd+shift+backspace']
44
48
  }
45
49
  };
46
50
 
51
+ type DeleteMode = 'char' | 'word' | 'sentence';
52
+
47
53
  export class Delete extends Plugin {
48
54
  /** @override */
49
55
  override requires = ['hotkeys'];
@@ -85,12 +91,20 @@ export class Delete extends Plugin {
85
91
  }
86
92
  )
87
93
  .registerCommand('deleteWordButton', {
88
- exec: () => this.onDelete(false, true),
94
+ exec: () => this.onDelete(false, 'word'),
89
95
  hotkeys: jodit.o.delete.hotkeys.deleteWord
90
96
  })
91
97
  .registerCommand('backspaceWordButton', {
92
- exec: () => this.onDelete(true, true),
98
+ exec: () => this.onDelete(true, 'word'),
93
99
  hotkeys: jodit.o.delete.hotkeys.backspaceWord
100
+ })
101
+ .registerCommand('deleteSentenceButton', {
102
+ exec: () => this.onDelete(false, 'sentence'),
103
+ hotkeys: jodit.o.delete.hotkeys.deleteSentence
104
+ })
105
+ .registerCommand('backspaceSentenceButton', {
106
+ exec: () => this.onDelete(true, 'sentence'),
107
+ hotkeys: jodit.o.delete.hotkeys.backspaceSentence
94
108
  });
95
109
  }
96
110
 
@@ -127,7 +141,10 @@ export class Delete extends Plugin {
127
141
  /**
128
142
  * Listener BackSpace or Delete button
129
143
  */
130
- private onDelete(backspace: boolean, block: boolean = false): false | void {
144
+ private onDelete(
145
+ backspace: boolean,
146
+ mode: DeleteMode = 'char'
147
+ ): false | void {
131
148
  const sel = this.j.selection;
132
149
 
133
150
  if (!sel.isFocused()) {
@@ -154,7 +171,7 @@ export class Delete extends Plugin {
154
171
 
155
172
  if (
156
173
  this.checkRemoveInseparableElement(fakeNode, backspace) ||
157
- this.checkRemoveChar(fakeNode, backspace, block) ||
174
+ this.checkRemoveChar(fakeNode, backspace, mode) ||
158
175
  this.checkTableCell(fakeNode) ||
159
176
  this.checkRemoveEmptyParent(fakeNode, backspace) ||
160
177
  this.checkRemoveEmptyNeighbor(fakeNode, backspace) ||
@@ -213,7 +230,7 @@ export class Delete extends Plugin {
213
230
  private checkRemoveChar(
214
231
  fakeNode: Node,
215
232
  backspace: boolean,
216
- block: boolean
233
+ mode: DeleteMode
217
234
  ): void | true {
218
235
  const step = backspace ? -1 : 1;
219
236
  const anotherSibling: Nullable<Node> = getSibling(fakeNode, !backspace);
@@ -303,8 +320,13 @@ export class Delete extends Plugin {
303
320
 
304
321
  call(backspace ? Dom.after : Dom.before, sibling, fakeNode);
305
322
 
306
- if (block) {
307
- while (this.checkRemoveChar(fakeNode, backspace, false)) {}
323
+ if (
324
+ mode === 'sentence' ||
325
+ (mode === 'word' &&
326
+ removed !== ' ' &&
327
+ removed !== NBSP_SPACE)
328
+ ) {
329
+ this.checkRemoveChar(fakeNode, backspace, mode);
308
330
  }
309
331
 
310
332
  break;
@@ -93,13 +93,13 @@ export const formTemplate = (editor: IJodit): IUIForm => {
93
93
  [
94
94
  new UIButton(editor, {
95
95
  name: 'unlink',
96
- status: 'default',
96
+ variant: 'default',
97
97
  text: 'Unlink'
98
98
  }),
99
99
  new UIButton(editor, {
100
100
  name: 'insert',
101
101
  type: 'submit',
102
- status: 'primary',
102
+ variant: 'primary',
103
103
  text: 'Insert'
104
104
  })
105
105
  ],
@@ -13,10 +13,10 @@ import type {
13
13
  } from '../types/';
14
14
  import { Config } from '../config';
15
15
  import * as consts from '../core/constants';
16
- import { splitArray } from '../core/helpers/';
16
+ import { splitArray, toArray } from '../core/helpers/';
17
17
  import { makeCollection } from '../modules/toolbar/factory';
18
18
  import { UIList } from '../core/ui';
19
- import { flatButtonsSet, isButtonGroup } from '../core/ui/helpers/buttons';
19
+ import { flatButtonsSet } from '../core/ui/helpers/buttons';
20
20
 
21
21
  declare module '../config' {
22
22
  interface Config {
@@ -117,18 +117,14 @@ export function mobile(editor: IJodit): void {
117
117
  'getDiffButtons.mobile',
118
118
  (toolbar: IToolbarCollection): void | ButtonsGroups => {
119
119
  if (toolbar === editor.toolbar) {
120
- const buttons: ButtonsGroups = splitArray(editor.o.buttons),
121
- flatStore = flatButtonsSet(store);
122
-
123
- return buttons.reduce((acc, item) => {
124
- if (isButtonGroup(item)) {
125
- acc.push({
126
- ...item,
127
- buttons: item.buttons.filter(
128
- btn => !flatStore.has(btn)
129
- )
130
- });
131
- } else if (!flatStore.has(item)) {
120
+ const buttons = flatButtonsSet(
121
+ splitArray(editor.o.buttons),
122
+ editor
123
+ ),
124
+ flatStore = flatButtonsSet(store, editor);
125
+
126
+ return toArray(buttons).reduce((acc, item) => {
127
+ if (!flatStore.has(item)) {
132
128
  acc.push(item);
133
129
  }
134
130
 
@@ -8,6 +8,8 @@ import type { IControlType, IJodit, Nullable } from '../types';
8
8
  import { Config } from '../config';
9
9
  import { Dom } from '../core/dom';
10
10
  import { dataBind, toArray } from '../core/helpers';
11
+ import { Plugin } from '../core/plugin';
12
+ import { autobind } from '../core/decorators';
11
13
 
12
14
  const exec: IControlType<IJodit>['exec'] = (jodit, _, { control }): void => {
13
15
  const key = `button${control.command}`;
@@ -52,7 +54,44 @@ Config.prototype.controls.ol = {
52
54
  /**
53
55
  * Process commands insertOrderedList and insertUnOrderedList
54
56
  */
55
- export function orderedList(editor: IJodit): void {
57
+ export class orderedList extends Plugin {
58
+ override buttons: Plugin['buttons'] = [
59
+ {
60
+ name: 'ul',
61
+ group: 'list'
62
+ },
63
+ {
64
+ name: 'ol',
65
+ group: 'list'
66
+ }
67
+ ];
68
+
69
+ protected afterInit(jodit: IJodit): void {
70
+ jodit
71
+ .registerCommand('insertUnorderedList', this.onCommand)
72
+ .registerCommand('insertOrderedList', this.onCommand);
73
+ }
74
+
75
+ @autobind
76
+ private onCommand(command: string, _: unknown, type: string): false {
77
+ this.jodit.s.applyStyle(
78
+ {
79
+ listStyleType: type ?? null
80
+ },
81
+ {
82
+ element: command === 'insertunorderedlist' ? 'ul' : 'ol'
83
+ }
84
+ );
85
+
86
+ this.jodit.setEditorValue();
87
+
88
+ return false;
89
+ }
90
+
91
+ protected beforeDestruct(jodit: IJodit): void {}
92
+ }
93
+
94
+ export function orderedList1(editor: IJodit): void {
56
95
  const isOurCommand = (command: string) =>
57
96
  /insert(un)?orderedlist/i.test(command),
58
97
  getListWrapper = () =>
@@ -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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { IJodit } from '../types';
8
+
9
+ declare module '../config' {
10
+ interface Config {
11
+ hidePoweredByJodit: boolean;
12
+ }
13
+ }
14
+
15
+ export function poweredByJodit(jodit: IJodit): void {
16
+ if (
17
+ !jodit.o.hidePoweredByJodit &&
18
+ !jodit.o.inline &&
19
+ (jodit.o.showCharsCounter ||
20
+ jodit.o.showWordsCounter ||
21
+ jodit.o.showXPathInStatusbar)
22
+ ) {
23
+ jodit.hookStatus('ready', () => {
24
+ jodit.statusbar.append(
25
+ jodit.create.fromHTML(
26
+ `<a
27
+ tabindex="-1"
28
+ style="text-transform: uppercase"
29
+ class="jodit-status-bar-link"
30
+ target="_blank"
31
+ href="https://xdsoft.net/jodit/">
32
+ Powered by Jodit
33
+ </a>`
34
+ ),
35
+ true
36
+ );
37
+ });
38
+ }
39
+ }
@@ -6,58 +6,12 @@
6
6
 
7
7
  import type { IControlType, IDialog, IJodit } from '../../types';
8
8
  import { Config } from '../../config';
9
- import { css } from '../../core/helpers';
9
+ import { attr, css } from '../../core/helpers';
10
10
  import * as consts from '../../core/constants';
11
11
 
12
12
  Config.prototype.controls.preview = {
13
13
  icon: 'eye',
14
- exec: (editor: IJodit) => {
15
- const dialog = <IDialog>editor.getInstance('Dialog', {
16
- language: editor.o.language,
17
- theme: editor.o.theme
18
- });
19
-
20
- const div = editor.c.div();
21
- css(div, {
22
- padding: 16
23
- });
24
-
25
- if (editor.iframe) {
26
- const iframe = editor.create.element('iframe');
27
-
28
- css(iframe, {
29
- minWidth: 800,
30
- minHeight: 600,
31
- border: 0
32
- });
33
-
34
- div.appendChild(iframe);
35
- dialog.open(div, editor.i18n('Preview'));
36
-
37
- const mywindow = iframe.contentWindow;
38
-
39
- if (mywindow) {
40
- editor.e.fire(
41
- 'generateDocumentStructure.iframe',
42
- mywindow.document,
43
- editor
44
- );
45
-
46
- mywindow.document.body.innerHTML = editor.value;
47
- }
48
- } else {
49
- css(div, {
50
- minWidth: 1024,
51
- minHeight: 600,
52
- border: 0
53
- });
54
-
55
- div.innerHTML = editor.value;
56
- dialog.open(div, editor.i18n('Preview'));
57
- }
58
-
59
- dialog.setModal(true);
60
- },
14
+ command: 'preview',
61
15
  mode: consts.MODE_SOURCE + consts.MODE_WYSIWYG,
62
16
  tooltip: 'Preview'
63
17
  } as IControlType;
@@ -66,4 +20,105 @@ export function preview(editor: IJodit): void {
66
20
  editor.registerButton({
67
21
  name: 'preview'
68
22
  });
23
+
24
+ editor.registerCommand(
25
+ 'preview',
26
+ (_: any, _1: any, defaultValue: string) => {
27
+ const dialog = <IDialog>editor.getInstance('Dialog', {
28
+ language: editor.o.language,
29
+ theme: editor.o.theme
30
+ });
31
+
32
+ const div = editor.c.div();
33
+ css(div, {
34
+ position: 'relative',
35
+ padding: 16
36
+ });
37
+
38
+ const value =
39
+ defaultValue ||
40
+ editor.value ||
41
+ `<div style='position: absolute;left:50%;top:50%;transform: translateX(-50%) translateY(-50%);color:#ccc;'>${editor.i18n(
42
+ 'Empty'
43
+ )}</div>`;
44
+
45
+ if (editor.iframe) {
46
+ const iframe = editor.create.element('iframe');
47
+
48
+ css(iframe, {
49
+ minWidth: 800,
50
+ minHeight: 600,
51
+ border: 0
52
+ });
53
+
54
+ div.appendChild(iframe);
55
+ dialog.open(div, editor.i18n('Preview'));
56
+
57
+ const mywindow = iframe.contentWindow;
58
+
59
+ if (mywindow) {
60
+ editor.e.fire(
61
+ 'generateDocumentStructure.iframe',
62
+ mywindow.document,
63
+ editor
64
+ );
65
+
66
+ mywindow.document.body.innerHTML = value;
67
+ }
68
+ } else {
69
+ css(div, {
70
+ minWidth: 1024,
71
+ minHeight: 600,
72
+ border: 0
73
+ });
74
+
75
+ dialog.setSize(1024, 600).open(div, editor.i18n('Preview'));
76
+
77
+ const setHTML = (box: HTMLElement, value: string): void => {
78
+ const dv = editor.c.div();
79
+ dv.innerHTML = value;
80
+
81
+ for (let i = 0; i < dv.children.length; i += 1) {
82
+ const c = dv.children[i];
83
+
84
+ const newNode = document.createElement(c.nodeName);
85
+
86
+ for (let j = 0; j < c.attributes.length; j += 1) {
87
+ attr(
88
+ newNode,
89
+ c.attributes[j].nodeName,
90
+ c.attributes[j].nodeValue
91
+ );
92
+ }
93
+
94
+ if (c.children.length === 0) {
95
+ switch (c.nodeName) {
96
+ case 'SCRIPT':
97
+ if (c.textContent) {
98
+ newNode.textContent = c.textContent;
99
+ }
100
+ break;
101
+
102
+ default:
103
+ if (c.innerHTML) {
104
+ newNode.innerHTML = c.innerHTML;
105
+ }
106
+ break;
107
+ }
108
+ } else {
109
+ setHTML(newNode, c.innerHTML);
110
+ }
111
+
112
+ try {
113
+ box.appendChild(newNode);
114
+ } catch {}
115
+ }
116
+ };
117
+
118
+ setHTML(div, value);
119
+ }
120
+
121
+ dialog.setModal(true);
122
+ }
123
+ );
69
124
  }
@@ -9,7 +9,10 @@
9
9
  :root {
10
10
  --viewer_width: 70px;
11
11
  --viewer_height: 24px;
12
- --resizer-handle-size: var(--padding-default);
12
+ --resizer-handle-size: 10px;
13
+ --resizer-border-color: #98c1f1;
14
+ --resizer-handle-color: #5ba4f3;
15
+ --resizer-handle-hover-color: #537ebb;
13
16
  }
14
17
 
15
18
  [data-jodit_iframe_wrapper] {
@@ -37,8 +40,9 @@
37
40
  left: 0;
38
41
  width: 100px;
39
42
  height: 100px;
40
- border: 1px solid var(--color-border-dark);
43
+ box-sizing: border-box;
41
44
  font-size: 0;
45
+ outline: 3px solid var(--resizer-border-color);
42
46
  pointer-events: none;
43
47
 
44
48
  * {
@@ -68,7 +72,7 @@
68
72
  transition: opacity 0.2s linear;
69
73
  }
70
74
 
71
- > i {
75
+ > div {
72
76
  position: absolute;
73
77
  z-index: 4;
74
78
  display: inline-block;
@@ -76,12 +80,11 @@
76
80
  width: var(--resizer-handle-size);
77
81
  height: var(--resizer-handle-size);
78
82
 
79
- border: 1px solid var(--color-border-dark);
80
- background-color: var(--color-background-gray);
83
+ background-color: var(--resizer-handle-color);
81
84
  pointer-events: all;
82
85
 
83
86
  &:hover {
84
- background-color: var(--color-background-gray-hover);
87
+ background-color: var(--resizer-handle-hover-color);
85
88
  }
86
89
 
87
90
  &:nth-child(1) {
@@ -110,7 +113,7 @@
110
113
 
111
114
  @media (max-width: @screen-sm) {
112
115
  :root {
113
- --resizer-handle-size: calc(var(--padding-default) * 2);
116
+ --resizer-handle-size: calc(var(--resizer-handle-size) * 2);
114
117
  }
115
118
  }
116
119
  }
@@ -91,10 +91,10 @@ export class resizer extends Plugin {
91
91
 
92
92
  private rect = this.j.c.fromHTML(
93
93
  `<div class="jodit-resizer">
94
- <i class="jodit-resizer-topleft"></i>
95
- <i class="jodit-resizer-topright"></i>
96
- <i class="jodit-resizer-bottomright"></i>
97
- <i class="jodit-resizer-bottomleft"></i>
94
+ <div class="jodit-resizer__top-left"></div>
95
+ <div class="jodit-resizer__top-right"></div>
96
+ <div class="jodit-resizer__bottom-right"></div>
97
+ <div class="jodit-resizer__bottom-left"></div>
98
98
  <span>100x100</span>
99
99
  </div>`
100
100
  );
@@ -104,7 +104,7 @@ export class resizer extends Plugin {
104
104
 
105
105
  /** @override */
106
106
  protected afterInit(editor: IJodit): void {
107
- $$('i', this.rect).forEach((resizeHandle: HTMLElement) => {
107
+ $$('div', this.rect).forEach((resizeHandle: HTMLElement) => {
108
108
  editor.e.on(
109
109
  resizeHandle,
110
110
  'mousedown.resizer touchstart.resizer',
@@ -458,17 +458,15 @@ export class resizer extends Plugin {
458
458
 
459
459
  if (this.element && this.rect) {
460
460
  const workplacePosition = this.getWorkplacePosition();
461
- const pos: IBound = offset(this.element, this.j, this.j.ed),
462
- left: number = parseInt(this.rect.style.left || '0', 10),
463
- top: number = parseInt(this.rect.style.top || '0', 10),
464
- w: number = this.rect.offsetWidth,
465
- h: number = this.rect.offsetHeight;
466
461
 
467
- // 1 - because need move border higher and toWYSIWYG the left than the picture
468
- // 2 - in box-sizing: border-box mode width is real width indifferent by border-width.
462
+ const pos = offset(this.element, this.j, this.j.ed),
463
+ left = parseInt(this.rect.style.left || '0', 10),
464
+ top = parseInt(this.rect.style.top || '0', 10),
465
+ w = this.rect.offsetWidth,
466
+ h = this.rect.offsetHeight;
469
467
 
470
- const newTop: number = pos.top - 1 - workplacePosition.top,
471
- newLeft: number = pos.left - 1 - workplacePosition.left;
468
+ const newTop = pos.top - workplacePosition.top,
469
+ newLeft = pos.left - workplacePosition.left;
472
470
 
473
471
  if (
474
472
  top !== newTop ||
@@ -8,6 +8,7 @@ import type { IJodit, IPointBound } from '../../types';
8
8
  import { Plugin } from '../../core/plugin';
9
9
  import { Dom } from '../../core/dom';
10
10
  import { autobind } from '../../core/decorators';
11
+ import { Icon } from '../../core/ui';
11
12
 
12
13
  @autobind
13
14
  export class resizeHandler extends Plugin {
@@ -27,6 +28,8 @@ export class resizeHandler extends Plugin {
27
28
  (height !== 'auto' || width !== 'auto') &&
28
29
  (allowResizeX || allowResizeY)
29
30
  ) {
31
+ editor.statusbar.setMod('resize-handle', true);
32
+
30
33
  editor.e
31
34
  .on('toggleFullSize.resizeHandler', () => {
32
35
  this.handle.style.display = editor.isFullSize
@@ -114,7 +117,7 @@ export class resizeHandler extends Plugin {
114
117
  */
115
118
  private handle = this.j.c.div(
116
119
  'jodit-editor__resize',
117
- '<span tabindex="-1"></span>'
120
+ Icon.get('resize_handler')
118
121
  );
119
122
 
120
123
  /** @override **/
@@ -4,6 +4,7 @@
4
4
  * Copyright (c) 2013-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
5
  */
6
6
  @import (reference) '../../styles/variables';
7
+ @import (reference) '../../styles/mixins';
7
8
 
8
9
  @resizer-size: 7px;
9
10
 
@@ -19,24 +20,6 @@
19
20
  }
20
21
 
21
22
  .jodit-editor__resize {
22
- position: relative;
23
-
24
- span {
25
- position: absolute;
26
- right: 0;
27
- bottom: 0;
28
- overflow: hidden;
29
-
30
- width: 0;
31
- height: 0;
32
-
33
- border-width: @resizer-size @resizer-size 0 0;
34
- border-style: dashed solid dashed dashed;
35
- border-color: rgba(0, 0, 0, 0) var(--color-border) rgba(0, 0, 0, 0)
36
- rgba(0, 0, 0, 0);
37
-
38
- cursor: se-resize;
39
- user-select: none;
40
- }
23
+ .resize-handle();
41
24
  }
42
25
  }
@@ -29,8 +29,12 @@ export class size extends Plugin {
29
29
  .on(editor.ow, 'load.size', this.resizeWorkspaces)
30
30
  .on(
31
31
  'afterInit.size resize.size afterUpdateToolbar.size ' +
32
- 'scroll.size afterResize.size toggleFullSize.size',
32
+ 'scroll.size afterResize.size',
33
33
  this.resizeWorkspaces
34
+ )
35
+ .on(
36
+ 'toggleFullSize.size toggleToolbar.size',
37
+ this.resizeWorkspaceImd
34
38
  );
35
39
 
36
40
  this.initialize();
@@ -131,6 +135,7 @@ export class size extends Plugin {
131
135
  /**
132
136
  * Calculate workspace height
133
137
  */
138
+ @autobind
134
139
  private resizeWorkspaceImd() {
135
140
  if (!this.j || this.j.isDestructed || !this.j.o || this.j.o.inline) {
136
141
  return;
@@ -0,0 +1,7 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ export const SOURCE_CONSUMER = 'source-consumer';
@@ -22,6 +22,10 @@ export class AceEditor
22
22
  /**
23
23
  * Proxy Method
24
24
  */
25
+ private proxyOnBlur = (e: MouseEvent) => {
26
+ this.j.e.fire('blur', e);
27
+ };
28
+
25
29
  private proxyOnFocus = (e: MouseEvent) => {
26
30
  this.j.e.fire('focus', e);
27
31
  };
@@ -133,6 +137,7 @@ export class AceEditor
133
137
  this.instance.on('change', this.toWYSIWYG as any);
134
138
  this.instance.on('focus', this.proxyOnFocus);
135
139
  this.instance.on('mousedown', this.proxyOnMouseDown);
140
+ this.instance.on('blur', this.proxyOnBlur);
136
141
 
137
142
  if (editor.getRealMode() !== constants.MODE_WYSIWYG) {
138
143
  this.setValue(this.getValue());