Skip to content

Commit 292e3c6

Browse files
test: Use SDK
1 parent c22407d commit 292e3c6

3 files changed

Lines changed: 127 additions & 98 deletions

File tree

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"lint": "prettier --write . --ignore-path .gitignore --ignore-path .prettierignore --ignore-path .eslintignore && nx run-many --target=lint --all --parallel --fix"
1616
},
1717
"devDependencies": {
18+
"@wiris/mathtype.integrations.sdk": "^1.1.3",
1819
"@babel/eslint-parser": "^7.24.1",
1920
"@nrwl/js": "18.2.2",
2021
"@nrwl/tao": "18.2.2",

packages/devkit/src/contentmanager.js

Lines changed: 125 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import Configuration from "./configuration";
22
import Core from "./core.src";
3-
import EditorListener from "./editorlistener";
43
import Listeners from "./listeners";
54
import MathML from "./mathml";
65
import Util from "./util";
76
import Telemeter from "./telemeter";
7+
import SDK from "@wiris/mathtype.integrations.sdk";
88

99
export default class ContentManager {
1010
/**
@@ -69,14 +69,22 @@ export default class ContentManager {
6969
}
7070

7171
/**
72-
* {@link EditorListener} instance. Manages the changes inside the editor.
73-
* @type {EditorListener}
72+
* Tracks whether the editor content has been changed by the user.
73+
* Replaces the old EditorListener class.
74+
* @type {Boolean}
75+
*/
76+
this.isContentChanged = false;
77+
78+
/**
79+
* Whether the content manager is waiting for changes from the editor.
80+
* @type {Boolean}
7481
*/
75-
this.editorListener = new EditorListener();
82+
this.waitingForChanges = false;
7683

7784
/**
78-
* MathType editor instance.
79-
* @type {JsEditor}
85+
* SDK Editor instance. This is the only editor reference needed.
86+
* Created via the SDK's createEditor() factory method.
87+
* @type {import("@wiris/mathtype.integrations.sdk").Editor}
8088
*/
8189
this.editor = null;
8290

@@ -174,77 +182,93 @@ export default class ContentManager {
174182
}
175183

176184
/**
177-
* Inserts MathType editor into the {@link ModalDialog.contentContainer}. It waits until
178-
* editor's JavaScript is loaded.
185+
* Inserts MathType editor into the {@link ModalDialog.contentContainer} using the SDK Editor.
186+
* The SDK handles script loading and JsEditor instantiation internally.
179187
*/
180188
insertEditor() {
181-
if (ContentManager.isEditorLoaded()) {
182-
this.editor = window.com.wiris.jsEditor.JsEditor.newInstance(this.editorAttributes);
183-
this.editor.insertInto(this.modalDialogInstance.contentContainer);
184-
this.editor.focus();
189+
const container = this.modalDialogInstance.contentContainer;
185190

186-
// `editor.action("rtl");` toggles the RTL mode based on the current state, it doesn't just switch to RTL.
187-
if (this.modalDialogInstance.rtl && !this.editor.getEditorModel().isRTL()) {
188-
this.editor.action("rtl");
189-
}
190-
// Setting div in rtl in case of it's activated.
191-
if (this.editor.getEditorModel().isRTL()) {
192-
this.editor.element.style.direction = "rtl";
193-
}
191+
// Ensure the container has an id so the SDK Editor can find it.
192+
if (!container.id) {
193+
container.id = "wrs_sdk_editor_container";
194+
}
194195

195-
// Editor listener: this object manages the changes logic of editor.
196-
this.editor.getEditorModel().addEditorListener(this.editorListener);
196+
// Derive the SDK base URL from the configured editorUrl.
197+
const editorUrl = ContentManager.getEditorBaseUrl();
198+
199+
// Map the current editorAttributes to the SDK EditorConfig.
200+
const sdkEditorConfig = {
201+
language: this.editorAttributes.language || this.language,
202+
toolbar: this.editorAttributes.toolbar || "general",
203+
};
204+
205+
// Create the SDK instance and the SDK Editor.
206+
const sdkInstance = new SDK({ url: "patata" });
207+
console.log("Creating SDK Editor with config:", sdkEditorConfig);
208+
this.editor = sdkInstance.createEditor(sdkEditorConfig);
209+
210+
// Use the SDK's ContentChanged event to track changes
211+
// (replaces the old EditorListener pattern).
212+
this.editor.on("ContentChanged", () => {
213+
if (this.waitingForChanges && !this.isContentChanged) {
214+
this.isContentChanged = true;
215+
}
216+
});
197217

218+
// Listen for the EditorReady event to perform post-init setup.
219+
this.editor.on("EditorReady", () => {
198220
// iOS events.
199-
if (this.modalDialogInstance.deviceProperties.isIOS) {
221+
if (this.modalDialogInstance.deviceProperties?.isIOS) {
200222
setTimeout(function () {
201-
// Make sure the modalDialogInstance is available when the timeout is over
202-
// to avoid throw errors and stop execution.
203223
if (this.hasOwnProperty("modalDialogInstance")) this.modalDialogInstance.hideKeyboard(); // eslint-disable-line no-prototype-builtins
204224
}, 400);
205225

206226
const formulaDisplayDiv = document.getElementsByClassName("wrs_formulaDisplay")[0];
207-
Util.addEvent(formulaDisplayDiv, "focus", this.modalDialogInstance.handleOpenedIosSoftkeyboard);
208-
Util.addEvent(formulaDisplayDiv, "blur", this.modalDialogInstance.handleClosedIosSoftkeyboard);
227+
if (formulaDisplayDiv) {
228+
Util.addEvent(formulaDisplayDiv, "focus", this.modalDialogInstance.handleOpenedIosSoftkeyboard);
229+
Util.addEvent(formulaDisplayDiv, "blur", this.modalDialogInstance.handleClosedIosSoftkeyboard);
230+
}
209231
}
210-
// Fire onLoad event. Necessary to set the MathML into the editor
211-
// after is loaded.
232+
233+
// Fire onLoad event. Necessary to set the MathML into the editor after it is loaded.
212234
this.listeners.fire("onLoad", {});
213-
} else {
214-
setTimeout(ContentManager.prototype.insertEditor.bind(this), 100);
215-
}
216-
}
235+
});
217236

218-
/**
219-
* Initializes the current class by loading MathType script.
220-
*/
221-
init() {
222-
if (!ContentManager.isEditorLoaded()) {
223-
this.addEditorAsExternalDependency();
224-
}
237+
// Kick off the SDK Editor initialization (loads script + creates editor in the container).
238+
this.editor.init(container.id);
225239
}
226240

227241
/**
228-
* Adds script element to the DOM to include editor externally.
242+
* Returns the base URL for the SDK from the configured editorUrl.
243+
* Strips the trailing "/editor" segment if present.
244+
* @returns {String} The SDK-compatible base URL.
229245
*/
230-
addEditorAsExternalDependency() {
231-
const script = document.createElement("script");
232-
script.type = "text/javascript";
246+
static getEditorBaseUrl() {
233247
let editorUrl = Configuration.get("editorUrl");
234248

235-
// We create an object url for parse url string and work more efficiently.
249+
// Normalize protocol.
236250
const anchorElement = document.createElement("a");
237-
238251
ContentManager.setHrefToAnchorElement(anchorElement, editorUrl);
239252
ContentManager.setProtocolToAnchorElement(anchorElement);
240-
241253
editorUrl = ContentManager.getURLFromAnchorElement(anchorElement);
242254

243-
// Load editor URL. We add stats as GET params.
244-
const stats = this.getEditorStats();
245-
script.src = `${editorUrl}?lang=${this.language}&stats-editor=${stats.editor}&stats-mode=${stats.mode}&stats-version=${stats.version}`;
255+
// The SDK appends "/editor" internally, so strip it from the configured URL.
256+
if (editorUrl.endsWith("/editor")) {
257+
editorUrl = editorUrl.slice(0, -"/editor".length);
258+
}
246259

247-
document.getElementsByTagName("head")[0].appendChild(script);
260+
return editorUrl;
261+
}
262+
263+
/**
264+
* Initializes the current class.
265+
* With the SDK, script loading is handled by the SDK Editor's init() method,
266+
* so this method is now a no-op. The SDK will load the editor script
267+
* when insertEditor() calls sdkEditor.init().
268+
*/
269+
init() {
270+
// Script loading is now deferred to insertEditor() via the SDK.
271+
// No pre-loading is needed.
248272
}
249273

250274
/**
@@ -338,18 +362,13 @@ export default class ContentManager {
338362

339363
/**
340364
* Returns true if editor is loaded. Otherwise, false.
365+
* With the SDK, the editor script loading is handled internally by the SDK Editor.
366+
* This always returns false since the SDK uses async init — callers should
367+
* rely on the 'onLoad' listener event instead.
341368
* @returns {Boolean}
342369
*/
343370
static isEditorLoaded() {
344-
// To know if editor JavaScript is loaded we need to wait until
345-
// window.com.wiris.jsEditor.JsEditor.newInstance is ready.
346-
return (
347-
window.com &&
348-
window.com.wiris &&
349-
window.com.wiris.jsEditor &&
350-
window.com.wiris.jsEditor.JsEditor &&
351-
window.com.wiris.jsEditor.JsEditor.newInstance
352-
);
371+
return false;
353372
}
354373

355374
/**
@@ -362,28 +381,26 @@ export default class ContentManager {
362381
}
363382

364383
/**
365-
* Sets a MathML into {@link ContentManager.editor} instance.
384+
* Sets a MathML into the SDK Editor instance.
366385
* @param {String} mathml - MathML string.
367-
* @param {Boolean} focusDisabled - If true editor don't get focus after the MathML is set.
386+
* @param {Boolean} focusDisabled - If true editor doesn't get focus after the MathML is set.
368387
* False by default.
369388
*/
370389
setMathML(mathml, focusDisabled) {
371-
// By default focus is enabled.
372390
if (typeof focusDisabled === "undefined") {
373391
focusDisabled = false;
374392
}
375-
// Using setMathML method is not a change produced by the user but for the API
376-
// so we set to false the contentChange property of editorListener.
377-
this.editor.setMathMLWithCallback(mathml, () => {
378-
this.editorListener.setWaitingForChanges(true);
379-
});
393+
// The SDK Editor's setMathML is synchronous.
394+
// We manage the change tracking state directly.
395+
this.editor.setMathML(mathml);
396+
this.waitingForChanges = true;
380397

381-
// We need to wait a little until the callback finish.
398+
// We need to wait a little to allow the editor to settle before
399+
// resetting the content changed flag (same timing as the original).
382400
setTimeout(() => {
383-
this.editorListener.setIsContentChanged(false);
401+
this.isContentChanged = false;
384402
}, 500);
385403

386-
// In some scenarios - like closing modal object - editor mustn't be focused.
387404
if (!focusDisabled) {
388405
this.onFocus();
389406
}
@@ -410,7 +427,7 @@ export default class ContentManager {
410427
* Triggered by {@link ModalDialog.submitAction}.
411428
*/
412429
submitAction() {
413-
if (!this.editor.isFormulaEmpty()) {
430+
if (!this.editor.isEmpty()) {
414431
let mathML = this.editor.getMathMLWithSemantics();
415432
// Add class for custom editors.
416433
if (this.customEditors.getActiveEditor() !== null) {
@@ -438,13 +455,14 @@ export default class ContentManager {
438455
}
439456

440457
/**
441-
* Sets an empty MathML as {@link ContentManager.editor} content.
458+
* Sets an empty MathML as editor content.
442459
* This will open the MT/CT editor with the hand mode.
443460
* It adds dir rtl in case of it's activated.
444461
*/
445462
setEmptyMathML() {
446463
const isMobile = this.deviceProperties.isAndroid || this.deviceProperties.isIOS;
447-
const isRTL = this.editor.getEditorModel().isRTL();
464+
// Use the RTL flag from the modal dialog instance (set during integration init).
465+
const isRTL = this.modalDialogInstance?.rtl || false;
448466

449467
if (isMobile || this.integrationModel.forcedHandMode) {
450468
// For mobile devices or forced hand mode, set an empty annotation MATHML to maintain the editor in Hand mode.
@@ -563,34 +581,36 @@ export default class ContentManager {
563581
* It will open any formula written in Keyboard mode with the hand mode with the default hand trace.
564582
*
565583
* @param {String} mathml The original KeyBoard MathML
566-
* @param {Object} editor The editor object.
584+
* @param {Object} editor The SDK Editor instance.
567585
*/
568586
async openHandOnKeyboardMathML(mathml, editor) {
569-
// First, as an editor requirement, we need to update the editor object with the current MathML formula.
570-
// Once the MathML formula is updated to the one we want to open with handMode, we will be able to proceed.
571-
await new Promise((resolve) => {
572-
editor.setMathMLWithCallback(mathml, resolve);
573-
});
574-
575-
// We wait until the hand editor object exists.
576-
await this.waitForHand(editor);
587+
// Set the MathML first via the SDK Editor (synchronous).
588+
editor.setMathML(mathml);
589+
590+
// Use the SDK's getHand() to access the hand editor.
591+
const handAccessor = editor.getHand();
592+
if (!handAccessor) {
593+
// Wait for the hand editor to become available.
594+
await new Promise((resolve) => {
595+
const interval = setInterval(() => {
596+
if (editor.getHand()) {
597+
clearInterval(interval);
598+
resolve();
599+
}
600+
}, 100);
601+
});
602+
}
577603

578-
// Logic to get the hand traces and open the formula in hand mode.
579-
// This logic comes from the editor.
580-
const handEditor = editor.hand;
581-
editor.handTemporalMathML = editor.getMathML();
582-
const handCoordinates = editor.editorModel.getHandStrokes();
583-
handEditor.setStrokes(handCoordinates);
584-
handEditor.fitStrokes(true);
585-
editor.openHand();
604+
// Switch to handwriting input mode via the SDK.
605+
editor.setInputMode("handwriting");
586606
}
587607

588608
/**
589609
* Waits until the hand editor object exists.
590-
* @param {Obect} editor The editor object.
610+
* @param {Object} editor The SDK Editor instance.
591611
*/
592612
async waitForHand(editor) {
593-
while (!editor.hand) {
613+
while (!editor.getHand()) {
594614
await new Promise((resolve) => setTimeout(resolve, 100));
595615
}
596616
}
@@ -656,16 +676,22 @@ export default class ContentManager {
656676
}
657677

658678
/**
659-
* Sets the current {@link ContentManager.editor} instance toolbar.
679+
* Sets the current editor toolbar.
680+
* Note: With the SDK Editor, the toolbar is set at creation time via EditorConfig.
681+
* Runtime toolbar changes require re-creating the editor. For now, we store the value
682+
* for reference but it will only take effect on the next editor creation.
660683
* @param {String} toolbar - The toolbar name.
661684
*/
662685
setToolbar(toolbar) {
663686
this.toolbar = toolbar;
664-
this.editor.setParams({ toolbar: this.toolbar });
687+
// The SDK Editor does not support runtime toolbar changes via setParams.
688+
// The toolbar is applied when the editor is created in insertEditor().
689+
console.warn("ContentManager.setToolbar: Runtime toolbar change is not supported by the SDK Editor. It will take effect on next editor open.");
665690
}
666691

667692
/**
668693
* Sets the custom headers added on editor requests.
694+
* Note: With the SDK Editor, custom headers are not supported via setParams.
669695
* @returns {Object} headers - key value headers.
670696
*/
671697
setCustomHeaders(headers) {
@@ -678,17 +704,18 @@ export default class ContentManager {
678704
headersObj = Util.convertStringToObject(headers);
679705
}
680706

681-
this.editor.setParams({ customHeaders: headersObj });
707+
// The SDK Editor does not support setParams for custom headers.
708+
console.warn("ContentManager.setCustomHeaders: Custom headers are not supported by the SDK Editor.");
682709
return headersObj;
683710
}
684711

685712
/**
686713
* Returns true if the content of the editor has been changed. The logic of the changes
687-
* is delegated to {@link EditorListener} class.
714+
* is tracked via the SDK Editor's ContentChanged event.
688715
* @returns {Boolean} True if the editor content has been changed. False otherwise.
689716
*/
690717
hasChanges() {
691-
return !this.editor.isFormulaEmpty() && this.editorListener.getIsContentChanged();
718+
return !this.editor.isEmpty() && this.isContentChanged;
692719
}
693720

694721
/**

0 commit comments

Comments
 (0)