@wiris/mathtype-tinymce7 8.12.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 ADDED
@@ -0,0 +1,98 @@
1
+ # MathType for TinyMCE V7
2
+
3
+ Type and handwrite mathematical notation with MathType.
4
+
5
+ Easily include quality math equations in your documents and digital content.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Install instructions](#install-instructions)
10
+ - [Known issues](#known-issues)
11
+ - [Services](#services)
12
+ - [Documentation](#documentation)
13
+ - [Displaying on Target Page](#displaying-on-target-page)
14
+ - [Privacy policy](#privacy-policy)
15
+
16
+ ## Install instructions
17
+
18
+ 1. Install the npm module:
19
+
20
+ ```bash
21
+ npm install @wiris/mathtype-tinymce7
22
+ ```
23
+
24
+ > MathType is fully compatible with TinyMCE 7 from version 7.6.0.
25
+
26
+ 2. Add the plugin as an external plugin:
27
+
28
+ ```js
29
+ tinymce.init({
30
+ external_plugins: {
31
+ tiny_mce_wiris: `node_modules/@wiris/mathtype-tinymce7/plugin.min.js`,
32
+ },
33
+ });
34
+ ```
35
+
36
+ 3. Add MathType buttons to the TinyMCE7 toolbar and the recommended settings:
37
+
38
+ ```js
39
+ tinymce.init({
40
+ toolbar: "tiny_mce_wiris_formulaEditor tiny_mce_wiris_formulaEditorChemistry",
41
+ // We recommend to set 'draggable_modal' to true to avoid overlapping issues
42
+ // with the different UI modal dialog windows implementations between core and third-party plugins on TinyMCE.
43
+ // @see: https://github.com/wiris/html-integrations/issues/134#issuecomment-905448642
44
+ draggable_modal: true,
45
+
46
+ // This option allows you to introduce mathml formulas with wiris plugins.
47
+ // Not enabling this, will provide formulas from being created and rendered.
48
+ extended_valid_elements: "*[.*]",
49
+ valid_elements: "*[*]",
50
+
51
+ // You could set a different language for MathType editor:
52
+ // language: 'fr_FR',
53
+ // mathTypeParameters: {
54
+ // editorParameters: { language: 'fr' },
55
+ // },
56
+ });
57
+ ```
58
+
59
+ Notice the example assumes this directory structure:
60
+
61
+ ```
62
+ └───index.html
63
+ └───node_modules
64
+ └───@wiris/mathtype-tinymce7
65
+ ```
66
+
67
+ ## Known issues
68
+
69
+ - When loading the page with initial content, TinyMCE 7 removes the `<semantics>` tag. This tag is the one that identifies formulas as Handwriting. To bypass their sanitization and allow the `<semantics>` tag the initial content, add the following configuration to you TinyMCE instance: `xss_sanitization: false`. Checkout [more information here](https://github.com/tinymce/tinymce/issues/10114).
70
+ - The editor's caret is lost when inserting a new formula on Safari with ChemType [#486](https://github.com/wiris/html-integrations/issues/486)
71
+
72
+ ## Services
73
+
74
+ This npm module uses remotely hosted services to render MathML data. However, we recommend you install these services on your backend. This will allow you, among other things, to configure the service and to locally store the images generated by MathType.
75
+
76
+ The services are available for Java, PHP, .NET and Ruby on Rails. If you use any of these technologies, please download the plugin for your backend technology from [here](https://store.wiris.com/en/products/downloads/mathtype/integrations#froala?utm_source=npmjs&utm_medium=referral).
77
+
78
+ ## Displaying on Target Page
79
+
80
+ In order to display mathematical formulas on the target page, i.e. the page where content produced by the HTML editor will be visible, the target page needs to include the [MathType script](https://docs.wiris.com/en/mathtype/mathtype_web/integrations/mathml-mode#add_a_script_to_head). For example for the default setting this would be:
81
+
82
+ ```html
83
+ <script src="https://www.wiris.net/demo/plugins/app/WIRISplugins.js?viewer=image"></script>
84
+ ```
85
+
86
+ ## Documentation
87
+
88
+ To find out more information about MathType, please go to the following documentation:
89
+
90
+ - [Install instructions](https://docs.wiris.com/mathtype/en/mathtype-integrations/mathtype-for-html-editors/mathtype-for-tinymce.html?utm_source=npmjs&utm_medium=referral)
91
+ - [MathType documentation](https://docs.wiris.com/en/mathtype/mathtype_web/start?utm_source=npmjs&utm_medium=referral)
92
+ - [Introductory tutorials](https://docs.wiris.com/en/mathtype/mathtype_web/intro_tutorials?utm_source=npmjs&utm_medium=referral)
93
+ - [Service customization](https://docs.wiris.com/en/mathtype/mathtype_web/integrations/config-table?utm_source=npmjs&utm_medium=referral)
94
+ - [Testing](https://docs.wiris.com/en/mathtype/mathtype_web/integrations/html/plugins-test?utm_source=npmjs&utm_medium=referral)
95
+
96
+ ## Privacy policy
97
+
98
+ The [MathType Privacy Policy](https://www.wiris.com/en/mathtype-privacy-policy/?utm_source=npmjs&utm_medium=referral) covers the data processing operations for the MathType users. It is an addendum of the company’s general Privacy Policy and the [general Privacy Policy](https://www.wiris.com/en/privacy-policy?utm_source=npmjs&utm_medium=referral) still applies to MathType users.
@@ -0,0 +1,548 @@
1
+ import IntegrationModel from "@wiris/mathtype-html-integration-devkit/src/integrationmodel";
2
+ import Configuration from "@wiris/mathtype-html-integration-devkit/src/configuration";
3
+ import Parser from "@wiris/mathtype-html-integration-devkit/src/parser";
4
+ import Util from "@wiris/mathtype-html-integration-devkit/src/util";
5
+ import Listeners from "@wiris/mathtype-html-integration-devkit/src/listeners";
6
+ import StringManager from "@wiris/mathtype-html-integration-devkit/src/stringmanager";
7
+
8
+ import packageInfo from "./package.json";
9
+
10
+ /**
11
+ * TinyMCE integration class. This class extends IntegrationModel class.
12
+ */
13
+ export class TinyMceIntegration extends IntegrationModel {
14
+ constructor(integrationModelProperties) {
15
+ super(integrationModelProperties);
16
+ /**
17
+ * Indicates if the content of the TinyMCE editor has
18
+ * been parsed.
19
+ * @type {Boolean}
20
+ */
21
+ this.initParsed = integrationModelProperties.initParsed;
22
+ /**
23
+ * Indicates if the TinyMCE is integrated in Moodle.
24
+ * @type {Boolean}
25
+ */
26
+ this.isMoodle = integrationModelProperties.isMoodle;
27
+ /**
28
+ * Indicates if the plugin is loaded as an external plugin by TinyMCE.
29
+ * @type {Boolean}
30
+ */
31
+ this.isExternal = integrationModelProperties.isExternal;
32
+ }
33
+
34
+ /**
35
+ * Returns the absolute path of the integration script. Depends on
36
+ * TinyMCE integration (Moodle or standard).
37
+ * @returns {Boolean} - Absolute path for the integration script.
38
+ */
39
+ getPath() {
40
+ if (this.isMoodle) {
41
+ const search = "lib/editor/tinymce";
42
+ const pos = tinymce.baseURL.indexOf(search);
43
+ const baseURL = tinymce.baseURL.substr(0, pos + search.length);
44
+ return `${baseURL}/plugins/tiny_mce_wiris/tinymce/`;
45
+ }
46
+ if (this.isExternal) {
47
+ const externalUrl = this.editorObject.options.get("external_plugins").tiny_mce_wiris;
48
+ return externalUrl.substring(0, externalUrl.lastIndexOf("/") + 1);
49
+ }
50
+ return `${tinymce.baseURL}/plugins/tiny_mce_wiris/`;
51
+ }
52
+
53
+ /**
54
+ * Returns the absolute path of plugin icons.
55
+ * @returns {String} - Absolute path of the icons folder.
56
+ */
57
+ getIconsPath() {
58
+ return `${this.getPath()}icons/`;
59
+ }
60
+
61
+ /**
62
+ * Returns the integration language. TinyMCE language is inherited.
63
+ * When no language is set, TinyMCE sets the toolbar to english.
64
+ * @returns {String} - Integration language.
65
+ */
66
+ getLanguage() {
67
+ const editorSettings = this.editorObject;
68
+ // Try to get editorParameters.language, fail silently otherwise
69
+ try {
70
+ return editorSettings.options.get("mathTypeParameters").editorParameters.language;
71
+ } catch (e) {}
72
+ // Get the deprecated wirisformulaeditorlang
73
+ if (editorSettings.options.get("wirisformulaeditorlang")) {
74
+ console.warn("Deprecated property wirisformulaeditorlang. Use mathTypeParameters on instead.");
75
+ return editorSettings.options.get("wirisformulaeditorlang");
76
+ }
77
+ const langParam = this.editorObject.options.get("language");
78
+ return langParam || super.getLanguage();
79
+ }
80
+
81
+ /**
82
+ * Callback function called before 'onTargetLoad' is fired. All the logic here is to
83
+ * avoid TinyMCE change MathType formulas.
84
+ */
85
+ callbackFunction() {
86
+ const dataImgFiltered = [];
87
+ super.callbackFunction();
88
+
89
+ // Avoid to change class of image formulas.
90
+ const imageClassName = Configuration.get("imageClassName");
91
+ if (this.isIframe) {
92
+ // Attaching observers to wiris images.
93
+ if (typeof Parser.observer !== "undefined") {
94
+ Array.prototype.forEach.call(
95
+ this.target.contentDocument.getElementsByClassName(imageClassName),
96
+ (wirisImages) => {
97
+ Parser.observer.observe(wirisImages);
98
+ },
99
+ );
100
+ }
101
+ } else {
102
+ // Inline.
103
+ // Attaching observers to wiris images.
104
+ Array.prototype.forEach.call(document.getElementsByClassName(imageClassName), (wirisImages) => {
105
+ Parser.observer.observe(wirisImages);
106
+ });
107
+ }
108
+
109
+ // When a formula is updated TinyMCE 'Change' event must be fired.
110
+ // See https://www.tiny.cloud/docs/advanced/events/#change for further information.
111
+ const listener = Listeners.newListener("onAfterFormulaInsertion", () => {
112
+ if (typeof this.editorObject.fire !== "undefined") {
113
+ this.editorObject.fire("Change");
114
+ }
115
+ });
116
+ this.getCore().addListener(listener);
117
+
118
+ // Deprecated part on TinyMCE7; We need to find a workaround
119
+ // Avoid filter formulas with performance enabled.
120
+ dataImgFiltered[this.editorObject.id] = this.editorObject.images_dataimg_filter;
121
+ this.editorObject.images_dataimg_filter = (img) => {
122
+ if (img.hasAttribute("class") && img.getAttribute("class").indexOf(Configuration.get("imageClassName")) !== -1) {
123
+ return img.hasAttribute("internal-blob");
124
+ }
125
+ // If the client put an image data filter, run. Otherwise default behaviour (put blob).
126
+ if (typeof dataImgFiltered[this.editorObject.id] !== "undefined") {
127
+ return dataImgFiltered[this.editorObject.id](img);
128
+ }
129
+ return true;
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Fires the event ExecCommand and transform a MathML into an image formula.
135
+ * @param {string} mathml - MathML to generate the formula and can be caught with the event.
136
+ */
137
+ updateFormula(mathml) {
138
+ if (typeof this.editorObject.fire !== "undefined") {
139
+ this.editorObject.fire("ExecCommand", {
140
+ command: "updateFormula",
141
+ value: mathml,
142
+ });
143
+ }
144
+ super.updateFormula(mathml);
145
+ }
146
+
147
+ /** @inheritdoc */
148
+ insertFormula(focusElement, windowTarget, mathml, wirisProperties) {
149
+ // Due to insertFormula adds an image using pure JavaScript functions,
150
+ // it is needed notificate to the editorObject that placeholder status
151
+ // has to be updated.
152
+ const obj = super.insertFormula(focusElement, windowTarget, mathml, wirisProperties);
153
+
154
+ // Add formula to undo & redo
155
+ this.editorObject.undoManager.add(obj);
156
+
157
+ return obj;
158
+ }
159
+
160
+ /**
161
+ * Set Moodle configuration on plugin.
162
+ * @param {string} editor - Editor instance.
163
+ * @param {string} pluginName - TinyMCE 7 plugin name.
164
+ */
165
+ registerMoodleOption(editor, pluginName) {
166
+ const registerOption = editor.options.register;
167
+
168
+ registerOption(`${pluginName}:filterEnabled`, {
169
+ processor: "boolean",
170
+ default: false,
171
+ });
172
+
173
+ registerOption(`${pluginName}:editorEnabled`, {
174
+ processor: "boolean",
175
+ default: false,
176
+ });
177
+
178
+ registerOption(`${pluginName}:chemistryEnabled`, {
179
+ processor: "boolean",
180
+ default: false,
181
+ });
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Object containing all TinyMCE integration instances. One for each TinyMCE editor.
187
+ * @type {Object}
188
+ */
189
+ export const instances = {};
190
+
191
+ /**
192
+ * TinyMCE integration current instance. The current instance
193
+ * is the instance related with the focused editor.
194
+ * @type {TinyMceIntegration}
195
+ */
196
+ export const currentInstance = null;
197
+
198
+ /*
199
+ Note: We have included the plugin in the same JavaScript file as the TinyMCE
200
+ instance for display purposes only. Tiny recommends not maintaining the plugin
201
+ with the TinyMCE instance and using the `external_plugins` option.
202
+ */
203
+ (function () {
204
+ const isMoodle = !!(typeof M === "object" && M !== null); // eslint-disable-line no-undef;
205
+ const pluginName = isMoodle ? "tiny_wiris/plugin" : "tiny_mce_wiris";
206
+
207
+ tinymce.PluginManager.add(pluginName, (editor, url) => ({
208
+ // eslint-disable-line no-unused-vars
209
+ init(editor) {
210
+ const callbackMethodArguments = {};
211
+
212
+ /**
213
+ * Integration model properties
214
+ * @type {Object}
215
+ * @property {Object} target - Integration DOM target.
216
+ * @property {String} configurationService - Configuration integration service.
217
+ * @property {String} version - Plugin version.
218
+ * @property {String} scriptName - Integration script name.
219
+ * @property {Object} environment - Integration environment properties.
220
+ * @property {String} editor - Editor name.
221
+ */
222
+ const integrationModelProperties = {};
223
+ integrationModelProperties.serviceProviderProperties = {
224
+ URI: process.env.SERVICE_PROVIDER_URI,
225
+ server: process.env.SERVICE_PROVIDER_SERVER,
226
+ };
227
+ integrationModelProperties.version = packageInfo.version;
228
+ integrationModelProperties.isMoodle = isMoodle; // eslint-disable-line no-undef
229
+ if (integrationModelProperties.isMoodle) {
230
+ // eslint-disable-next-line no-undef
231
+ integrationModelProperties.configurationService =
232
+ M.cfg.wwwroot + "/filter/wiris/integration/configurationjs.php"; // eslint-disable-line prefer-template
233
+ }
234
+ if (typeof editor.options.get("wiriscontextpath") !== "undefined") {
235
+ integrationModelProperties.configurationService = Util.concatenateUrl(
236
+ editor.options.get("wiriscontextpath"),
237
+ integrationModelProperties.configurationService,
238
+ );
239
+ `${editor.options.get("wiriscontextpath")}/${integrationModelProperties.configurationService}`; // eslint-disable-line no-unused-expressions
240
+ console.warn(
241
+ "Deprecated property wiriscontextpath. Use mathTypeParameters instead.",
242
+ editor.opts.wiriscontextpath,
243
+ );
244
+ }
245
+
246
+ // Overriding MathType integration parameters.
247
+
248
+ // Register our custom parameters inside TinyMCE's options
249
+ editor.options.register("mathTypeParameters", {
250
+ processor: "object",
251
+ default: {},
252
+ });
253
+
254
+ if (editor.options.isRegistered("mathTypeParameters")) {
255
+ integrationModelProperties.integrationParameters = editor.options.get("mathTypeParameters");
256
+ }
257
+
258
+ integrationModelProperties.scriptName = "plugin.min.js";
259
+ integrationModelProperties.environment = {};
260
+
261
+ integrationModelProperties.environment.editor = `TinyMCE ${tinymce.majorVersion}.x`;
262
+ integrationModelProperties.environment.editorVersion = `${tinymce.majorVersion}.${tinymce.minorVersion}`;
263
+
264
+ integrationModelProperties.callbackMethodArguments = callbackMethodArguments;
265
+ integrationModelProperties.editorObject = editor;
266
+ integrationModelProperties.initParsed = false;
267
+ // We need to create the instance before TinyMce initialization in order to register commands.
268
+ // However, as TinyMCE is not initialized at this point the HTML target is not created.
269
+ // Here we create the target as null and onInit object the target is updated.
270
+ integrationModelProperties.target = null;
271
+ const isExternalPlugin =
272
+ typeof editor.options.get("external_plugins") !== "undefined" &&
273
+ "tiny_mce_wiris" in editor.options.get("external_plugins");
274
+ integrationModelProperties.isExternal = isExternalPlugin;
275
+ integrationModelProperties.rtl = editor.options.get("directionality") === "rtl";
276
+
277
+ // Set Moodle configurations for Telemetry purposes.
278
+ const registerOption = editor.options.register;
279
+ registerOption(`${pluginName}:moodleCourseCategory`, {
280
+ processor: "integer",
281
+ default: undefined,
282
+ });
283
+ registerOption(`${pluginName}:moodleCourseName`, {
284
+ processor: "string",
285
+ default: undefined,
286
+ });
287
+ registerOption(`${pluginName}:moodleVersion`, {
288
+ processor: "integer",
289
+ default: undefined,
290
+ });
291
+
292
+ integrationModelProperties.environment.moodleVersion = editor.options.get(`${pluginName}:moodleVersion`);
293
+ integrationModelProperties.environment.moodleCourseCategory = editor.options.get(
294
+ `${pluginName}:moodleCourseCategory`,
295
+ );
296
+ integrationModelProperties.environment.moodleCourseName = editor.options.get(`${pluginName}:moodleCourseName`);
297
+
298
+ // GenericIntegration instance.
299
+ const tinyMceIntegrationInstance = new TinyMceIntegration(integrationModelProperties);
300
+ tinyMceIntegrationInstance.init();
301
+ WirisPlugin.instances[tinyMceIntegrationInstance.editorObject.id] = tinyMceIntegrationInstance;
302
+ WirisPlugin.currentInstance = tinyMceIntegrationInstance;
303
+
304
+ // Set Moodle configuration parameters to the plugin
305
+ if (isMoodle) {
306
+ tinyMceIntegrationInstance.registerMoodleOption(editor, pluginName);
307
+ }
308
+
309
+ const onInit = function (editor) {
310
+ // eslint-disable-line no-shadow
311
+ const integrationInstance = WirisPlugin.instances[tinyMceIntegrationInstance.editorObject.id];
312
+ if (!editor.inline) {
313
+ integrationInstance.setTarget(editor.getContentAreaContainer().firstChild);
314
+ } else {
315
+ integrationInstance.setTarget(editor.getElement());
316
+ }
317
+ integrationInstance.setEditorObject(editor);
318
+ integrationInstance.listeners.fire("onTargetReady", {});
319
+ if (editor.options.isRegistered("mathTypeParameters")) {
320
+ Configuration.update("editorParameters", editor.options.get("mathTypeParameters"));
321
+ }
322
+
323
+ // Prevent TinyMCE attributes insertion.
324
+ // TinyMCE insert attributes only when a new node is inserted.
325
+ // For this reason, the mutation observer only acts on addedNodes.
326
+ const mutationInstance = new MutationObserver(
327
+ function (editor, mutations) {
328
+ // eslint-disable-line no-shadow
329
+ Array.prototype.forEach.call(
330
+ mutations,
331
+ function (editor, mutation) {
332
+ // eslint-disable-line no-shadow
333
+ Array.prototype.forEach.call(
334
+ mutation.addedNodes,
335
+ function (editor, node) {
336
+ // eslint-disable-line no-shadow
337
+ if (node.nodeType === 1) {
338
+ // Act only in our own formulas.
339
+ Array.prototype.forEach.call(
340
+ node.querySelectorAll(`.${WirisPlugin.Configuration.get("imageClassName")}`),
341
+ ((editor, image) => {
342
+ // eslint-disable-line no-shadow
343
+ // This only is executed due to init parse.
344
+ image.removeAttribute("data-mce-src");
345
+ image.removeAttribute("data-mce-style");
346
+ }).bind(this, editor),
347
+ );
348
+ }
349
+ }.bind(this, editor),
350
+ );
351
+ }.bind(this, editor),
352
+ );
353
+ }.bind(this, editor),
354
+ );
355
+ mutationInstance.observe(editor.getBody(), {
356
+ attributes: true,
357
+ childList: true,
358
+ characterData: true,
359
+ subtree: true,
360
+ });
361
+
362
+ const content = editor.getContent();
363
+ // We set content in html because other tiny plugins need data-mce
364
+ // and this is not possible with raw format.
365
+ editor.setContent(Parser.initParse(content, editor.options.get("language")), { format: "html" });
366
+ // This clean undoQueue for prevent onChange and Dirty state.
367
+ editor.undoManager.clear();
368
+ // Init parsing OK. If a setContent method is called
369
+ // wrs_initParse is called again.
370
+ // Now if source code is edited the returned code is parsed.
371
+ // PLUGINS-1070: We set this variable out of condition to parse content after.
372
+ WirisPlugin.instances[editor.id].initParsed = true;
373
+ };
374
+
375
+ // Change the destroy behavior to also destroy the MathType instance.
376
+ const destroy = editor.destroy;
377
+
378
+ editor.destroy = function () {
379
+ WirisPlugin.instances[editor.id].listeners.fire("onDestroy", {});
380
+
381
+ // Destroy the Mathtype instance.
382
+ WirisPlugin.instances[editor.id].destroy();
383
+ destroy.call(editor);
384
+ };
385
+
386
+ if ("onInit" in editor) {
387
+ editor.onInit.add(onInit);
388
+ } else {
389
+ editor.on("init", () => {
390
+ onInit(editor);
391
+ });
392
+ }
393
+
394
+ if ("onActivate" in editor) {
395
+ editor.onActivate.add((editor) => {
396
+ // eslint-disable-line no-unused-vars, no-shadow
397
+ WirisPlugin.currentInstance = WirisPlugin.instances[tinymce.activeEditor.id];
398
+ });
399
+ } else {
400
+ editor.on("focus", (event) => {
401
+ // eslint-disable-line no-unused-vars, no-shadow
402
+ WirisPlugin.currentInstance = WirisPlugin.instances[tinymce.activeEditor.id];
403
+ });
404
+ }
405
+
406
+ const onSave = function (editor, params) {
407
+ // eslint-disable-line no-shadow
408
+ if (integrationModelProperties.isMoodle) {
409
+ params.content = Parser.endParseSaveMode(params.content, editor.getParam("language"));
410
+ } else {
411
+ params.content = Parser.endParse(params.content, editor.getParam("language"));
412
+ }
413
+ };
414
+
415
+ if ("onSaveContent" in editor) {
416
+ editor.onSaveContent.add(onSave);
417
+ } else {
418
+ editor.on("saveContent", (params) => {
419
+ onSave(editor, params);
420
+ });
421
+ }
422
+
423
+ if ("onGetContent" in editor) {
424
+ editor.onGetContent.add(onSave);
425
+ } else {
426
+ editor.on("getContent", (params) => {
427
+ onSave(editor, params);
428
+ });
429
+ }
430
+
431
+ if ("onBeforeSetContent" in editor) {
432
+ editor.onBeforeSetContent.add((e, params) => {
433
+ if (integrationModelProperties.isMoodle) {
434
+ params.content = Parser.initParseSaveMode(params.content, editor.getParam("language"));
435
+ } else if (WirisPlugin.instances[editor.id].initParsed) {
436
+ params.content = Parser.initParseSaveMode(params.content, editor.getParam("language"));
437
+ }
438
+ });
439
+ } else {
440
+ editor.on("beforeSetContent", (params) => {
441
+ if (integrationModelProperties.isMoodle) {
442
+ params.content = Parser.initParseSaveMode(params.content, editor.getParam("language"));
443
+ } else if (WirisPlugin.instances[editor.id].initParsed) {
444
+ params.content = Parser.initParse(params.content, editor.getParam("language"));
445
+ }
446
+ });
447
+ }
448
+
449
+ function openFormulaEditorFunction() {
450
+ const tinyMceIntegrationInstance = WirisPlugin.instances[editor.id]; // eslint-disable-line no-shadow
451
+ // Disable previous custom editors.
452
+ tinyMceIntegrationInstance.core.getCustomEditors().disable();
453
+ tinyMceIntegrationInstance.openNewFormulaEditor();
454
+ }
455
+
456
+ const commonEditor = editor.ui.registry;
457
+ const mathTypeIcon = "mathtypeicon";
458
+ const chemTypeIcon = "chemtypeicon";
459
+ const mathTypeIconSvg =
460
+ '<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"viewBox="0 0 300 261.7" style="enable-background:new 0 0 300 261.7;" xml:space="preserve"><g id=icon-wirisformula stroke="none" stroke-width="1" fill-rule="evenodd"><g><path class="st1" d="M90.2,257.7c-11.4,0-21.9-6.4-27-16.7l-60-119.9c-7.5-14.9-1.4-33.1,13.5-40.5c14.9-7.5,33.1-1.4,40.5,13.5l27.3,54.7L121.1,39c5.3-15.8,22.4-24.4,38.2-19.1c15.8,5.3,24.4,22.4,19.1,38.2l-59.6,179c-3.9,11.6-14.3,19.7-26.5,20.6C91.6,257.7,90.9,257.7,90.2,257.7"/></g></g><g><g><path class="st2" d="M300,32.8c0-16.4-13.4-29.7-29.9-29.7c-2.9,0-7.2,0.8-7.2,0.8c-37.9,9.1-71.3,14-112,14c-0.3,0-0.6,0-1,0c-16.5,0-29.9,13.3-29.9,29.7c0,16.4,13.4,29.7,29.9,29.7l0,0c45.3,0,83.1-5.3,125.3-15.3h0C289.3,59.5,300,47.4,300,32.8"/></g></g></svg>'; // eslint-disable-line max-len
461
+ const chemTypeIconSvg =
462
+ '<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"viewBox="0 0 40.3 49.5" style="enable-background:new 0 0 40.3 49.5;" xml:space="preserve"><g id=icon-wirisformula stroke="none" stroke-width="1" fill-rule="evenodd"><g><path class="st1" d="M39.2,12.1c0-1.9-1.1-3.6-2.7-4.4L24.5,0.9l0,0c-0.7-0.4-1.5-0.6-2.4-0.6c-0.9,0-1.7,0.2-2.4,0.6l0,0L2.3,10.8 l0,0C0.9,11.7,0,13.2,0,14.9h0v19.6h0c0,1.7,0.9,3.3,2.3,4.1l0,0l17.4,9.9l0,0c0.7,0.4,1.5,0.6,2.4,0.6c0.9,0,1.7-0.2,2.4-0.6l0,0 l12.2-6.9h0c1.5-0.8,2.6-2.5,2.6-4.3c0-2.7-2.2-4.9-4.9-4.9c-0.9,0-1.8,0.3-2.5,0.7l0,0l-9.7,5.6l-12.3-7V17.8l12.3-7l9.9,5.7l0,0 c0.7,0.4,1.5,0.6,2.4,0.6C37,17,39.2,14.8,39.2,12.1"/></g></g></svg>';
463
+
464
+ commonEditor.addIcon(mathTypeIcon, mathTypeIconSvg);
465
+ commonEditor.addIcon(chemTypeIcon, chemTypeIconSvg);
466
+
467
+ // Get editor language code
468
+ let lang_code = editor.options.get("language");
469
+ lang_code = lang_code.split("-")[0].split("_")[0];
470
+
471
+ // Check If MathType/ChemType are enabled on Moodle
472
+ const editorEnabled =
473
+ !isMoodle ||
474
+ (isMoodle &&
475
+ editor.options.get(`${pluginName}:editorEnabled`) &&
476
+ editor.options.get(`${pluginName}:filterEnabled`));
477
+ const chemEnabled =
478
+ !isMoodle ||
479
+ (isMoodle &&
480
+ editor.options.get(`${pluginName}:chemistryEnabled`) &&
481
+ editor.options.get(`${pluginName}:filterEnabled`));
482
+
483
+ if (editorEnabled) {
484
+ // The next two blocks create menu items to give the possibility
485
+ // of add MathType in the menubar.
486
+ commonEditor.addMenuItem("tiny_mce_wiris_formulaEditor", {
487
+ text: "MathType",
488
+ icon: mathTypeIcon,
489
+ onAction: openFormulaEditorFunction,
490
+ });
491
+
492
+ // MathType button.
493
+ commonEditor.addButton("tiny_mce_wiris_formulaEditor", {
494
+ tooltip: StringManager.get("insert_math", lang_code),
495
+ image: `${WirisPlugin.instances[editor.id].getIconsPath()}formula.png`,
496
+ onAction: openFormulaEditorFunction,
497
+ icon: mathTypeIcon,
498
+ });
499
+ }
500
+
501
+ if (chemEnabled) {
502
+ // Dynamic customEditors buttons.
503
+ const customEditors = WirisPlugin.instances[editor.id].getCore().getCustomEditors();
504
+ Object.keys(customEditors.editors).forEach((customEditor) => {
505
+ if (customEditors.editors[customEditor].confVariable) {
506
+ commonEditor.addMenuItem(`tiny_mce_wiris_formulaEditor${customEditors.editors[customEditor].name}`, {
507
+ text: customEditors.editors[customEditor].title,
508
+ icon: chemTypeIcon, // Parametrize when other custom editors are added.
509
+ onAction: () => {
510
+ customEditors.enable(customEditor);
511
+ WirisPlugin.instances[editor.id].openNewFormulaEditor();
512
+ },
513
+ });
514
+ }
515
+ });
516
+
517
+ // Dynamic customEditors buttons.
518
+ for (const customEditor in customEditors.editors) {
519
+ if (customEditors.editors[customEditor].confVariable) {
520
+ const cmd = `tiny_mce_wiris_openFormulaEditor${customEditors.editors[customEditor].name}`;
521
+ // eslint-disable-next-line no-inner-declarations, no-loop-func
522
+ function commandFunction() {
523
+ customEditors.enable(customEditor);
524
+ WirisPlugin.instances[editor.id].openNewFormulaEditor(); // eslint-disable-line no-undef
525
+ }
526
+ editor.addCommand(cmd, commandFunction);
527
+ commonEditor.addButton(`tiny_mce_wiris_formulaEditor${customEditors.editors[customEditor].name}`, {
528
+ tooltip: StringManager.get("insert_chem", lang_code),
529
+ onAction: commandFunction,
530
+ image: WirisPlugin.instances[editor.id].getIconsPath() + customEditors.editors[customEditor].icon,
531
+ icon: chemTypeIcon, // At the moment only chemTypeIcon because of the provisional solution for TinyMCE7.
532
+ });
533
+ }
534
+ }
535
+ }
536
+ },
537
+
538
+ // All versions.
539
+ getMetadata() {
540
+ return {
541
+ longname: "tiny_mce_wiris",
542
+ name: "Maths for More",
543
+ url: "http://www.wiris.com",
544
+ version: packageInfo.version,
545
+ };
546
+ },
547
+ }));
548
+ })();
package/global.js ADDED
@@ -0,0 +1,27 @@
1
+ import Core from "@wiris/mathtype-html-integration-devkit/src/core.src";
2
+ import Parser from "@wiris/mathtype-html-integration-devkit/src/parser";
3
+ import Util from "@wiris/mathtype-html-integration-devkit/src/util";
4
+ import Image from "@wiris/mathtype-html-integration-devkit/src/image";
5
+ import Configuration from "@wiris/mathtype-html-integration-devkit/src/configuration";
6
+ import Listeners from "@wiris/mathtype-html-integration-devkit/src/listeners";
7
+ import IntegrationModel from "@wiris/mathtype-html-integration-devkit/src/integrationmodel";
8
+ import Latex from "@wiris/mathtype-html-integration-devkit/src/latex";
9
+ import "@wiris/mathtype-html-integration-devkit/src/backwardslib";
10
+ import Test from "@wiris/mathtype-html-integration-devkit/src/test";
11
+ import { TinyMceIntegration, currentInstance, instances } from "./editor_plugin.src";
12
+
13
+ // Expose WirisPlugin variable to the window.
14
+ window.WirisPlugin = {
15
+ Core,
16
+ Parser,
17
+ Image,
18
+ Util,
19
+ Configuration,
20
+ Listeners,
21
+ IntegrationModel,
22
+ currentInstance,
23
+ instances,
24
+ TinyMceIntegration,
25
+ Latex,
26
+ Test,
27
+ };