jodit 3.22.1 → 3.23.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 (57) hide show
  1. package/README.md +4 -4
  2. package/build/jodit.css +2 -2
  3. package/build/jodit.es2018.css +1 -1
  4. package/build/jodit.es2018.en.css +1 -1
  5. package/build/jodit.es2018.en.js +155 -77
  6. package/build/jodit.es2018.en.min.js +1 -1
  7. package/build/jodit.es2018.js +155 -77
  8. package/build/jodit.es2018.min.js +1 -1
  9. package/build/jodit.js +208 -117
  10. package/build/jodit.min.css +1 -1
  11. package/build/jodit.min.js +1 -1
  12. package/build/plugins/debug/debug.es2018.en.js +1 -1
  13. package/build/plugins/debug/debug.es2018.js +1 -1
  14. package/build/plugins/debug/debug.js +1 -1
  15. package/build/plugins/speech-recognize/speech-recognize.css +1 -1
  16. package/build/plugins/speech-recognize/speech-recognize.es2018.css +1 -1
  17. package/build/plugins/speech-recognize/speech-recognize.es2018.en.css +1 -1
  18. package/build/plugins/speech-recognize/speech-recognize.es2018.en.js +1 -1
  19. package/build/plugins/speech-recognize/speech-recognize.es2018.js +1 -1
  20. package/build/plugins/speech-recognize/speech-recognize.js +1 -1
  21. package/build/vdom.css +1 -1
  22. package/build/vdom.js +1 -1
  23. package/package.json +1 -1
  24. package/src/config.ts +64 -21
  25. package/src/core/request/ajax.ts +44 -29
  26. package/src/core/request/config.ts +0 -1
  27. package/src/core/selection/selection.test.js +168 -0
  28. package/src/core/selection/style/style.test.js +14 -0
  29. package/src/jodit.ts +106 -39
  30. package/src/modules/file-browser/README.md +0 -3
  31. package/src/modules/file-browser/config.ts +0 -2
  32. package/src/modules/file-browser/data-provider.ts +1 -1
  33. package/src/modules/history/snapshot.ts +1 -3
  34. package/src/modules/uploader/helpers/send.ts +4 -2
  35. package/src/plugins/add-new-line/add-new-line.ts +1 -1
  36. package/src/plugins/bold/README.md +11 -1
  37. package/src/plugins/bold/bold.test.js +35 -0
  38. package/src/plugins/bold/bold.ts +19 -49
  39. package/src/plugins/bold/config.ts +54 -0
  40. package/src/plugins/bold/interface.ts +39 -0
  41. package/src/plugins/font/font.ts +1 -1
  42. package/src/plugins/placeholder/placeholder.test.js +24 -7
  43. package/src/plugins/placeholder/placeholder.ts +4 -0
  44. package/src/plugins/search/search.test.screenshot.js +4 -2
  45. package/src/plugins/source/source.ts +5 -5
  46. package/src/types/ajax.d.ts +0 -9
  47. package/src/types/file-browser.d.ts +0 -2
  48. package/src/types/jodit.d.ts +15 -0
  49. package/types/config.d.ts +60 -20
  50. package/types/core/request/ajax.d.ts +6 -9
  51. package/types/jodit.d.ts +16 -13
  52. package/types/plugins/bold/bold.d.ts +2 -0
  53. package/types/plugins/bold/config.d.ts +6 -0
  54. package/types/plugins/bold/interface.d.ts +33 -0
  55. package/types/types/ajax.d.ts +0 -9
  56. package/types/types/file-browser.d.ts +0 -2
  57. package/types/types/jodit.d.ts +15 -0
package/src/jodit.ts CHANGED
@@ -27,13 +27,15 @@ import type {
27
27
  IFileBrowserCallBackData,
28
28
  IStorage,
29
29
  CanPromise,
30
- IHistory
31
- } from './types';
30
+ IHistory,
31
+ AjaxOptions,
32
+ IResponse
33
+ } from 'jodit/types';
32
34
 
33
- import type * as Modules from './modules/';
35
+ import type * as Modules from 'jodit/modules/';
34
36
 
35
- import { Config } from './config';
36
- import * as constants from './core/constants';
37
+ import { Config } from 'jodit/config';
38
+ import * as constants from 'jodit/core/constants';
37
39
 
38
40
  import {
39
41
  Create,
@@ -44,7 +46,7 @@ import {
44
46
  StatusBar,
45
47
  STATUSES,
46
48
  ViewWithToolbar
47
- } from './modules/';
49
+ } from 'jodit/modules/';
48
50
 
49
51
  import {
50
52
  asArray,
@@ -64,14 +66,26 @@ import {
64
66
  kebabCase,
65
67
  isJoditObject,
66
68
  isNumber
67
- } from './core/helpers/';
69
+ } from 'jodit/core/helpers/';
68
70
 
69
- import { Storage } from './core/storage/';
71
+ import { Storage } from 'jodit/core/storage/';
70
72
 
71
73
  import { lang } from 'jodit/core/constants';
72
- import { instances, pluginSystem, modules, eventEmitter } from './core/global';
73
- import { autobind, cache, throttle, watch, derive } from './core/decorators';
74
+ import {
75
+ instances,
76
+ pluginSystem,
77
+ modules,
78
+ eventEmitter
79
+ } from 'jodit/core/global';
80
+ import {
81
+ autobind,
82
+ cache,
83
+ throttle,
84
+ watch,
85
+ derive
86
+ } from 'jodit/core/decorators';
74
87
  import { Dlgs } from 'jodit/core/traits';
88
+ import { Ajax } from 'jodit/core/request';
75
89
 
76
90
  const __defaultStyleDisplayKey = 'data-jodit-default-style-display';
77
91
  const __defaultClassesKey = 'data-jodit-default-classes';
@@ -217,7 +231,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
217
231
  */
218
232
  editorIsActive = false;
219
233
 
220
- private setPlaceField(field: keyof IWorkPlace, value: any): void {
234
+ private __setPlaceField(field: keyof IWorkPlace, value: any): void {
221
235
  if (!this.currentPlace) {
222
236
  this.currentPlace = {} as any;
223
237
  this.places = [this.currentPlace];
@@ -241,7 +255,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
241
255
  }
242
256
 
243
257
  set editor(editor: HTMLDivElement | HTMLBodyElement) {
244
- this.setPlaceField('editor', editor);
258
+ this.__setPlaceField('editor', editor);
245
259
  }
246
260
 
247
261
  /**
@@ -252,7 +266,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
252
266
  }
253
267
 
254
268
  override set container(container: HTMLDivElement) {
255
- this.setPlaceField('container', container);
269
+ this.__setPlaceField('container', container);
256
270
  }
257
271
 
258
272
  /**
@@ -277,7 +291,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
277
291
  }
278
292
 
279
293
  set iframe(iframe: HTMLIFrameElement | void) {
280
- this.setPlaceField('iframe', iframe);
294
+ this.__setPlaceField('iframe', iframe);
281
295
  }
282
296
 
283
297
  get history(): IHistory {
@@ -299,7 +313,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
299
313
  }
300
314
 
301
315
  set editorWindow(win: Window) {
302
- this.setPlaceField('editorWindow', win);
316
+ this.__setPlaceField('editorWindow', win);
303
317
  }
304
318
 
305
319
  /**
@@ -331,7 +345,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
331
345
  }
332
346
 
333
347
  override set options(opt: Config) {
334
- this.setPlaceField('options', opt);
348
+ this.__setPlaceField('options', opt);
335
349
  }
336
350
 
337
351
  readonly selection!: Select;
@@ -460,6 +474,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
460
474
  /**
461
475
  * This is an internal method, do not use it in your applications.
462
476
  * @private
477
+ * @internal
463
478
  */
464
479
  __imdSynchronizeValues(): void {
465
480
  this.setEditorValue();
@@ -581,7 +596,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
581
596
  new_value = this.getEditorValue();
582
597
 
583
598
  if (
584
- !this.isSilentChange &&
599
+ !this.__isSilentChange &&
585
600
  old_value !== new_value &&
586
601
  this.__callChangeCount < constants.SAFE_COUNT_CHANGE_CALL
587
602
  ) {
@@ -810,7 +825,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
810
825
  result = this.e.fire('beforeCommand', command, showUI, value, ...args);
811
826
 
812
827
  if (result !== false) {
813
- result = this.execCustomCommands(command, showUI, value, ...args);
828
+ result = this.__execCustomCommands(command, showUI, value, ...args);
814
829
  }
815
830
 
816
831
  if (result !== false) {
@@ -846,7 +861,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
846
861
  /**
847
862
  * Don't raise a change event
848
863
  */
849
- private isSilentChange: boolean = false;
864
+ private __isSilentChange: boolean = false;
850
865
 
851
866
  /**
852
867
  * Exec native command
@@ -856,16 +871,16 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
856
871
  showUI?: boolean,
857
872
  value?: null | any
858
873
  ): boolean {
859
- this.isSilentChange = true;
874
+ this.__isSilentChange = true;
860
875
 
861
876
  try {
862
877
  return this.ed.execCommand(command, showUI, value);
863
878
  } finally {
864
- this.isSilentChange = false;
879
+ this.__isSilentChange = false;
865
880
  }
866
881
  }
867
882
 
868
- private execCustomCommands<C extends string>(
883
+ private __execCustomCommands<C extends string>(
869
884
  commandName: C,
870
885
  second?: any,
871
886
  third?: null | any,
@@ -1125,17 +1140,27 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1125
1140
  return this.o.readonly;
1126
1141
  }
1127
1142
 
1143
+ focus(): void {
1144
+ if (this.getMode() !== constants.MODE_SOURCE) {
1145
+ this.s.focus();
1146
+ }
1147
+ }
1148
+
1149
+ get isFocused(): boolean {
1150
+ return this.s.isFocused();
1151
+ }
1152
+
1128
1153
  /**
1129
1154
  * Hook before init
1130
1155
  */
1131
- beforeInitHook(): CanPromise<void> {
1156
+ protected beforeInitHook(): CanPromise<void> {
1132
1157
  // do nothing
1133
1158
  }
1134
1159
 
1135
1160
  /**
1136
1161
  * Hook after init
1137
1162
  */
1138
- afterInitHook(): void {
1163
+ protected afterInitHook(): void {
1139
1164
  // do nothing
1140
1165
  }
1141
1166
 
@@ -1197,7 +1222,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1197
1222
  }
1198
1223
  });
1199
1224
 
1200
- this.e.on('prepareWYSIWYGEditor', this.prepareWYSIWYGEditor);
1225
+ this.e.on('prepareWYSIWYGEditor', this.__prepareWYSIWYGEditor);
1201
1226
 
1202
1227
  this.selection = new Select(this);
1203
1228
 
@@ -1241,7 +1266,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1241
1266
  currentPlace!: IWorkPlace;
1242
1267
  places!: IWorkPlace[];
1243
1268
 
1244
- private readonly elementToPlace: Map<HTMLElement, IWorkPlace> = new Map();
1269
+ private readonly __elementToPlace: Map<HTMLElement, IWorkPlace> = new Map();
1245
1270
 
1246
1271
  /**
1247
1272
  * Create and init current editable place
@@ -1281,6 +1306,11 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1281
1306
  container.classList.add('jodit');
1282
1307
  container.classList.add('jodit-container');
1283
1308
  container.classList.add(`jodit_theme_${this.o.theme || 'default'}`);
1309
+ addClassNames(this.o.className, container);
1310
+
1311
+ if (this.o.containerStyle) {
1312
+ css(container, this.o.containerStyle);
1313
+ }
1284
1314
 
1285
1315
  const { styleValues } = this.o;
1286
1316
 
@@ -1363,14 +1393,14 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1363
1393
  editorWindow: this.ow
1364
1394
  };
1365
1395
 
1366
- this.elementToPlace.set(editor, currentPlace);
1396
+ this.__elementToPlace.set(editor, currentPlace);
1367
1397
 
1368
1398
  this.setCurrentPlace(currentPlace);
1369
1399
  this.places.push(currentPlace);
1370
1400
 
1371
1401
  this.setNativeEditorValue(this.getElementValue()); // Init value
1372
1402
 
1373
- const initResult = this.initEditor(buffer);
1403
+ const initResult = this.__initEditor(buffer);
1374
1404
 
1375
1405
  const opt = this.options;
1376
1406
 
@@ -1384,8 +1414,8 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1384
1414
  }
1385
1415
 
1386
1416
  // in initEditor - the editor could change
1387
- if (!this.elementToPlace.get(this.editor)) {
1388
- this.elementToPlace.set(this.editor, currentPlace);
1417
+ if (!this.__elementToPlace.get(this.editor)) {
1418
+ this.__elementToPlace.set(this.editor, currentPlace);
1389
1419
  }
1390
1420
 
1391
1421
  this.e.fire('afterAddPlace', currentPlace);
@@ -1394,7 +1424,6 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1394
1424
  return callPromise(initResult, init);
1395
1425
  }
1396
1426
 
1397
- /** @override */
1398
1427
  protected override addDisclaimer(elm: HTMLElement): void {
1399
1428
  this.workplace.appendChild(elm);
1400
1429
  }
@@ -1420,8 +1449,8 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1420
1449
  }
1421
1450
  }
1422
1451
 
1423
- private initEditor(buffer: null | string): void | Promise<any> {
1424
- const result = this.createEditor();
1452
+ private __initEditor(buffer: null | string): void | Promise<any> {
1453
+ const result = this.__createEditor();
1425
1454
 
1426
1455
  return callPromise(result, () => {
1427
1456
  if (this.isInDestruct) {
@@ -1483,7 +1512,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1483
1512
  /**
1484
1513
  * Create main DIV element and replace source textarea
1485
1514
  */
1486
- private createEditor(): void | Promise<any> {
1515
+ private __createEditor(): void | Promise<any> {
1487
1516
  const defaultEditorArea = this.editor;
1488
1517
 
1489
1518
  const stayDefault: boolean | undefined | Promise<void> = this.e.fire(
@@ -1500,6 +1529,11 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1500
1529
  Dom.safeRemove(defaultEditorArea);
1501
1530
  }
1502
1531
 
1532
+ addClassNames(
1533
+ this.o.editorClassName || this.o.editorCssClass,
1534
+ this.editor
1535
+ );
1536
+
1503
1537
  if (this.o.editorCssClass) {
1504
1538
  this.editor.classList.add(this.o.editorCssClass);
1505
1539
  }
@@ -1517,7 +1551,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1517
1551
  })
1518
1552
  .on('blur', () => (this.editorIsActive = false));
1519
1553
 
1520
- this.prepareWYSIWYGEditor();
1554
+ this.__prepareWYSIWYGEditor();
1521
1555
 
1522
1556
  // direction
1523
1557
  if (this.o.direction) {
@@ -1545,7 +1579,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1545
1579
  * Attach some native event listeners
1546
1580
  */
1547
1581
  @autobind
1548
- private prepareWYSIWYGEditor(): void {
1582
+ private __prepareWYSIWYGEditor(): void {
1549
1583
  const { editor } = this;
1550
1584
 
1551
1585
  // direction
@@ -1560,7 +1594,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1560
1594
  // proxy events
1561
1595
  this.e
1562
1596
  .on(editor, 'mousedown touchstart focus', () => {
1563
- const place = this.elementToPlace.get(editor);
1597
+ const place = this.__elementToPlace.get(editor);
1564
1598
 
1565
1599
  if (place) {
1566
1600
  this.setCurrentPlace(place);
@@ -1572,7 +1606,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1572
1606
  'selectionchange selectionstart keydown keyup input keypress dblclick mousedown mouseup ' +
1573
1607
  'click copy cut dragstart drop dragover paste resize touchstart touchend focus blur',
1574
1608
  (event: Event): false | void => {
1575
- if (this.o.readonly || this.isSilentChange) {
1609
+ if (this.o.readonly || this.__isSilentChange) {
1576
1610
  return;
1577
1611
  }
1578
1612
 
@@ -1595,6 +1629,33 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1595
1629
  );
1596
1630
  }
1597
1631
 
1632
+ fetch<Response extends object = any>(
1633
+ url: string,
1634
+ options?: Partial<AjaxOptions>
1635
+ ): Promise<IResponse<Response>> {
1636
+ const ajax = new Ajax<Response>(
1637
+ {
1638
+ url,
1639
+ ...options
1640
+ },
1641
+ this.o.defaultAjaxOptions
1642
+ );
1643
+
1644
+ const destroy = (): void => {
1645
+ this.e.off('beforeDestruct', destroy);
1646
+ this.progressbar.progress(100).hide();
1647
+ ajax.destruct();
1648
+ };
1649
+ this.e.one('beforeDestruct', destroy);
1650
+
1651
+ this.progressbar.show().progress(30);
1652
+ const promise = ajax.send();
1653
+
1654
+ promise.finally(destroy).catch(() => null);
1655
+
1656
+ return promise;
1657
+ }
1658
+
1598
1659
  /**
1599
1660
  * Jodit's Destructor. Remove editor, and return source input
1600
1661
  */
@@ -1605,7 +1666,7 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1605
1666
 
1606
1667
  this.setStatus(STATUSES.beforeDestruct);
1607
1668
 
1608
- this.elementToPlace.clear();
1669
+ this.__elementToPlace.clear();
1609
1670
 
1610
1671
  if (!this.editor) {
1611
1672
  return;
@@ -1695,3 +1756,9 @@ export class Jodit extends ViewWithToolbar implements IJodit, Dlgs {
1695
1756
  super.destruct();
1696
1757
  }
1697
1758
  }
1759
+
1760
+ function addClassNames(className: string | false, elm: HTMLElement): void {
1761
+ if (className) {
1762
+ className.split(/\s+/).forEach(cn => elm.classList.add(cn));
1763
+ }
1764
+ }
@@ -205,7 +205,6 @@ const response = {
205
205
 
206
206
  - filebrowser.ajax.url='' Address entry point on the server for AJAX connection
207
207
  - filebrowser.ajax.data={} Default data to send to the server
208
- - filebrowser.ajax.dataType='json' The format of the returned data
209
208
  - filebrowser.ajax.headers={} An object of additional header key/value pairs toWYSIWYG
210
209
  send along with requests using the `XMLHttpRequest` transport. The header `X-Requested-With: XMLHttpRequest`
211
210
  is always added, but its default `XMLHttpRequest` value can be changed here.
@@ -254,7 +253,6 @@ const options = {
254
253
  headers: {},
255
254
  method: 'POST',
256
255
  processData: true,
257
- dataType: 'json',
258
256
  headers: {},
259
257
  prepareData: function (data) {
260
258
  return data;
@@ -314,7 +312,6 @@ Jodit.make('#editor2', {
314
312
  ajax: {
315
313
  url: 'ajax.php',
316
314
  method: 'GET',
317
- dataType: 'text',
318
315
  headers: {
319
316
  'X-CSRF-Token': document
320
317
  .querySelector('meta[name="csrf-token"]')
@@ -227,7 +227,6 @@ Config.prototype.filebrowser = {
227
227
  ...Config.prototype.defaultAjaxOptions,
228
228
 
229
229
  url: '',
230
- async: true,
231
230
 
232
231
  data: {},
233
232
  cache: true,
@@ -235,7 +234,6 @@ Config.prototype.filebrowser = {
235
234
 
236
235
  method: 'POST',
237
236
  processData: true,
238
- dataType: 'json',
239
237
 
240
238
  headers: {},
241
239
 
@@ -101,7 +101,7 @@ export default class DataProvider implements IFileBrowserDataProvider {
101
101
  opts.data = opts.prepareData.call(this, opts.data as IDictionary);
102
102
  }
103
103
 
104
- const ajax = new Ajax<T>(this.parent, opts);
104
+ const ajax = new Ajax<T>(opts);
105
105
  ai.set(name, ajax);
106
106
 
107
107
  const promise = ajax.send();
@@ -207,9 +207,7 @@ export class Snapshot extends ViewComponent<IJodit> implements ISnapshot {
207
207
  this.j.value = snapshot.html;
208
208
  }
209
209
 
210
- if (this.j.s.isFocused()) {
211
- this.restoreOnlySelection(snapshot);
212
- }
210
+ this.restoreOnlySelection(snapshot);
213
211
 
214
212
  this.restoreScrollState(scroll);
215
213
  });
@@ -24,7 +24,7 @@ export function send(
24
24
  const sendData = (
25
25
  request: FormData | IDictionary<string> | string
26
26
  ): Promise<any> => {
27
- const ajax = new Ajax<IUploaderAnswer>(uploader.j, {
27
+ const ajax = new Ajax<IUploaderAnswer>({
28
28
  xhr: (): XMLHttpRequest => {
29
29
  const xhr = new XMLHttpRequest();
30
30
 
@@ -69,7 +69,6 @@ export function send(
69
69
  headers: uploader.o.headers,
70
70
  queryBuild: uploader.o.queryBuild,
71
71
  contentType: uploader.o.contentType.call(uploader, request),
72
- dataType: uploader.o.format || 'json',
73
72
  withCredentials: uploader.o.withCredentials || false
74
73
  });
75
74
 
@@ -82,6 +81,8 @@ export function send(
82
81
 
83
82
  instances.add(ajax);
84
83
 
84
+ uploader.j.e.one('beforeDestruct', ajax.destruct);
85
+
85
86
  return ajax
86
87
  .send()
87
88
  .then(resp => resp.json())
@@ -89,6 +90,7 @@ export function send(
89
90
  uploader.o.error.call(uploader, error);
90
91
  })
91
92
  .finally(() => {
93
+ ajax.destruct();
92
94
  instances?.delete(ajax);
93
95
  });
94
96
  };
@@ -159,7 +159,7 @@ export class addNewLine extends Plugin {
159
159
  editor.s.setCursorIn(p);
160
160
  scrollIntoViewIfNeeded(p, editor.editor, editor.ed);
161
161
 
162
- editor.e.fire('synchro');
162
+ editor.synchronizeValues();
163
163
  this.hideForce();
164
164
 
165
165
  e.preventDefault();
@@ -1,3 +1,13 @@
1
1
  # Bold and styles button
2
2
 
3
- Bold/Italic/Strikethrough/Underile/Subscript buttons
3
+ Provide Bold/Italic/Strikethrough/Underline/Subscript/Superscript buttons and commands.
4
+
5
+ ```js
6
+ const editor = Jodit.make('#editor');
7
+ editor.execCommand('bold'); // or press Ctrl+B
8
+ editor.execCommand('italic'); // or press Ctrl+I
9
+ editor.execCommand('underline'); // or press Ctrl+U
10
+ editor.execCommand('strikethrough');
11
+ editor.execCommand('subscript');
12
+ editor.execCommand('superscript');
13
+ ```
@@ -8,10 +8,15 @@ describe('Bold plugin', () => {
8
8
  let jodit;
9
9
  beforeEach(() => {
10
10
  jodit = getJodit();
11
+ jodit.focus();
11
12
  jodit.value = '<p>|<br></p>';
12
13
  setCursorToChar(jodit);
13
14
  });
14
15
 
16
+ afterEach(() => {
17
+ jodit.destruct();
18
+ });
19
+
15
20
  describe('Click bold button', () => {
16
21
  it('Should add empty STRONG element', async () => {
17
22
  clickButton('bold', jodit);
@@ -20,4 +25,34 @@ describe('Bold plugin', () => {
20
25
  expect(jodit.value).eq('<p><strong>|</strong></p>');
21
26
  });
22
27
  });
28
+
29
+ describe('Click subscript button', () => {
30
+ it('Should add empty SUB element', async () => {
31
+ clickButton('subscript', jodit);
32
+ jodit.async.requestIdlePromise();
33
+ replaceCursorToChar(jodit);
34
+ expect(jodit.value).eq('<p><sub>|</sub></p>');
35
+ });
36
+
37
+ describe('Inside sub tag', () => {
38
+ it('Should move cursor in the outside from the tag', async () => {
39
+ jodit.value = '<p><sup>test|</sup></p>';
40
+ setCursorToChar(jodit);
41
+ clickButton('superscript', jodit);
42
+ jodit.async.requestIdlePromise();
43
+ jodit.s.insertHTML('pop');
44
+ replaceCursorToChar(jodit);
45
+ expect(jodit.value).eq('<p><sup>test</sup>pop|</p>');
46
+ });
47
+ });
48
+ });
49
+
50
+ describe('Click superscript button', () => {
51
+ it('Should add empty SUP element', async () => {
52
+ clickButton('superscript', jodit);
53
+ jodit.async.requestIdlePromise();
54
+ replaceCursorToChar(jodit);
55
+ expect(jodit.value).eq('<p><sup>|</sup></p>');
56
+ });
57
+ });
23
58
  });
@@ -10,57 +10,14 @@
10
10
  * @module plugins/bold
11
11
  */
12
12
 
13
- import type { IDictionary, IJodit, IControlType } from 'jodit/types';
13
+ import type { IDictionary, IJodit, IControlType, CanUndef } from 'jodit/types';
14
14
  import { Config } from 'jodit/config';
15
15
  import { isArray } from 'jodit/core/helpers';
16
16
  import { pluginSystem } from 'jodit/core/global';
17
17
  import { Icon } from 'jodit/core/ui/icon';
18
18
 
19
- Config.prototype.controls.subscript = {
20
- tags: ['sub'],
21
- tooltip: 'subscript'
22
- } as IControlType;
23
-
24
- Config.prototype.controls.superscript = {
25
- tags: ['sup'],
26
- tooltip: 'superscript'
27
- } as IControlType;
28
-
29
- Config.prototype.controls.bold = {
30
- tagRegExp: /^(strong|b)$/i,
31
- tags: ['strong', 'b'],
32
- css: {
33
- 'font-weight': ['bold', '700']
34
- },
35
- tooltip: 'Bold'
36
- } as IControlType;
37
-
38
- Config.prototype.controls.italic = {
39
- tagRegExp: /^(em|i)$/i,
40
- tags: ['em', 'i'],
41
- css: {
42
- 'font-style': 'italic'
43
- },
44
- tooltip: 'Italic'
45
- } as IControlType;
46
-
47
- Config.prototype.controls.underline = {
48
- tagRegExp: /^(u)$/i,
49
- tags: ['u'],
50
- css: {
51
- 'text-decoration-line': 'underline'
52
- },
53
- tooltip: 'Underline'
54
- } as IControlType;
55
-
56
- Config.prototype.controls.strikethrough = {
57
- tagRegExp: /^(s)$/i,
58
- tags: ['s'],
59
- css: {
60
- 'text-decoration-line': 'line-through'
61
- },
62
- tooltip: 'Strike through'
63
- } as IControlType;
19
+ import './interface';
20
+ import './config';
64
21
 
65
22
  /**
66
23
  * Adds `bold`,` strikethrough`, `underline` and` italic` buttons to Jodit
@@ -74,10 +31,15 @@ export function bold(editor: IJodit): void {
74
31
  | IDictionary<string | string[]>
75
32
  | IDictionary<(editor: IJodit, value: string) => boolean> = {
76
33
  ...control.css
77
- },
78
- cssRules: IDictionary<string> = {};
34
+ };
35
+
36
+ let cssRules: CanUndef<IDictionary<string>>;
79
37
 
80
38
  Object.keys(cssOptions).forEach((key: string) => {
39
+ if (!cssRules) {
40
+ cssRules = {};
41
+ }
42
+
81
43
  cssRules[key] = isArray(cssOptions[key])
82
44
  ? (cssOptions[key] as any)[0]
83
45
  : cssOptions[key];
@@ -87,7 +49,7 @@ export function bold(editor: IJodit): void {
87
49
  element: control.tags ? control.tags[0] : undefined
88
50
  });
89
51
 
90
- editor.e.fire('synchro');
52
+ editor.synchronizeValues();
91
53
 
92
54
  return false;
93
55
  };
@@ -124,6 +86,14 @@ export function bold(editor: IJodit): void {
124
86
 
125
87
  .registerCommand('strikethrough', {
126
88
  exec: callBack
89
+ })
90
+
91
+ .registerCommand('subscript', {
92
+ exec: callBack
93
+ })
94
+
95
+ .registerCommand('superscript', {
96
+ exec: callBack
127
97
  });
128
98
  }
129
99