diff --git a/ts/components/startup.ts b/ts/components/startup.ts index 3cac215a8..12321c5ae 100644 --- a/ts/components/startup.ts +++ b/ts/components/startup.ts @@ -342,12 +342,13 @@ export abstract class Startup { public static typesetPromise(elements: any[]): Promise { Startup.document.options.elements = elements; Startup.document.reset(); - return Startup.mathjax.handleRetriesFor(() => { + Startup.rerenderPromise = Startup.promise = Startup.mathjax.handleRetriesFor(() => { Startup.document.render(); const promise = Promise.all(Startup.document.renderPromises); Startup.document.renderPromises = []; return promise; }); + return Startup.promise; } /** diff --git a/ts/output/common.ts b/ts/output/common.ts index dd6134848..5757f2afd 100644 --- a/ts/output/common.ts +++ b/ts/output/common.ts @@ -404,13 +404,17 @@ export abstract class CommonOutputJax< if (linebreak) { this.getLinebreakWidth(); } + const inlineMarked = !!math.root.getProperty('inlineMarked'); if ( this.options.linebreaks.inline && !math.display && - !math.outputData.inlineMarked + !inlineMarked ) { this.markInlineBreaks(math.root.childNodes?.[0]); - math.outputData.inlineMarked = true; + math.root.setProperty('inlineMarked', true); + } else if (!this.options.linebreaks.inline && inlineMarked) { + this.unmarkInlineBreaks(math.root); + math.root.setProperty('inlineMarked', false); } math.root.setTeXclass(null); const wrapper = this.factory.wrap(math.root); @@ -588,6 +592,21 @@ export abstract class CommonOutputJax< return marked; } + /** + * @param {MmlNode} node The node where inline breaks are to be removed + */ + public unmarkInlineBreaks(node: MmlNode) { + if (!node) return; + node.removeProperty('forcebreak'); + node.removeProperty('breakable'); + if (node.getProperty('process-breaks')) { + node.removeProperty('process-breaks'); + for (const child of node.childNodes) { + this.unmarkInlineBreaks(child); + } + } + } + /** * @override */ diff --git a/ts/output/common/Wrapper.ts b/ts/output/common/Wrapper.ts index 95b1ac4d8..2504e55dd 100644 --- a/ts/output/common/Wrapper.ts +++ b/ts/output/common/Wrapper.ts @@ -1220,12 +1220,12 @@ export class CommonWrapper< return ['left', 0]; } if (!align || align === 'auto') { - align = this.jax.math.outputData.inlineMarked + align = this.jax.math.root.getProperty('inlineMarked') ? 'left' : this.jax.options.displayAlign; } if (!shift || shift === 'auto') { - shift = this.jax.math.outputData.inlineMarked + shift = this.jax.math.root.getProperty('inlineMarked') ? '0' : this.jax.options.displayIndent; } diff --git a/ts/ui/menu/MJContextMenu.ts b/ts/ui/menu/MJContextMenu.ts index 5a5aa31bb..2044992e5 100644 --- a/ts/ui/menu/MJContextMenu.ts +++ b/ts/ui/menu/MJContextMenu.ts @@ -55,6 +55,11 @@ export class MJContextMenu extends ContextMenu { */ public mathItem: MathItem = null; + /** + * True when the menu is posted while the explorer is in operation + */ + public refocus: boolean = false; + /** * The document options */ @@ -80,6 +85,7 @@ export class MJContextMenu extends ContextMenu { */ public post(x?: any, y?: number) { if (this.mathItem) { + this.refocus = document.activeElement.nodeName.toLowerCase() !== 'mjx-container'; if (y !== undefined) { this.getOriginalMenu(); this.getSemanticsMenu(); @@ -99,9 +105,20 @@ export class MJContextMenu extends ContextMenu { * @override */ public unpost() { - super.unpost(); - this.mathItem?.typesetRoot?.blur(); this.mathItem = null; + if (this.refocus) { + super.unpost(); + return; + } + // + // Prevent store.active.focus() from refocusing the menu in super.unpost() + // (no pretty way to do it without making changes to mj-context-menu) + // + const store = this.store; + const active = store.active; + (store as any)._active = document.body; + super.unpost(); + store.active = active; } /*======================================================================*/ diff --git a/ts/ui/menu/Menu.ts b/ts/ui/menu/Menu.ts index dd7b2db21..b92700f8f 100644 --- a/ts/ui/menu/Menu.ts +++ b/ts/ui/menu/Menu.ts @@ -499,11 +499,11 @@ export class Menu { this.jax[jax.name] = jax; this.settings.renderer = jax.name; this.settings.scale = jax.options.scale; - this.defaultSettings = Object.assign({}, this.settings); this.settings.overflow = jax.options.displayOverflow.substring(0, 1).toUpperCase() + jax.options.displayOverflow.substring(1).toLowerCase(); this.settings.breakInline = jax.options.linebreaks.inline; + this.defaultSettings = Object.assign({}, this.document.options.a11y, this.settings); } /** @@ -1019,7 +1019,9 @@ export class Menu { */ protected setOverflow(overflow: string) { this.document.outputJax.options.displayOverflow = overflow.toLowerCase(); - this.document.rerender(); + if (!Menu.loading) { + this.document.rerender(); + } } /** @@ -1027,7 +1029,9 @@ export class Menu { */ protected setInlineBreaks(breaks: boolean) { this.document.outputJax.options.linebreaks.inline = breaks; - this.document.rerender(); + if (!Menu.loading) { + this.document.rerender(); + } } /** @@ -1035,7 +1039,9 @@ export class Menu { */ protected setScale(scale: string) { this.document.outputJax.options.scale = parseFloat(scale); - this.document.rerender(); + if (!Menu.loading) { + this.document.rerender(); + } } /** @@ -1277,15 +1283,17 @@ export class Menu { Menu.loading++; // pretend we're loading, to suppress rerendering for each variable change const pool = this.menu.pool; const settings = this.defaultSettings; - for (const name of Object.keys(this.settings) as (keyof MenuSettings)[]) { + for (const name of Object.keys(settings) as (keyof MenuSettings)[]) { const variable = pool.lookup(name); if (variable) { - variable.setValue(settings[name] as string | boolean); - const item = (variable as any).items[0]; - if (item) { - item.executeCallbacks_(); + if (variable.getValue() !== settings[name]) { + variable.setValue(settings[name] as string | boolean); + const item = (variable as any).items[0]; + if (item) { + item.executeCallbacks_(); + } } - } else { + } else if (Object.hasOwn(this.settings, name)) { (this.settings as any)[name] = settings[name]; } } @@ -1366,6 +1374,13 @@ export class Menu { this.document = startup.document = startup.getDocument(); this.document.menu = this; this.setA11y(this.settings); + this.defaultSettings = + Object.assign( + {}, + this.document.options.a11y, + MathJax.config?.options?.a11y || {}, + this.defaultSettings + ); this.document.outputJax.reset(); this.transferMathList(document); this.document.processed = document.processed; @@ -1468,11 +1483,8 @@ export class Menu { math.root = root.copy(true); math.root.setInheritedAttributes({}, math.display, 0, false); if (breaks) { - math.root.walkTree((n) => { - n.removeProperty('process-breaks'); - n.removeProperty('forcebreak'); - n.removeProperty('breakable'); - }); + jax.unmarkInlineBreaks(math.root); + math.root.setProperty('inlineMarked', false); } const promise = mathjax.handleRetriesFor(() => { jax.toDOM(math, div, jax.document); @@ -1554,6 +1566,7 @@ export class Menu { * @param {number=} start The state at which to start rerendering */ protected rerender(start: number = STATE.TYPESET) { + this.menu.refocus = false; this.rerenderStart = Math.min(start, this.rerenderStart); const startup = MathJax.startup; if (!Menu.loading && startup.rerenderPromise) {