@wiris/mathtype-ckeditor5 8.9.1 → 8.10.0
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.
- package/README.md +93 -68
- package/dist/browser/index-content.css +0 -0
- package/dist/browser/index-editor.css +502 -0
- package/dist/browser/index.css +650 -0
- package/dist/browser/index.css.map +1 -0
- package/dist/browser/index.js +11211 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/index.umd.js +11215 -0
- package/dist/browser/index.umd.js.map +1 -0
- package/dist/index-content.css +0 -0
- package/dist/index-editor.css +0 -0
- package/dist/index.css +0 -0
- package/dist/index.js +803 -0
- package/dist/index.js.map +1 -0
- package/package.json +23 -8
- package/src/commands.js +17 -13
- package/src/index.js +3 -0
- package/src/integration.js +83 -86
- package/src/plugin.js +147 -147
package/src/integration.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import IntegrationModel from
|
|
2
|
-
import Util from
|
|
3
|
-
import Configuration from
|
|
4
|
-
import Latex from
|
|
5
|
-
import MathML from
|
|
6
|
-
import Telemeter from
|
|
1
|
+
import IntegrationModel from "@wiris/mathtype-html-integration-devkit/src/integrationmodel.js";
|
|
2
|
+
import Util from "@wiris/mathtype-html-integration-devkit/src/util.js";
|
|
3
|
+
import Configuration from "@wiris/mathtype-html-integration-devkit/src/configuration.js";
|
|
4
|
+
import Latex from "@wiris/mathtype-html-integration-devkit/src/latex.js";
|
|
5
|
+
import MathML from "@wiris/mathtype-html-integration-devkit/src/mathml.js";
|
|
6
|
+
import Telemeter from "@wiris/mathtype-html-integration-devkit/src/telemeter.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* This class represents the MathType integration for CKEditor5.
|
|
@@ -13,40 +13,41 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
13
13
|
constructor(ckeditorIntegrationModelProperties) {
|
|
14
14
|
const editor = ckeditorIntegrationModelProperties.editorObject;
|
|
15
15
|
|
|
16
|
-
if (typeof editor.config !==
|
|
17
|
-
ckeditorIntegrationModelProperties.integrationParameters = editor.config.get(
|
|
16
|
+
if (typeof editor.config !== "undefined" && typeof editor.config.get("mathTypeParameters") !== "undefined") {
|
|
17
|
+
ckeditorIntegrationModelProperties.integrationParameters = editor.config.get("mathTypeParameters");
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
* CKEditor5 Integration.
|
|
21
|
+
*
|
|
22
|
+
* @param {integrationModelProperties} integrationModelAttributes
|
|
23
|
+
*/
|
|
24
24
|
super(ckeditorIntegrationModelProperties);
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Folder name used for the integration inside CKEditor plugins folder.
|
|
28
28
|
*/
|
|
29
|
-
this.integrationFolderName =
|
|
29
|
+
this.integrationFolderName = "ckeditor_wiris";
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
* @inheritdoc
|
|
34
|
+
* @returns {string} - The CKEditor instance language.
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
37
|
getLanguage() {
|
|
38
38
|
// Returns the CKEDitor instance language taking into account that the language can be an object.
|
|
39
39
|
// Try to get editorParameters.language, fail silently otherwise
|
|
40
40
|
try {
|
|
41
41
|
return this.editorParameters.language;
|
|
42
42
|
} catch (e) {}
|
|
43
|
-
const languageObject = this.editorObject.config.get(
|
|
43
|
+
const languageObject = this.editorObject.config.get("language");
|
|
44
44
|
if (languageObject != null) {
|
|
45
|
-
if (typeof
|
|
45
|
+
if (typeof languageObject === "object") {
|
|
46
46
|
// eslint-disable-next-line no-prototype-builtins
|
|
47
|
-
if (languageObject.hasOwnProperty(
|
|
47
|
+
if (languageObject.hasOwnProperty("ui")) {
|
|
48
48
|
return languageObject.ui;
|
|
49
|
-
}
|
|
49
|
+
}
|
|
50
|
+
return languageObject;
|
|
50
51
|
}
|
|
51
52
|
return languageObject;
|
|
52
53
|
}
|
|
@@ -54,29 +55,28 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
* Adds callbacks to the following CKEditor listeners:
|
|
59
|
+
* - 'focus' - updates the current instance.
|
|
60
|
+
* - 'contentDom' - adds 'doubleclick' callback.
|
|
61
|
+
* - 'doubleclick' - sets to null data.dialog property to avoid modifications for MathType formulas.
|
|
62
|
+
* - 'setData' - parses the data converting MathML into images.
|
|
63
|
+
* - 'afterSetData' - adds an observer to MathType formulas to avoid modifications.
|
|
64
|
+
* - 'getData' - parses the data converting images into selected save mode (MathML by default).
|
|
65
|
+
* - 'mode' - recalculates the active element.
|
|
66
|
+
*/
|
|
66
67
|
addEditorListeners() {
|
|
67
68
|
const editor = this.editorObject;
|
|
68
69
|
|
|
69
|
-
if (typeof editor.config.wirislistenersdisabled ===
|
|
70
|
-
|| !editor.config.wirislistenersdisabled) {
|
|
70
|
+
if (typeof editor.config.wirislistenersdisabled === "undefined" || !editor.config.wirislistenersdisabled) {
|
|
71
71
|
this.checkElement();
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
* Checks the current container and assign events in case that it doesn't have them.
|
|
77
|
+
* CKEditor replaces several times the element element during its execution,
|
|
78
|
+
* so we must assign the events again to editor element.
|
|
79
|
+
*/
|
|
80
80
|
checkElement() {
|
|
81
81
|
const editor = this.editorObject;
|
|
82
82
|
const newElement = editor.sourceElement;
|
|
@@ -91,24 +91,25 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
* @inheritdoc
|
|
95
|
+
* @param {HTMLElement} element - HTMLElement target.
|
|
96
|
+
* @param {MouseEvent} event - event which trigger the handler.
|
|
97
|
+
*/
|
|
98
98
|
doubleClickHandler(element, event) {
|
|
99
99
|
this.core.editionProperties.dbclick = true;
|
|
100
100
|
if (this.editorObject.isReadOnly === false) {
|
|
101
|
-
if (element.nodeName.toLowerCase() ===
|
|
102
|
-
if (Util.containsClass(element, Configuration.get(
|
|
101
|
+
if (element.nodeName.toLowerCase() === "img") {
|
|
102
|
+
if (Util.containsClass(element, Configuration.get("imageClassName"))) {
|
|
103
103
|
// Some plugins (image2, image) open a dialog on Double-click. On formulas
|
|
104
104
|
// doubleclick event ends here.
|
|
105
|
-
if (typeof event.stopPropagation !==
|
|
105
|
+
if (typeof event.stopPropagation !== "undefined") {
|
|
106
|
+
// old I.E compatibility.
|
|
106
107
|
event.stopPropagation();
|
|
107
108
|
} else {
|
|
108
109
|
event.returnValue = false;
|
|
109
110
|
}
|
|
110
111
|
this.core.getCustomEditors().disable();
|
|
111
|
-
const customEditorAttr = element.getAttribute(Configuration.get(
|
|
112
|
+
const customEditorAttr = element.getAttribute(Configuration.get("imageCustomEditorName"));
|
|
112
113
|
if (customEditorAttr) {
|
|
113
114
|
this.core.getCustomEditors().enable(customEditorAttr);
|
|
114
115
|
}
|
|
@@ -138,17 +139,17 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
/**
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
* Replaces old formula with new MathML or inserts it in caret position if new
|
|
143
|
+
* @param {String} mathml MathML to update old one or insert
|
|
144
|
+
* @returns {module:engine/model/element~Element} The model element corresponding to the inserted image
|
|
145
|
+
*/
|
|
145
146
|
insertMathml(mathml) {
|
|
146
147
|
// This returns the value returned by the callback function (writer => {...})
|
|
147
148
|
return this.editorObject.model.change((writer) => {
|
|
148
149
|
const core = this.getCore();
|
|
149
150
|
const selection = this.editorObject.model.document.selection;
|
|
150
151
|
|
|
151
|
-
const modelElementNew = writer.createElement(
|
|
152
|
+
const modelElementNew = writer.createElement("mathml", {
|
|
152
153
|
formula: mathml,
|
|
153
154
|
...Object.fromEntries(selection.getAttributes()), // To keep the format, such as style and font
|
|
154
155
|
});
|
|
@@ -158,7 +159,8 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
158
159
|
// Don't bother inserting anything at all if the MathML is empty.
|
|
159
160
|
if (!mathml) return;
|
|
160
161
|
|
|
161
|
-
const viewSelection =
|
|
162
|
+
const viewSelection =
|
|
163
|
+
this.core.editionProperties.selection || this.editorObject.editing.view.document.selection;
|
|
162
164
|
const modelPosition = this.editorObject.editing.mapper.toModelPosition(viewSelection.getLastPosition());
|
|
163
165
|
|
|
164
166
|
this.editorObject.model.insertObject(modelElementNew, modelPosition);
|
|
@@ -194,19 +196,18 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
/**
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
findText(viewElement) {
|
|
199
|
+
* Finds the text node corresponding to given DOM text element.
|
|
200
|
+
* @param {element} viewElement Element to find corresponding text node of.
|
|
201
|
+
* @returns {module:engine/model/text~Text|undefined} Text node corresponding to the given element or undefined if it doesn't exist.
|
|
202
|
+
*/
|
|
203
|
+
findText(viewElement) {
|
|
204
|
+
// eslint-disable-line consistent-return
|
|
202
205
|
// mapper always converts text nodes to *new* model elements so we need to convert the text's parents and then come back down
|
|
203
206
|
let pivot = viewElement;
|
|
204
207
|
let element;
|
|
205
208
|
while (!element) {
|
|
206
209
|
element = this.editorObject.editing.mapper.toModelElement(
|
|
207
|
-
this.editorObject.editing.view.domConverter.domToView(
|
|
208
|
-
pivot,
|
|
209
|
-
),
|
|
210
|
+
this.editorObject.editing.view.domConverter.domToView(pivot),
|
|
210
211
|
);
|
|
211
212
|
pivot = pivot.parentElement;
|
|
212
213
|
}
|
|
@@ -218,22 +219,23 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
218
219
|
let viewElementData = viewElement.data;
|
|
219
220
|
if (viewElement.nodeType === 3) {
|
|
220
221
|
// Remove invisible white spaces
|
|
221
|
-
viewElementData = viewElementData.replaceAll(String.fromCharCode(8288),
|
|
222
|
+
viewElementData = viewElementData.replaceAll(String.fromCharCode(8288), "");
|
|
222
223
|
}
|
|
223
|
-
if (node.is(
|
|
224
|
+
if (node.is("textProxy") && node.data === viewElementData.replace(String.fromCharCode(160), " ")) {
|
|
224
225
|
return node.textNode;
|
|
225
226
|
}
|
|
226
227
|
}
|
|
227
228
|
}
|
|
228
229
|
|
|
229
230
|
/** @inheritdoc */
|
|
230
|
-
insertFormula(focusElement, windowTarget, mathml, wirisProperties) {
|
|
231
|
+
insertFormula(focusElement, windowTarget, mathml, wirisProperties) {
|
|
232
|
+
// eslint-disable-line no-unused-vars
|
|
231
233
|
const returnObject = {};
|
|
232
234
|
|
|
233
235
|
let mathmlOrigin;
|
|
234
236
|
if (!mathml) {
|
|
235
|
-
this.insertMathml(
|
|
236
|
-
} else if (this.core.editMode ===
|
|
237
|
+
this.insertMathml("");
|
|
238
|
+
} else if (this.core.editMode === "latex") {
|
|
237
239
|
returnObject.latex = Latex.getLatexFromMathML(mathml);
|
|
238
240
|
returnObject.node = windowTarget.document.createTextNode(`$$${returnObject.latex}$$`);
|
|
239
241
|
|
|
@@ -246,28 +248,26 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
246
248
|
let startPosition = writer.createPositionAt(startNode.parent, startNode.startOffset + latexRange.startOffset);
|
|
247
249
|
let endPosition = writer.createPositionAt(endNode.parent, endNode.startOffset + latexRange.endOffset);
|
|
248
250
|
|
|
249
|
-
let range = writer.createRange(
|
|
250
|
-
startPosition,
|
|
251
|
-
endPosition,
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
let range = writer.createRange(startPosition, endPosition);
|
|
255
252
|
|
|
256
253
|
// When Latex is next to image/formula.
|
|
257
254
|
if (latexRange.startContainer.nodeType === 3 && latexRange.startContainer.previousSibling?.nodeType === 1) {
|
|
258
255
|
// Get the position of the latex to be replaced.
|
|
259
|
-
let latexEdited =
|
|
256
|
+
let latexEdited =
|
|
257
|
+
"$$" +
|
|
258
|
+
Latex.getLatexFromMathML(MathML.safeXmlDecode(this.core.editionProperties.temporalImage.dataset.mathml)) +
|
|
259
|
+
"$$";
|
|
260
260
|
let data = latexRange.startContainer.data;
|
|
261
261
|
|
|
262
262
|
// Remove invisible characters.
|
|
263
|
-
data = data.replaceAll(String.fromCharCode(8288),
|
|
263
|
+
data = data.replaceAll(String.fromCharCode(8288), "");
|
|
264
264
|
|
|
265
265
|
// Get to the start of the latex we are editing.
|
|
266
266
|
let offset = data.indexOf(latexEdited);
|
|
267
267
|
let dataOffset = data.substring(offset);
|
|
268
268
|
let second$ = dataOffset.substring(2).indexOf("$$") + 4;
|
|
269
269
|
let substring = dataOffset.substr(0, second$);
|
|
270
|
-
data = data.replace(substring,
|
|
270
|
+
data = data.replace(substring, "");
|
|
271
271
|
|
|
272
272
|
if (!data) {
|
|
273
273
|
startPosition = writer.createPositionBefore(startNode);
|
|
@@ -275,10 +275,7 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
275
275
|
} else {
|
|
276
276
|
startPosition = startPosition = writer.createPositionAt(startNode.parent, startNode.startOffset + offset);
|
|
277
277
|
endPosition = writer.createPositionAt(endNode.parent, endNode.startOffset + second$ + offset);
|
|
278
|
-
range = writer.createRange(
|
|
279
|
-
startPosition,
|
|
280
|
-
endPosition,
|
|
281
|
-
);
|
|
278
|
+
range = writer.createRange(startPosition, endPosition);
|
|
282
279
|
}
|
|
283
280
|
}
|
|
284
281
|
|
|
@@ -289,13 +286,12 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
289
286
|
mathmlOrigin = this.core.editionProperties.temporalImage?.dataset.mathml;
|
|
290
287
|
try {
|
|
291
288
|
returnObject.node = this.editorObject.editing.view.domConverter.viewToDom(
|
|
292
|
-
this.editorObject.editing.mapper.toViewElement(
|
|
293
|
-
|
|
294
|
-
), windowTarget.document,
|
|
289
|
+
this.editorObject.editing.mapper.toViewElement(this.insertMathml(mathml)),
|
|
290
|
+
windowTarget.document,
|
|
295
291
|
);
|
|
296
292
|
} catch (e) {
|
|
297
293
|
const x = e.toString();
|
|
298
|
-
if (
|
|
294
|
+
if (x.includes("CKEditorError: Cannot read property 'parent' of undefined")) {
|
|
299
295
|
this.core.modalDialog.cancelAction();
|
|
300
296
|
}
|
|
301
297
|
}
|
|
@@ -312,16 +308,17 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
312
308
|
};
|
|
313
309
|
|
|
314
310
|
// Remove desired null keys.
|
|
315
|
-
Object.keys(payload).forEach(key => {
|
|
316
|
-
if (key ===
|
|
311
|
+
Object.keys(payload).forEach((key) => {
|
|
312
|
+
if (key === "mathml_origin" || key === "editor_origin") !payload[key] ? delete payload[key] : {};
|
|
317
313
|
});
|
|
318
314
|
|
|
315
|
+
// Call Telemetry service to track the event.
|
|
319
316
|
try {
|
|
320
317
|
Telemeter.telemeter.track("INSERTED_FORMULA", {
|
|
321
318
|
...payload,
|
|
322
319
|
});
|
|
323
|
-
} catch (
|
|
324
|
-
console.error(
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error("Error tracking INSERTED_FORMULA", error);
|
|
325
322
|
}
|
|
326
323
|
|
|
327
324
|
/* Due to PLUGINS-1329, we add the onChange event to the CK4 insertFormula.
|
|
@@ -335,8 +332,8 @@ export default class CKEditor5Integration extends IntegrationModel {
|
|
|
335
332
|
}
|
|
336
333
|
|
|
337
334
|
/**
|
|
338
|
-
|
|
339
|
-
|
|
335
|
+
* Function called when the content submits an action.
|
|
336
|
+
*/
|
|
340
337
|
notifyWindowClosed() {
|
|
341
338
|
this.editorObject.editing.view.focus();
|
|
342
339
|
}
|