From 7fd8e44b5afae79621c5aaf4489a61af303486f2 Mon Sep 17 00:00:00 2001
From: "Davide P. Cervone" <dpvc@union.edu>
Date: Thu, 24 Oct 2024 17:36:04 -0400
Subject: [PATCH 1/2] Make over/under braces and matrices be full size, as in
 actual TeX (mathjax/MathJax#3300)

---
 ts/core/MmlTree/MmlNode.ts         | 10 ++--------
 ts/core/MmlTree/MmlNodes/mtable.ts |  1 -
 ts/core/MmlTree/MmlVisitor.ts      |  3 +--
 ts/input/mathml/MathMLCompile.ts   |  2 +-
 ts/input/tex.ts                    |  5 +++--
 ts/input/tex/FilterUtil.ts         | 28 ++++++++++++++++++++++++++++
 ts/input/tex/ParseUtil.ts          |  4 +++-
 ts/input/tex/ams/AmsMappings.ts    |  4 ++--
 ts/input/tex/base/BaseItems.ts     |  5 ++++-
 ts/input/tex/base/BaseMethods.ts   |  2 ++
 10 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/ts/core/MmlTree/MmlNode.ts b/ts/core/MmlTree/MmlNode.ts
index 3575d6704..937fc88c1 100644
--- a/ts/core/MmlTree/MmlNode.ts
+++ b/ts/core/MmlTree/MmlNode.ts
@@ -771,14 +771,8 @@ export abstract class AbstractMmlNode
         delete attributes[key];
       }
     }
-    const displaystyle = this.attributes.getExplicit('displaystyle');
-    if (displaystyle === undefined) {
-      this.attributes.setInherited('displaystyle', display);
-    }
-    const scriptlevel = this.attributes.getExplicit('scriptlevel');
-    if (scriptlevel === undefined) {
-      this.attributes.setInherited('scriptlevel', level);
-    }
+    this.attributes.setInherited('displaystyle', display);
+    this.attributes.setInherited('scriptlevel', level);
     if (prime) {
       this.setProperty('texprimestyle', prime);
     }
diff --git a/ts/core/MmlTree/MmlNodes/mtable.ts b/ts/core/MmlTree/MmlNodes/mtable.ts
index b50f26258..b803fcb6b 100644
--- a/ts/core/MmlTree/MmlNodes/mtable.ts
+++ b/ts/core/MmlTree/MmlNodes/mtable.ts
@@ -142,7 +142,6 @@ export class MmlMtable extends AbstractMmlNode {
         this.replaceChild(this.factory.create('mtr'), child).appendChild(child);
       }
     }
-    level = (this.getProperty('scriptlevel') as number) || level;
     display = !!(
       this.attributes.getExplicit('displaystyle') ||
       this.attributes.getDefault('displaystyle')
diff --git a/ts/core/MmlTree/MmlVisitor.ts b/ts/core/MmlTree/MmlVisitor.ts
index de1bcfead..dcdef661c 100644
--- a/ts/core/MmlTree/MmlVisitor.ts
+++ b/ts/core/MmlTree/MmlVisitor.ts
@@ -201,8 +201,7 @@ export class MmlVisitor extends AbstractVisitor<MmlNode> {
           texclass < 0 ? 'NONE' : TEXCLASSNAMES[texclass]
         );
     }
-    node.getProperty('scriptlevel') &&
-      node.getProperty('useHeight') === false &&
+    node.getProperty('smallmatrix') &&
       this.setDataAttribute(data, 'smallmatrix', 'true');
     return data;
   }
diff --git a/ts/input/mathml/MathMLCompile.ts b/ts/input/mathml/MathMLCompile.ts
index 74464c4e1..bf7919157 100644
--- a/ts/input/mathml/MathMLCompile.ts
+++ b/ts/input/mathml/MathMLCompile.ts
@@ -215,7 +215,7 @@ export class MathMLCompile<N, T, D> {
             ignoreVariant = true;
             break;
           case 'smallmatrix':
-            mml.setProperty('scriptlevel', 1);
+            mml.setProperty('smallmatrix', true);
             mml.setProperty('useHeight', false);
             break;
           case 'mathaccent':
diff --git a/ts/input/tex.ts b/ts/input/tex.ts
index f6dce8bad..1b19bafb3 100644
--- a/ts/input/tex.ts
+++ b/ts/input/tex.ts
@@ -157,8 +157,9 @@ export class TeX<N, T, D> extends AbstractInputJax<N, T, D> {
     userOptions(parseOptions.options, rest);
     configuration.config(this);
     TeX.tags(parseOptions, configuration);
-    this.postFilters.add(FilterUtil.cleanSubSup, -6);
-    this.postFilters.add(FilterUtil.setInherited, -5);
+    this.postFilters.add(FilterUtil.cleanSubSup, -7);
+    this.postFilters.add(FilterUtil.setInherited, -6);
+    this.postFilters.add(FilterUtil.checkScriptlevel, -5);
     this.postFilters.add(FilterUtil.moveLimits, -4);
     this.postFilters.add(FilterUtil.cleanStretchy, -3);
     this.postFilters.add(FilterUtil.cleanAttributes, -2);
diff --git a/ts/input/tex/FilterUtil.ts b/ts/input/tex/FilterUtil.ts
index 1d3959e7c..f748e3f49 100644
--- a/ts/input/tex/FilterUtil.ts
+++ b/ts/input/tex/FilterUtil.ts
@@ -333,6 +333,34 @@ namespace FilterUtil {
   }) {
     arg.data.root.setInheritedAttributes({}, arg.math['display'], 0, false);
   };
+
+
+  /**
+   * Removes unneeded mstyle elements that just set the scriptlevel
+   */
+  export const checkScriptlevel = function (arg: { data: ParseOptions }) {
+    const options = arg.data;
+    const remove: MmlNode[] = [];
+    for (const mml of options.getList('mstyle')) {
+      if (mml.childNodes?.[0]?.childNodes?.length !== 1) {
+        continue;
+      }
+      const attributes = mml.attributes;
+      for (const key of ['displaystyle', 'scriptlevel']) {
+        if (attributes.getExplicit(key) === attributes.getInherited(key)) {
+          attributes.unset(key);
+        }
+      }
+      const names = attributes.getExplicitNames();
+      if (names.filter(key => key.substring(0, 10) !== 'data-latex').length === 0) {
+        const child = mml.childNodes[0].childNodes[0];
+        names.forEach(key => child.attributes.set(key, attributes.get(key)));
+        mml.parent.replaceChild(child, mml);
+        remove.push(mml);
+      }
+    }
+    options.removeFromList('mstyle', remove);
+  }
 }
 
 export default FilterUtil;
diff --git a/ts/input/tex/ParseUtil.ts b/ts/input/tex/ParseUtil.ts
index 5443c1cc7..a901ad094 100644
--- a/ts/input/tex/ParseUtil.ts
+++ b/ts/input/tex/ParseUtil.ts
@@ -637,7 +637,9 @@ export const ParseUtil = {
     let node: MmlNode = mml;
     if (stack) {
       // @test Overbrace 1 2 3, Underbrace, Overbrace Op 1 2
-      node = parser.create('node', 'TeXAtom', [mml], {
+      node = parser.create('node', 'TeXAtom', [
+        parser.create('node', 'mstyle', [mml], { displaystyle: true, scriptlevel: 0 })
+      ], {
         texClass: TEXCLASS.OP,
         movesupsub: true,
       });
diff --git a/ts/input/tex/ams/AmsMappings.ts b/ts/input/tex/ams/AmsMappings.ts
index 14555e6bd..dcbe4d07a 100644
--- a/ts/input/tex/ams/AmsMappings.ts
+++ b/ts/input/tex/ams/AmsMappings.ts
@@ -205,7 +205,7 @@ new sm.EnvironmentMap('AMSmath-environment', ParseMethods.environment, {
     ParseUtil.cols(0),
     '0.1em',
     'S',
-    1,
+    true,
   ],
   smallmatrix: [
     AmsMethods.Array,
@@ -216,7 +216,7 @@ new sm.EnvironmentMap('AMSmath-environment', ParseMethods.environment, {
     ParseUtil.cols(1 / 3),
     '.2em',
     'S',
-    1,
+    true,
   ],
   matrix: [AmsMethods.Array, null, null, null, 'c'],
   pmatrix: [AmsMethods.Array, null, '(', ')', 'c'],
diff --git a/ts/input/tex/base/BaseItems.ts b/ts/input/tex/base/BaseItems.ts
index 5b5ccd0bd..2d16efdb2 100644
--- a/ts/input/tex/base/BaseItems.ts
+++ b/ts/input/tex/base/BaseItems.ts
@@ -1092,7 +1092,7 @@ export class ArrayItem extends BaseItem {
     delete this.arraydef['scriptlevel'];
     let mml = this.create('node', 'mtable', this.table, this.arraydef);
     if (scriptlevel) {
-      mml.setProperty('scriptlevel', scriptlevel);
+      mml.setProperty('smallmatrix', true);
     }
     if (this.breakAlign.table) {
       NodeUtil.setAttribute(mml, 'data-break-align', this.breakAlign.table);
@@ -1106,6 +1106,9 @@ export class ArrayItem extends BaseItem {
       );
     }
     mml = this.handleFrame(mml);
+    if (scriptlevel !== undefined) {
+      mml = this.create('node', 'mstyle', [mml], { scriptlevel });
+    }
     if (this.getProperty('open') || this.getProperty('close')) {
       // @test Cross Product Formula
       mml = ParseUtil.fenced(
diff --git a/ts/input/tex/base/BaseMethods.ts b/ts/input/tex/base/BaseMethods.ts
index 9e31d28ee..198c0ff4d 100644
--- a/ts/input/tex/base/BaseMethods.ts
+++ b/ts/input/tex/base/BaseMethods.ts
@@ -1961,6 +1961,8 @@ const BaseMethods: { [key: string]: ParseMethod } = {
     if (style === 'S') {
       // @test Subarray, Small Matrix
       array.arraydef['scriptlevel'] = 1;
+    } else {
+      array.arraydef['scriptlevel'] = 0;
     }
     if (raggedHeight) {
       // @test Subarray, Small Matrix

From bf5fc52544e5db00248ee2aa675dfe234ecab52c Mon Sep 17 00:00:00 2001
From: "Davide P. Cervone" <dpvc@union.edu>
Date: Thu, 24 Oct 2024 17:54:54 -0400
Subject: [PATCH 2/2] Make prettier happy

---
 ts/input/tex/FilterUtil.ts | 10 ++++++----
 ts/input/tex/ParseUtil.ts  | 20 ++++++++++++++------
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/ts/input/tex/FilterUtil.ts b/ts/input/tex/FilterUtil.ts
index f748e3f49..e4777ee9e 100644
--- a/ts/input/tex/FilterUtil.ts
+++ b/ts/input/tex/FilterUtil.ts
@@ -334,7 +334,6 @@ namespace FilterUtil {
     arg.data.root.setInheritedAttributes({}, arg.math['display'], 0, false);
   };
 
-
   /**
    * Removes unneeded mstyle elements that just set the scriptlevel
    */
@@ -352,15 +351,18 @@ namespace FilterUtil {
         }
       }
       const names = attributes.getExplicitNames();
-      if (names.filter(key => key.substring(0, 10) !== 'data-latex').length === 0) {
+      if (
+        names.filter((key) => key.substring(0, 10) !== 'data-latex').length ===
+        0
+      ) {
         const child = mml.childNodes[0].childNodes[0];
-        names.forEach(key => child.attributes.set(key, attributes.get(key)));
+        names.forEach((key) => child.attributes.set(key, attributes.get(key)));
         mml.parent.replaceChild(child, mml);
         remove.push(mml);
       }
     }
     options.removeFromList('mstyle', remove);
-  }
+  };
 }
 
 export default FilterUtil;
diff --git a/ts/input/tex/ParseUtil.ts b/ts/input/tex/ParseUtil.ts
index a901ad094..1c689582b 100644
--- a/ts/input/tex/ParseUtil.ts
+++ b/ts/input/tex/ParseUtil.ts
@@ -637,12 +637,20 @@ export const ParseUtil = {
     let node: MmlNode = mml;
     if (stack) {
       // @test Overbrace 1 2 3, Underbrace, Overbrace Op 1 2
-      node = parser.create('node', 'TeXAtom', [
-        parser.create('node', 'mstyle', [mml], { displaystyle: true, scriptlevel: 0 })
-      ], {
-        texClass: TEXCLASS.OP,
-        movesupsub: true,
-      });
+      node = parser.create(
+        'node',
+        'TeXAtom',
+        [
+          parser.create('node', 'mstyle', [mml], {
+            displaystyle: true,
+            scriptlevel: 0,
+          }),
+        ],
+        {
+          texClass: TEXCLASS.OP,
+          movesupsub: true,
+        }
+      );
     }
     NodeUtil.setProperty(node, 'subsupOK', true);
     return node;