jodit 3.9.3 → 3.9.4

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 (85) hide show
  1. package/.idea/workspace.xml +129 -121
  2. package/CHANGELOG.MD +21 -5
  3. package/build/jodit.css +92 -33
  4. package/build/jodit.es2018.css +65 -29
  5. package/build/jodit.es2018.en.css +65 -29
  6. package/build/jodit.es2018.en.js +854 -466
  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 +854 -466
  10. package/build/jodit.es2018.min.css +1 -1
  11. package/build/jodit.es2018.min.js +1 -1
  12. package/build/jodit.js +1804 -1360
  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 +1 -1
  17. package/src/config.ts +1 -1
  18. package/src/core/dom.ts +10 -3
  19. package/src/core/helpers/size/index.ts +1 -0
  20. package/src/core/helpers/size/object-size.ts +22 -0
  21. package/src/core/selection/select.ts +1 -0
  22. package/src/core/selection/style/api/{get-closest-wrapper.ts → extract.ts} +26 -43
  23. package/src/core/selection/style/api/finite-state-machine.ts +66 -0
  24. package/src/core/selection/style/api/index.ts +12 -5
  25. package/src/core/selection/style/api/{check-special-elements.ts → is-inside-invisible-element.ts} +1 -1
  26. package/src/core/selection/style/api/is-suit-element.ts +12 -1
  27. package/src/core/selection/style/api/toggle/toggle-css.ts +134 -0
  28. package/src/core/selection/style/api/toggle/toggle-ordered-list.ts +49 -0
  29. package/src/core/selection/style/api/toggle-commit-styles.ts +27 -0
  30. package/src/core/selection/style/api/wrap-and-commit-style.ts +68 -0
  31. package/src/core/selection/style/api/wrap-ordered-list.ts +37 -0
  32. package/src/core/selection/style/api/wrap-unwrapped-text.ts +1 -4
  33. package/src/core/selection/style/apply-style.ts +161 -97
  34. package/src/core/selection/style/commit-style.ts +13 -0
  35. package/src/core/ui/button/button/button.less +2 -0
  36. package/src/core/ui/helpers/buttons.ts +14 -6
  37. package/src/core/ui/list/list.less +1 -0
  38. package/src/core/ui/popup/popup.less +5 -3
  39. package/src/core/view/view-with-toolbar.ts +4 -0
  40. package/src/modules/status-bar/status-bar.less +27 -1
  41. package/src/modules/status-bar/status-bar.ts +15 -1
  42. package/src/modules/widget/tabs/tabs.less +1 -0
  43. package/src/plugins/bold.ts +2 -2
  44. package/src/plugins/font.ts +11 -1
  45. package/src/plugins/index.ts +1 -0
  46. package/src/plugins/mobile.ts +10 -14
  47. package/src/plugins/ordered-list.ts +40 -1
  48. package/src/plugins/powered-by-jodit.ts +39 -0
  49. package/src/plugins/print/preview.ts +9 -2
  50. package/src/plugins/resizer/resizer.less +10 -7
  51. package/src/plugins/resizer/resizer.ts +12 -14
  52. package/src/plugins/size/assests/resize-handler.svg +4 -0
  53. package/src/plugins/size/resize-handler.ts +4 -4
  54. package/src/plugins/size/size.less +6 -8
  55. package/src/plugins/source/source.ts +15 -1
  56. package/src/styles/themes/dark.less +11 -1
  57. package/src/types/style.d.ts +2 -0
  58. package/src/types/toolbar.d.ts +2 -1
  59. package/src/types/view.d.ts +1 -0
  60. package/types/core/dom.d.ts +2 -1
  61. package/types/core/helpers/size/index.d.ts +1 -0
  62. package/types/core/helpers/size/object-size.d.ts +7 -0
  63. package/types/core/selection/style/api/{get-closest-wrapper.d.ts → extract.d.ts} +6 -5
  64. package/types/core/selection/style/api/finite-state-machine.d.ts +21 -0
  65. package/types/core/selection/style/api/index.d.ts +12 -5
  66. package/types/core/selection/style/api/{check-special-elements.d.ts → is-inside-invisible-element.d.ts} +1 -1
  67. package/types/core/selection/style/api/is-suit-element.d.ts +9 -0
  68. package/types/core/selection/style/api/toggle/toggle-css.d.ts +11 -0
  69. package/types/core/selection/style/api/toggle/toggle-ordered-list.d.ts +11 -0
  70. package/types/core/selection/style/api/{toggle-styles.d.ts → toggle-commit-styles.d.ts} +1 -3
  71. package/types/core/selection/style/api/{post-process-list-element.d.ts → wrap-and-commit-style.d.ts} +3 -3
  72. package/types/core/selection/style/api/wrap-ordered-list.d.ts +12 -0
  73. package/types/core/selection/style/apply-style.d.ts +1 -4
  74. package/types/core/selection/style/commit-style.d.ts +7 -0
  75. package/types/core/ui/helpers/buttons.d.ts +2 -2
  76. package/types/core/view/view-with-toolbar.d.ts +2 -1
  77. package/types/modules/status-bar/status-bar.d.ts +6 -1
  78. package/types/plugins/index.d.ts +1 -0
  79. package/types/plugins/ordered-list.d.ts +8 -1
  80. package/types/plugins/powered-by-jodit.d.ts +12 -0
  81. package/types/types/style.d.ts +2 -0
  82. package/types/types/toolbar.d.ts +2 -1
  83. package/types/types/view.d.ts +1 -0
  84. package/src/core/selection/style/api/post-process-list-element.ts +0 -33
  85. package/src/core/selection/style/api/toggle-styles.ts +0 -74
@@ -4,132 +4,196 @@
4
4
  * Copyright (c) 2013-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
5
  */
6
6
 
7
- import type { IJodit, Nullable } from '../../../types';
7
+ import type { IJodit, Nullable, CanUndef, CommitMode } from '../../../types';
8
8
  import type { CommitStyle } from './commit-style';
9
- import { Dom } from '../../dom';
10
- import { attr, css, normalizeNode } from '../../helpers';
9
+ import { normalizeNode } from '../../helpers';
11
10
  import {
12
11
  getSuitParent,
13
12
  getSuitChild,
14
- checkSpecialElements,
15
- getClosestWrapper,
16
- unwrapChildren,
17
- wrapUnwrappedText,
18
- postProcessListElement,
19
- toggleStyles
13
+ isInsideInvisibleElement,
14
+ toggleCommitStyles,
15
+ unwrapChildren
16
+ } from './api';
17
+ import { CHANGE, INITIAL, REPLACE, UNWRAP, WRAP } from './commit-style';
18
+ import { Dom } from '../../dom';
19
+ import {
20
+ toggleOrderedList,
21
+ wrapAndCommitStyle,
22
+ isSuitElement,
23
+ extractSelectedPart,
24
+ toggleCSS,
25
+ FiniteStateMachine
20
26
  } from './api';
21
27
 
22
- /**
23
- * Apply options to selection
24
- */
25
- export function ApplyStyle(jodit: IJodit, style: CommitStyle): void {
26
- const { s: sel } = jodit,
27
- rng = () => sel.createRange();
28
+ export function ApplyStyle(jodit: IJodit, cs: CommitStyle): void {
29
+ const { s: sel, editor } = jodit;
30
+
31
+ const fsm = new FiniteStateMachine('start', {
32
+ start: {
33
+ start() {
34
+ sel.save();
35
+ normalizeNode(editor.firstChild); // FF fix for test "commandsTest - Exec command "bold"
36
+ this.setState('generator');
37
+ }
38
+ },
39
+
40
+ generator: {
41
+ initGenerator() {
42
+ return jodit.s.wrapInTagGen();
43
+ },
28
44
 
29
- let wrap: Nullable<boolean> = null;
45
+ nextFont(gen: Generator<HTMLElement>): CanUndef<HTMLElement> {
46
+ const font = gen.next();
30
47
 
31
- sel.save();
48
+ if (font.done) {
49
+ this.setState('end');
50
+ return;
51
+ }
32
52
 
33
- normalizeNode(sel.area.firstChild); // FF fix for test "commandsTest - Exec command "bold"
53
+ if (
54
+ isInsideInvisibleElement(font.value, editor) ||
55
+ Dom.isEmptyContent(font.value)
56
+ ) {
57
+ return;
58
+ }
34
59
 
35
- const gen = jodit.s.wrapInTagGen();
36
- let font = gen.next();
60
+ this.setState('check');
37
61
 
38
- while (!font.done) {
39
- wrap = applyToElement(style, font.value, rng, jodit, wrap);
40
- font = gen.next();
41
- }
62
+ return font.value;
63
+ }
64
+ },
42
65
 
43
- sel.restore();
44
- }
66
+ check: {
67
+ work(font: HTMLElement): Nullable<HTMLElement> {
68
+ let elm =
69
+ getSuitParent(cs, font, jodit.editor) ||
70
+ getSuitChild(cs, font);
45
71
 
46
- /**
47
- * Apply options to all selected fragment
48
- * @param font - a fake element that wraps all parts of the selection
49
- */
50
- function applyToElement(
51
- style: CommitStyle,
52
- font: HTMLElement,
53
- range: () => Range,
54
- jodit: IJodit,
55
- wrap: Nullable<boolean>
56
- ): Nullable<boolean> {
57
- const root = jodit.editor;
58
-
59
- if (checkSpecialElements(font, root)) {
60
- return wrap;
61
- }
72
+ if (elm) {
73
+ this.setState('wholeElement');
74
+ return elm;
75
+ }
62
76
 
63
- const toggleNode =
64
- getSuitParent(style, font, root) ||
65
- getSuitChild(style, font) ||
66
- getClosestWrapper(style, font, root, range);
77
+ elm = Dom.closest(
78
+ font,
79
+ node => isSuitElement(cs, node, true),
80
+ jodit.editor
81
+ );
67
82
 
68
- if (toggleNode) {
69
- return toggleStyles(style, toggleNode, wrap);
70
- }
83
+ if (elm) {
84
+ if (!cs.elementIsBlock) {
85
+ extractSelectedPart(elm, font, jodit);
86
+ }
87
+ }
71
88
 
72
- if (unwrapChildren(style, font)) {
73
- return wrap;
74
- }
89
+ if (cs.elementIsList && Dom.isTag(elm, ['ul', 'ol'])) {
90
+ this.setState('orderList');
91
+ return font;
92
+ }
75
93
 
76
- if (wrap == null) {
77
- wrap = true;
78
- }
94
+ if (elm) {
95
+ this.setState('wholeElement');
96
+ return elm;
97
+ }
79
98
 
80
- if (!wrap) {
81
- return wrap;
82
- }
99
+ if (unwrapChildren(cs, font)) {
100
+ this.setState('endProcess');
101
+ return null;
102
+ }
83
103
 
84
- let wrapper = font;
104
+ this.setState('wrap');
105
+ return font;
106
+ }
107
+ },
85
108
 
86
- if (style.elementIsBlock) {
87
- const ulReg = /^(ul|ol|li|td|th|tr|tbody|table)$/i;
109
+ wholeElement: {
110
+ toggleStyles(toggleElm: HTMLElement): void {
111
+ let mode: CommitMode = INITIAL;
88
112
 
89
- const box = Dom.up(
90
- font,
91
- node => {
92
- if (Dom.isBlock(node)) {
93
- if (
94
- ulReg.test(style.element) ||
95
- !ulReg.test(node.nodeName)
96
- ) {
97
- return true;
98
- }
113
+ if (toggleCommitStyles(cs, toggleElm)) {
114
+ mode = UNWRAP;
115
+ } else {
116
+ mode = toggleCSS(cs, toggleElm, jodit, mode);
99
117
  }
100
118
 
101
- return false;
102
- },
103
- root
104
- );
119
+ this.setState('generator', mode);
120
+ }
121
+ },
105
122
 
106
- if (box) {
107
- wrapper = box;
108
- } else {
109
- wrapper = wrapUnwrappedText(style, font, jodit, range);
110
- }
111
- }
123
+ orderList: {
124
+ toggleStyles(font: HTMLElement): void {
125
+ let mode: CommitMode = INITIAL;
126
+ const li = Dom.closest(font, 'li', jodit.editor);
112
127
 
113
- const newWrapper = Dom.replace(
114
- wrapper,
115
- style.element,
116
- jodit.createInside,
117
- true
118
- );
128
+ if (!li) {
129
+ this.setState('generator');
130
+ return;
131
+ }
119
132
 
120
- attr(newWrapper, 'size', null);
133
+ const ul = Dom.closest(font, ['ul', 'ol'], jodit.editor);
121
134
 
122
- if (style.elementIsBlock) {
123
- postProcessListElement(style, newWrapper, jodit.createInside);
124
- }
135
+ if (!ul) {
136
+ this.setState('generator');
137
+ return;
138
+ }
125
139
 
126
- if (style.options.style && style.elementIsDefault) {
127
- css(newWrapper, style.options.style);
128
- }
140
+ mode = toggleOrderedList(cs, li, jodit, mode);
141
+
142
+ if (mode === REPLACE || mode === UNWRAP || mode === CHANGE) {
143
+ this.setState('endWhile');
144
+ return;
145
+ }
146
+
147
+ this.setState('generator');
148
+ }
149
+ },
129
150
 
130
- if (style.options.className) {
131
- newWrapper.classList.toggle(style.options.className);
151
+ wrap: {
152
+ toggleStyles(font: HTMLElement): void {
153
+ if (this.getSubState() !== 'unwrap') {
154
+ const toggleElm = wrapAndCommitStyle(cs, font, jodit);
155
+ toggleCSS(cs, toggleElm, jodit, WRAP);
156
+ }
157
+
158
+ this.setState('generator');
159
+ }
160
+ },
161
+
162
+ endWhile: {
163
+ nextFont(gen: Generator<HTMLElement>): void {
164
+ const font = gen.next();
165
+
166
+ if (font.done) {
167
+ this.setState('end');
168
+ }
169
+ }
170
+ },
171
+
172
+ endProcess: {
173
+ toggleStyles() {
174
+ this.setState('generator');
175
+ }
176
+ },
177
+
178
+ end: {
179
+ finalize() {
180
+ sel.restore();
181
+ }
182
+ }
183
+ });
184
+
185
+ fsm.dispatch('start');
186
+
187
+ const gen = fsm.dispatch('initGenerator');
188
+
189
+ while (fsm.getState() !== 'end') {
190
+ const font = fsm.dispatch<HTMLElement>('nextFont', gen);
191
+
192
+ if (font) {
193
+ const wrapper = fsm.dispatch<HTMLElement>('work', font);
194
+ fsm.dispatch('toggleStyles', wrapper);
195
+ }
132
196
  }
133
197
 
134
- return wrap;
198
+ fsm.dispatch('finalize', gen);
135
199
  }
@@ -8,7 +8,20 @@ import type { HTMLTagNames, IJodit, IStyleOptions } from '../../../types';
8
8
  import { IS_BLOCK } from '../../constants';
9
9
  import { ApplyStyle } from './apply-style';
10
10
 
11
+ export const WRAP = 'wrap';
12
+ export const UNWRAP = 'unwrap';
13
+ export const CHANGE = 'change';
14
+ export const UNSET = 'unset';
15
+ export const INITIAL = 'initial';
16
+ export const REPLACE = 'replace';
17
+
11
18
  export class CommitStyle {
19
+ get elementIsList(): boolean {
20
+ return Boolean(
21
+ this.options.element && ['ul', 'ol'].includes(this.options.element)
22
+ );
23
+ }
24
+
12
25
  get element(): HTMLTagNames {
13
26
  return this.options.element || this.defaultTag;
14
27
  }
@@ -31,6 +31,8 @@
31
31
  }
32
32
 
33
33
  .jodit-ui-button-interaction() {
34
+ cursor: pointer;
35
+
34
36
  &:hover:not([disabled]) {
35
37
  background-color: var(--color-button-background-hover);
36
38
  opacity: 1;
@@ -8,7 +8,8 @@ import type {
8
8
  Buttons,
9
9
  ButtonsGroup,
10
10
  ButtonsGroups,
11
- IControlType
11
+ IControlType,
12
+ IJodit
12
13
  } from '../../../types';
13
14
  import { isArray } from '../../helpers/checker';
14
15
 
@@ -18,14 +19,20 @@ export const isButtonGroup = (
18
19
  return isArray((<ButtonsGroup>item).buttons);
19
20
  };
20
21
 
21
- export const flatButtonsSet = (
22
- buttons: ButtonsGroups
23
- ): Set<string | IControlType> =>
24
- new Set(
22
+ export function flatButtonsSet(
23
+ buttons: ButtonsGroups,
24
+ jodit: IJodit
25
+ ): Set<string | IControlType> {
26
+ const groups = jodit.getRegisteredButtonGroups();
27
+
28
+ return new Set(
25
29
  buttons.reduce(
26
30
  (acc: Buttons, item: ButtonsGroup | string | IControlType) => {
27
31
  if (isButtonGroup(item)) {
28
- acc.push(...(<ButtonsGroup>item).buttons);
32
+ acc = acc.concat([
33
+ ...(<ButtonsGroup>item).buttons,
34
+ ...(groups[item.group] ?? [])
35
+ ]);
29
36
  } else {
30
37
  acc.push(item);
31
38
  }
@@ -35,3 +42,4 @@ export const flatButtonsSet = (
35
42
  [] as Buttons
36
43
  )
37
44
  );
45
+ }
@@ -25,6 +25,7 @@
25
25
  width: 100%;
26
26
  height: auto;
27
27
  min-height: var(--button-size);
28
+ cursor: pointer;
28
29
  }
29
30
 
30
31
  &__text:not(:empty) {
@@ -7,16 +7,18 @@
7
7
  @import (reference) '../../../styles/variables';
8
8
  @import (reference) '../../../styles/mixins';
9
9
 
10
- .jodit-popup {
11
- --box-shadow: 0 4px 1px -2px rgba(76, 76, 76, 0.2),
10
+ :root {
11
+ --popup-box-shadow: 0 4px 1px -2px rgba(76, 76, 76, 0.2),
12
12
  0 3px 3px 0 rgba(76, 76, 76, 0.15), 0 1px 4px 0 rgba(76, 76, 76, 0.13);
13
+ }
13
14
 
15
+ .jodit-popup {
14
16
  .jodit-box();
15
17
 
16
18
  position: fixed;
17
19
  z-index: var(--z-index-popup);
18
20
  display: inline-block;
19
- box-shadow: var(--box-shadow);
21
+ box-shadow: var(--popup-box-shadow);
20
22
  transform: translate3d(0, 0, 0);
21
23
 
22
24
  &__content {
@@ -75,6 +75,10 @@ export abstract class ViewWithToolbar extends View implements IViewWithToolbar {
75
75
  registeredButtons: Set<IPluginButton> = new Set();
76
76
  private groupToButtons: IDictionary<string[]> = {};
77
77
 
78
+ getRegisteredButtonGroups(): IDictionary<string[]> {
79
+ return this.groupToButtons;
80
+ }
81
+
78
82
  /**
79
83
  * Register button for group
80
84
  */
@@ -10,12 +10,24 @@
10
10
  .jodit-status-bar {
11
11
  display: flex;
12
12
  overflow: hidden;
13
+ height: 20px;
14
+
13
15
  align-items: center;
14
16
  justify-content: flex-start;
17
+
15
18
  padding: 0 calc(var(--padding-default) / 2);
19
+
20
+ &_resize-handle_true {
21
+ padding-right: 14px;
22
+ }
23
+
16
24
  background-color: var(--color-panel);
17
25
  border-radius: 0 0 var(--border-radius-default) var(--border-radius-default);
26
+
27
+ color: var(--color-text-icons);
28
+
18
29
  font-size: var(--font-size-small);
30
+ text-transform: uppercase;
19
31
 
20
32
  &::before {
21
33
  flex: auto;
@@ -48,11 +60,25 @@
48
60
 
49
61
  &:hover {
50
62
  background-color: var(--color-background-gray);
51
- color: var(--color-text);
52
63
  text-decoration: none;
53
64
  }
54
65
  }
55
66
  }
67
+
68
+ a.jodit-status-bar-link {
69
+ cursor: pointer;
70
+
71
+ &,
72
+ &:hover,
73
+ &:visited {
74
+ background-color: transparent;
75
+ color: var(--color-text-icons);
76
+ }
77
+
78
+ &:hover {
79
+ text-decoration: underline;
80
+ }
81
+ }
56
82
  }
57
83
 
58
84
  .jodit-workplace + .jodit-status-bar:not(:empty) {
@@ -6,9 +6,10 @@
6
6
 
7
7
  import './status-bar.less';
8
8
 
9
- import type { IJodit, IStatusBar } from '../../types';
9
+ import type { IJodit, IStatusBar, IDictionary } from '../../types';
10
10
  import { ViewComponent, STATUSES } from '../../core/component';
11
11
  import { Dom } from '../../core/dom';
12
+ import { Mods } from '../../core/traits';
12
13
 
13
14
  export class StatusBar extends ViewComponent<IJodit> implements IStatusBar {
14
15
  className(): string {
@@ -38,6 +39,19 @@ export class StatusBar extends ViewComponent<IJodit> implements IStatusBar {
38
39
  return !this.container.classList.contains('jodit_hidden');
39
40
  }
40
41
 
42
+ readonly mods: IDictionary<string | boolean | null> = {};
43
+
44
+ /** @see [[Mods.setMod]] */
45
+ setMod(name: string, value: string | boolean | null): this {
46
+ Mods.setMod.call(this, name, value);
47
+ return this;
48
+ }
49
+
50
+ /** @see [[Mods.getMod]] */
51
+ getMod(name: string): string | boolean | null {
52
+ return Mods.getMod.call(this, name);
53
+ }
54
+
41
55
  /**
42
56
  * Height of statusbar
43
57
  */
@@ -19,6 +19,7 @@
19
19
 
20
20
  > * {
21
21
  margin-left: calc(var(--padding-default) / 2);
22
+ cursor: pointer;
22
23
 
23
24
  &:only-of-type {
24
25
  width: 100%;
@@ -40,7 +40,7 @@ Config.prototype.controls.underline = {
40
40
  tagRegExp: /^(u)$/i,
41
41
  tags: ['u'],
42
42
  css: {
43
- 'text-decoration': 'underline'
43
+ 'text-decoration-line': 'underline'
44
44
  },
45
45
  tooltip: 'Underline'
46
46
  } as IControlType;
@@ -49,7 +49,7 @@ Config.prototype.controls.strikethrough = {
49
49
  tagRegExp: /^(s)$/i,
50
50
  tags: ['s'],
51
51
  css: {
52
- 'text-decoration': 'line-through'
52
+ 'text-decoration-line': 'line-through'
53
53
  },
54
54
  tooltip: 'Strike through'
55
55
  } as IControlType;
@@ -114,7 +114,17 @@ Config.prototype.controls.font = {
114
114
  },
115
115
 
116
116
  childTemplate: (editor, key: string, value: string) => {
117
- return `<span style="font-family: ${key}!important;">${value}</span>`;
117
+ let isAvailable = false;
118
+
119
+ try {
120
+ isAvailable =
121
+ key.indexOf('dings') === -1 &&
122
+ document.fonts.check(`16px ${key}`, value);
123
+ } catch {}
124
+
125
+ return `<span style="${
126
+ isAvailable ? `font-family: ${key}!important;` : ''
127
+ }">${value}</span>`;
118
128
  },
119
129
 
120
130
  data: {
@@ -34,6 +34,7 @@ export { link } from './link/link';
34
34
  export * from './media';
35
35
  export { mobile } from './mobile';
36
36
  export { orderedList } from './ordered-list';
37
+ export { poweredByJodit } from './powered-by-jodit';
37
38
  export { placeholder } from './placeholder/placeholder';
38
39
  export { redoUndo } from './redo-undo';
39
40
  export { resizer } from './resizer/resizer';
@@ -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
+ }