Skip to content

Commit 48bf553

Browse files
HTML editor: rework quill module integration types (#30563)
1 parent 08a4c9f commit 48bf553

9 files changed

Lines changed: 282 additions & 50 deletions

File tree

packages/devextreme/js/__internal/ui/html_editor/converters/m_delta.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,40 @@
11
import ConverterController from '../m_converterController';
2+
import type { Delta, QuillInstance } from '../types/quill';
23

34
class DeltaConverter {
4-
quillInstance: any;
5+
quillInstance: QuillInstance | null = null;
56

6-
setQuillInstance(quillInstance) {
7+
setQuillInstance(quillInstance: QuillInstance): void {
78
this.quillInstance = quillInstance;
89
}
910

10-
toHtml() {
11+
toHtml(): string | undefined {
1112
if (!this.quillInstance) {
12-
return;
13+
return undefined;
1314
}
1415

1516
return this._isQuillEmpty()
1617
? ''
1718
: this.quillInstance.getSemanticHTML(0, this.quillInstance.getLength() + 1);
1819
}
1920

20-
_isQuillEmpty() {
21+
private _isQuillEmpty(): boolean {
22+
if (!this.quillInstance) {
23+
return true;
24+
}
25+
2126
const delta = this.quillInstance.getContents();
2227

23-
return delta.length() === 1 && this._isDeltaEmpty(delta);
28+
return delta.length() === 1 && DeltaConverter._isDeltaEmpty(delta);
2429
}
2530

26-
_isDeltaEmpty(delta) {
27-
return delta.reduce((__, { insert }) => insert.indexOf('\n') !== -1);
31+
private static _isDeltaEmpty(delta: Delta): boolean {
32+
return delta.reduce<boolean>((_, operation) => {
33+
if (typeof operation.insert === 'string') {
34+
return operation.insert.includes('\n');
35+
}
36+
return false;
37+
}, false);
2838
}
2939
}
3040

packages/devextreme/js/__internal/ui/html_editor/formats/m_align.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import Quill from 'devextreme-quill';
22

3-
// eslint-disable-next-line import/no-mutable-exports
4-
let AlignStyle = {};
3+
import type { AttributorConstructor } from '../types/quill';
54

6-
if (Quill) {
7-
AlignStyle = Quill.import('attributors/style/align');
8-
// @ts-expect-error
5+
type OptionalAttributor = AttributorConstructor | Record<string, never>;
6+
7+
const AlignStyle: OptionalAttributor = Quill?.import('attributors/style/align') || {};
8+
9+
if (Array.isArray(AlignStyle.whitelist)) {
910
AlignStyle.whitelist.push('left');
1011
}
1112

packages/devextreme/js/__internal/ui/html_editor/formats/m_font.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import Quill from 'devextreme-quill';
22

3-
// eslint-disable-next-line import/no-mutable-exports
4-
let FontStyle = {};
3+
import type { AttributorConstructor } from '../types/quill';
54

6-
if (Quill) {
7-
FontStyle = Quill.import('attributors/style/font');
8-
// @ts-expect-error
5+
type OptionalAttributor = AttributorConstructor | Record<string, never>;
6+
7+
const FontStyle: OptionalAttributor = Quill?.import('attributors/style/font') || {};
8+
9+
if ('whitelist' in FontStyle) {
910
FontStyle.whitelist = null;
1011
}
1112

packages/devextreme/js/__internal/ui/html_editor/formats/m_size.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import Quill from 'devextreme-quill';
22

3-
// eslint-disable-next-line import/no-mutable-exports
4-
let SizeStyle = {};
3+
import type { AttributorConstructor } from '../types/quill';
54

6-
if (Quill) {
7-
SizeStyle = Quill.import('attributors/style/size');
8-
// @ts-expect-error
5+
type OptionalAttributor = AttributorConstructor | Record<string, never>;
6+
7+
const SizeStyle: OptionalAttributor = Quill?.import('attributors/style/size') || {};
8+
9+
if ('whitelist' in SizeStyle) {
910
SizeStyle.whitelist = null;
1011
}
1112

packages/devextreme/js/__internal/ui/html_editor/html_editor.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ import type { Converter, HtmlEditorFormat, Properties } from '@js/ui/html_editor
3131
import type { OptionChanged } from '@ts/core/widget/types';
3232
import type { ValueChangedEvent } from '@ts/ui/editor/editor';
3333
import Editor from '@ts/ui/editor/editor';
34-
import type DeltaConverterType from '@ts/ui/html_editor/converters/m_delta';
35-
import ConverterController from '@ts/ui/html_editor/m_converterController';
34+
import ConverterController, { type BaseConverter } from '@ts/ui/html_editor/m_converterController';
3635
import { getQuill } from '@ts/ui/html_editor/m_quill_importer';
3736
import QuillRegistrator from '@ts/ui/html_editor/m_quill_registrator';
3837
import getWordMatcher from '@ts/ui/html_editor/matchers/m_wordLists';
@@ -89,7 +88,7 @@ class HtmlEditor extends Editor<Properties> {
8988

9089
_htmlConverter?: Converter;
9190

92-
_deltaConverter!: DeltaConverterType;
91+
_deltaConverter!: BaseConverter;
9392

9493
_updateContentTask?: DeferredObj<unknown> & { abort: () => void };
9594

@@ -367,10 +366,11 @@ class HtmlEditor extends Editor<Properties> {
367366
if (isFunction(customizeModules)) {
368367
customizeModules(modulesConfig);
369368
}
369+
const { placeholder, readOnly, disabled } = this.option();
370370

371371
this._quillInstance = this._getRegistrator().createEditor(this._$htmlContainer[0], {
372-
placeholder: this.option('placeholder'),
373-
readOnly: this.option('readOnly') || this.option('disabled'),
372+
placeholder,
373+
readOnly: Boolean(readOnly) || Boolean(disabled),
374374
modules: modulesConfig,
375375
theme: 'basic',
376376
});
@@ -783,7 +783,7 @@ class HtmlEditor extends Editor<Properties> {
783783
this._contentInitializedCallback.add(callback);
784784
}
785785

786-
register(components: unknown): void {
786+
register(components: Record<string, unknown>): void {
787787
this._getRegistrator().registerModules(components);
788788

789789
if (this._quillInstance) {
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
1+
import type { QuillInstance } from './types/quill';
2+
3+
interface BaseConverter {
4+
setQuillInstance: (quillInstance: QuillInstance) => void;
5+
toHtml: () => string | undefined;
6+
}
7+
8+
type ConverterConstructor = new () => BaseConverter;
9+
110
class ConverterController {
2-
_converters = {};
11+
_converters: Record<string, ConverterConstructor> = {};
312

413
constructor() {
514
this._converters = {};
615
}
716

8-
addConverter(name, converter) {
17+
addConverter(name: string, converter: ConverterConstructor): void {
918
this._converters[name] = converter;
1019
}
1120

12-
getConverter(name) {
21+
getConverter(name: string): ConverterConstructor | undefined {
1322
return this._converters[name];
1423
}
1524
}
1625

1726
const controller = new ConverterController();
1827

28+
export type { BaseConverter, ConverterConstructor };
1929
export default controller;
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import Errors from '@js/ui/widget/ui.errors';
22
import Quill from 'devextreme-quill';
33

4-
export function getQuill() {
4+
import type { QuillStatic } from './types/quill';
5+
6+
export function getQuill(): QuillStatic {
57
if (!Quill) {
68
throw Errors.Error('E1041', 'Quill');
79
}
810

9-
return Quill;
11+
return Quill as QuillStatic;
1012
}

packages/devextreme/js/__internal/ui/html_editor/m_quill_registrator.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,12 @@ import TableResizing from './modules/m_tableResizing';
1414
import Toolbar from './modules/m_toolbar';
1515
import Variables from './modules/m_variables';
1616
import BaseTheme from './themes/m_base';
17+
import type { QuillInstance, QuillOptions, QuillStatic } from './types/quill';
1718

1819
class QuillRegistrator {
19-
_customModules: any[] = [];
20+
private readonly _customModules: string[] = [];
2021

2122
constructor() {
22-
// @ts-expect-error
23-
if (QuillRegistrator.initialized) {
24-
return;
25-
}
26-
2723
const quill = this.getQuill();
2824
const DirectionStyle = quill.import('attributors/style/direction');
2925

@@ -53,21 +49,18 @@ class QuillRegistrator {
5349
);
5450

5551
this._customModules = [];
56-
// @ts-expect-error
57-
QuillRegistrator._initialized = true;
5852
}
5953

60-
createEditor(container, config) {
61-
const quill = this.getQuill();
54+
createEditor(container: string | Element, config: QuillOptions): QuillInstance {
55+
const QuillConstructor = this.getQuill();
6256

63-
// eslint-disable-next-line new-cap
64-
return new quill(container, config);
57+
return new QuillConstructor(container, config);
6558
}
6659

67-
registerModules(modulesConfig) {
60+
registerModules(modulesConfig: Record<string, unknown>): void {
6861
const isModule = RegExp('modules/*');
6962
const quill = this.getQuill();
70-
const isRegisteredModule = (modulePath) => !!quill.imports[modulePath];
63+
const isRegisteredModule = (modulePath: string): boolean => Boolean(quill.imports[modulePath]);
7164

7265
// eslint-disable-next-line no-restricted-syntax
7366
for (const modulePath in modulesConfig) {
@@ -79,11 +72,11 @@ class QuillRegistrator {
7972
quill.register(modulesConfig, true);
8073
}
8174

82-
getRegisteredModuleNames() {
75+
getRegisteredModuleNames(): string[] {
8376
return this._customModules;
8477
}
8578

86-
getQuill() {
79+
getQuill(): QuillStatic {
8780
return getQuill();
8881
}
8982
}

0 commit comments

Comments
 (0)