From 94d8736a3fb00d1123b80055ccd9f4cae2989936 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 5 Feb 2026 08:52:42 -0500 Subject: [PATCH 1/3] Add isEmpty test (deep tree check) to MmlNode and use it to test for empty mathop. --- testsuite/tests/input/tex/Base.test.ts | 17 ++++++++++++++++- ts/core/MmlTree/MmlNode.ts | 23 +++++++++++++++++++++++ ts/input/tex/base/BaseItems.ts | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/input/tex/Base.test.ts b/testsuite/tests/input/tex/Base.test.ts index 680765ab2..13aedaced 100644 --- a/testsuite/tests/input/tex/Base.test.ts +++ b/testsuite/tests/input/tex/Base.test.ts @@ -12191,7 +12191,7 @@ describe('Character Class Changes', () => { /********************************************************************************/ - it('Mathop No Apply', () => { + it('Mathop No Apply I', () => { toXmlMatch( tex2mml('\\mathop{} x'), ` @@ -12203,6 +12203,21 @@ describe('Character Class Changes', () => { /********************************************************************************/ + it('Mathop no Apply II', () => { + toXmlMatch( + tex2mml('\\mathop{\\mathrm{}{}} x'), + ` + + + + + x + ` + ); + }); + + /********************************************************************************/ + it('Mathrel', () => { toXmlMatch( tex2mml('\\mathrel{R}'), diff --git a/ts/core/MmlTree/MmlNode.ts b/ts/core/MmlTree/MmlNode.ts index 7fe0c8155..eb071e112 100644 --- a/ts/core/MmlTree/MmlNode.ts +++ b/ts/core/MmlTree/MmlNode.ts @@ -144,6 +144,7 @@ export interface MmlNode extends Node { readonly isSpacelike: boolean; readonly linebreakContainer: boolean; readonly linebreakAlign: string; + readonly isEmpty: boolean; /** * The expected number of children (-1 means use inferred mrow) @@ -540,6 +541,16 @@ export abstract class AbstractMmlNode return 'data-align'; } + /** + * @returns {string} True if all child nodes are empty + */ + public get isEmpty(): boolean { + for (const child of this.childNodes) { + if (!child.isEmpty) return false; + } + return true; + } + /** * @returns {number} The number of children allowed, or Infinity for any number, * or -1 for when an inferred row is needed for the children. @@ -1023,6 +1034,18 @@ export abstract class AbstractMmlTokenNode extends AbstractMmlNode { return true; } + /** + * @override + */ + public get isEmpty() { + for (const child of this.childNodes) { + if (!(child instanceof TextNode) || child.getText().length) { + return false; + } + } + return true; + } + /** * Get the text of the token node (skipping mglyphs, and combining * multiple text nodes) diff --git a/ts/input/tex/base/BaseItems.ts b/ts/input/tex/base/BaseItems.ts index 960fa3a2a..7e89a15d9 100644 --- a/ts/input/tex/base/BaseItems.ts +++ b/ts/input/tex/base/BaseItems.ts @@ -788,7 +788,7 @@ export class FnItem extends BaseItem { } } // @test Mathop Apply, Mathop No Apply - if (top.isKind('TeXAtom') && top.childNodes[0].childNodes.length === 0) { + if (top.isKind('TeXAtom') && top.isEmpty) { return [[top, item], true]; } // @test Named Function, Named Function Arg From a43a44f5446814064bbfe66c5402d985637a8a9f Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 5 Feb 2026 09:03:13 -0500 Subject: [PATCH 2/3] Add isEmpty to AbstractMmlEmptyNode --- ts/core/MmlTree/MmlNode.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ts/core/MmlTree/MmlNode.ts b/ts/core/MmlTree/MmlNode.ts index eb071e112..5ee7ed3ef 100644 --- a/ts/core/MmlTree/MmlNode.ts +++ b/ts/core/MmlTree/MmlNode.ts @@ -1251,6 +1251,13 @@ export abstract class AbstractMmlEmptyNode return false; } + /** + * @returns {boolean} Is empty + */ + public get isEmpty(): boolean { + return true; + } + /** * @returns {boolean} Not embellished */ From 574e1c36b5165890cc218f7cfc354fa09f233231 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 5 Feb 2026 13:04:04 -0500 Subject: [PATCH 3/3] Use isEmpty in MathtoolsUtil, as request in review --- ts/input/tex/mathtools/MathtoolsUtil.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/input/tex/mathtools/MathtoolsUtil.ts b/ts/input/tex/mathtools/MathtoolsUtil.ts index b7dc01f4b..3134c888b 100644 --- a/ts/input/tex/mathtools/MathtoolsUtil.ts +++ b/ts/input/tex/mathtools/MathtoolsUtil.ts @@ -158,7 +158,7 @@ export const MathtoolsUtil = { parser.stack.env, parser.configuration ).mml(); - return mml.isKind('TeXAtom') && mml.childNodes[0].childNodes.length === 0 + return mml.isKind('TeXAtom') && mml.isEmpty ? parser.create('node', 'none') : mml; },