Skip to content

Commit 7f2cc88

Browse files
authored
Feat(math): Improve legacy math input with MathLive (#7842)
2 parents 19a365a + 181e36a commit 7f2cc88

File tree

13 files changed

+771
-278
lines changed

13 files changed

+771
-278
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ upload
5151
# docs
5252
site/
5353
apps/*/coverage
54-
scripts/translation/.language*.json
54+
scripts/translation/.language*.json

packages/ckeditor5-math/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
]
7171
},
7272
"dependencies": {
73-
"@ckeditor/ckeditor5-icons": "47.3.0"
73+
"@ckeditor/ckeditor5-icons": "47.3.0",
74+
"mathlive": "0.108.2"
7475
}
7576
}

packages/ckeditor5-math/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import ckeditor from './../theme/icons/math.svg?raw';
22
import './augmentation.js';
33
import "../theme/mathform.css";
4+
import 'mathlive';
5+
import 'mathlive/fonts.css';
6+
import 'mathlive/static.css';
47

58
export { default as Math } from './math.js';
69
export { default as MathUI } from './mathui.js';

packages/ckeditor5-math/src/mathui.ts

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ export default class MathUI extends Plugin {
5555

5656
this._balloon.showStack( 'main' );
5757

58-
requestAnimationFrame(() => {
59-
this.formView?.mathInputView.fieldView.element?.focus();
60-
});
58+
requestAnimationFrame( () => {
59+
this.formView?.mathInputView.focus();
60+
} );
6161
}
6262

6363
private _createFormView() {
@@ -71,31 +71,37 @@ export default class MathUI extends Plugin {
7171
throw new CKEditorError( 'math-command' );
7272
}
7373

74-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
7574
const mathConfig = editor.config.get( 'math' )!;
7675

7776
const formView = new MainFormView(
7877
editor.locale,
79-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
80-
mathConfig.engine!,
81-
mathConfig.lazyLoad,
78+
{
79+
engine: mathConfig.engine!,
80+
lazyLoad: mathConfig.lazyLoad,
81+
previewUid: this._previewUid,
82+
previewClassName: mathConfig.previewClassName!,
83+
katexRenderOptions: mathConfig.katexRenderOptions!
84+
},
8285
mathConfig.enablePreview,
83-
this._previewUid,
84-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
85-
mathConfig.previewClassName!,
86-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
87-
mathConfig.popupClassName!,
88-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
89-
mathConfig.katexRenderOptions!
86+
mathConfig.popupClassName!
9087
);
9188

9289
formView.mathInputView.bind( 'value' ).to( mathCommand, 'value' );
9390
formView.displayButtonView.bind( 'isOn' ).to( mathCommand, 'display' );
9491

9592
// Form elements should be read-only when corresponding commands are disabled.
96-
formView.mathInputView.bind( 'isReadOnly' ).to( mathCommand, 'isEnabled', value => !value );
97-
formView.saveButtonView.bind( 'isEnabled' ).to( mathCommand );
98-
formView.displayButtonView.bind( 'isEnabled' ).to( mathCommand );
93+
formView.mathInputView.bind( 'isReadOnly' ).to( mathCommand, 'isEnabled', ( value: boolean ) => !value );
94+
formView.saveButtonView.bind( 'isEnabled' ).to(
95+
mathCommand,
96+
'isEnabled',
97+
formView.mathInputView,
98+
'value',
99+
( commandEnabled, equation ) => {
100+
const normalizedEquation = ( equation ?? '' ).trim();
101+
return commandEnabled && normalizedEquation.length > 0;
102+
}
103+
);
104+
formView.displayButtonView.bind( 'isEnabled' ).to( mathCommand, 'isEnabled' );
99105

100106
// Listen to submit button click
101107
this.listenTo( formView, 'submit', () => {
@@ -115,24 +121,12 @@ export default class MathUI extends Plugin {
115121
} );
116122

117123
// Allow pressing Enter to submit changes, and use Shift+Enter to insert a new line
118-
formView.keystrokes.set('enter', (data, cancel) => {
119-
if (!data.shiftKey) {
120-
formView.fire('submit');
124+
formView.keystrokes.set( 'enter', ( data, cancel ) => {
125+
if ( !data.shiftKey ) {
126+
formView.fire( 'submit' );
121127
cancel();
122128
}
123-
});
124-
125-
// Allow the textarea to be resizable
126-
formView.mathInputView.fieldView.once('render', () => {
127-
const textarea = formView.mathInputView.fieldView.element;
128-
if (!textarea) return;
129-
Object.assign(textarea.style, {
130-
resize: 'both',
131-
height: '100px',
132-
width: '400px',
133-
minWidth: '100%',
134-
});
135-
});
129+
} );
136130

137131
return formView;
138132
}
@@ -162,14 +156,12 @@ export default class MathUI extends Plugin {
162156
} );
163157

164158
if ( this._balloon.visibleView === this.formView ) {
165-
this.formView.mathInputView.fieldView.element?.select();
159+
this.formView.mathInputView.focus();
166160
}
167161

168-
// Show preview element
169162
const previewEl = document.getElementById( this._previewUid );
170-
if ( previewEl && this.formView.previewEnabled ) {
171-
// Force refresh preview
172-
this.formView.mathView?.updateMath();
163+
if ( previewEl && this.formView.mathView ) {
164+
this.formView.mathView.updateMath();
173165
}
174166

175167
this.formView.equation = mathCommand.value ?? '';
@@ -206,8 +198,10 @@ export default class MathUI extends Plugin {
206198

207199
private _removeFormView() {
208200
if ( this._isFormInPanel && this.formView ) {
209-
this.formView.saveButtonView.focus();
201+
// Hide virtual keyboard before removing the form
202+
this.formView.hideKeyboard();
210203

204+
this.formView.saveButtonView.focus();
211205
this._balloon.remove( this.formView );
212206

213207
// Hide preview element

0 commit comments

Comments
 (0)