From 969ada97cb14ae6a59b97bfc4d83ead3e293e916 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Tue, 9 Jun 2026 07:46:40 -0400 Subject: [PATCH 01/26] Fix problem with \limits and \nolimits when used after a script. (mathjax/MathJax#3569) --- ts/input/tex/base/BaseMethods.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/input/tex/base/BaseMethods.ts b/ts/input/tex/base/BaseMethods.ts index dc371a34d..f993da940 100644 --- a/ts/input/tex/base/BaseMethods.ts +++ b/ts/input/tex/base/BaseMethods.ts @@ -645,14 +645,14 @@ const BaseMethods: { [key: string]: ParseMethod } = { // @test Limits UnderOver node = parser.create('node', 'msubsup'); NodeUtil.copyChildren(op, node); - op = top.Last = node; + op = top.First = node; } else if (NodeUtil.isType(op, 'msubsup') && limits) { // @test Limits SubSup // node = parser.create('node', 'munderover', NodeUtil.getChildren(op), {}); // Needs to be copied, otherwise we get an error in MmlNode.appendChild! node = parser.create('node', 'munderover'); NodeUtil.copyChildren(op, node); - op = top.Last = node; + op = top.First = node; } NodeUtil.setProperty(op, 'movesupsub', limits ? true : false); NodeUtil.setProperties(NodeUtil.getCoreMO(op), { movablelimits: false }); From e72921f6b9174dc90d272dcd4d06fbebb5ea3bf2 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 16 May 2026 07:09:50 -0400 Subject: [PATCH 02/26] Add symmetric="true" to \middle results. (mathjax/MathJax#3560) --- ts/input/tex/base/BaseItems.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/input/tex/base/BaseItems.ts b/ts/input/tex/base/BaseItems.ts index 4704a6b57..a2eb4d66b 100644 --- a/ts/input/tex/base/BaseItems.ts +++ b/ts/input/tex/base/BaseItems.ts @@ -432,7 +432,7 @@ export class LeftItem extends BaseItem { // // Add the middle delimiter, with empty open and close elements around it for spacing // - const def = { stretchy: true } as any; + const def = { stretchy: true, symmetric: true } as any; if (item.getProperty('color')) { def.mathcolor = item.getProperty('color'); } From e33f654b2f7bae56e8af44a406ec5c807d327980 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 16 May 2026 07:17:02 -0400 Subject: [PATCH 03/26] Load font files synchronously, when possible. (#1458) --- ts/output/common/FontData.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ts/output/common/FontData.ts b/ts/output/common/FontData.ts index a74e341c3..26aaf4be9 100644 --- a/ts/output/common/FontData.ts +++ b/ts/output/common/FontData.ts @@ -1330,8 +1330,13 @@ export class FontData< const delim = this.delimiters[n]; if (delim && !('dir' in delim)) { this.delimiters[n] = null; - retryAfter(this.loadDynamicFile(delim)); - return null; + if (mathjax.asyncIsSynchronous) { + this.loadDynamicFileSync(delim); + return this.getDelimiter(n); + } else { + retryAfter(this.loadDynamicFile(delim)); + return null; + } } return delim as DelimiterData; } @@ -1378,8 +1383,13 @@ export class FontData< const variant = this.variant[name]; delete variant.chars[n]; variant.linked.forEach((link) => delete link[n]); - retryAfter(this.loadDynamicFile(char)); - return null; + if (mathjax.asyncIsSynchronous) { + this.loadDynamicFileSync(char); + return this.getChar(name, n); + } else { + retryAfter(this.loadDynamicFile(char)); + return null; + } } return char as CharDataArray; } From 139fe609e8360425b722b44167a8a0189ad79d53 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Tue, 9 Jun 2026 07:47:27 -0400 Subject: [PATCH 04/26] Don't rerender the output during menu initialization. --- ts/ui/menu/Menu.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ts/ui/menu/Menu.ts b/ts/ui/menu/Menu.ts index ebee11f7b..78b100f31 100644 --- a/ts/ui/menu/Menu.ts +++ b/ts/ui/menu/Menu.ts @@ -250,6 +250,8 @@ export class Menu { */ protected document: MenuMathDocument; + protected initialized: boolean = false; + /** * Instances of the various output jax that we can switch to */ @@ -566,6 +568,7 @@ export class Menu { this.mergeUserSettings(); this.initMenu(); this.applySettings(); + this.initialized = true; } /** @@ -1108,7 +1111,7 @@ export class Menu { */ protected setOverflow(overflow: string) { this.document.outputJax.options.displayOverflow = overflow.toLowerCase(); - if (!Menu.loading) { + if (!Menu.loading && this.initialized) { this.document.rerenderPromise(); } } @@ -1118,7 +1121,7 @@ export class Menu { */ protected setInlineBreaks(breaks: boolean) { this.document.outputJax.options.linebreaks.inline = breaks; - if (!Menu.loading) { + if (!Menu.loading && this.initialized) { this.document.rerenderPromise(); } } @@ -1128,7 +1131,7 @@ export class Menu { */ protected setScale(scale: string) { this.document.outputJax.options.scale = parseFloat(scale); - if (!Menu.loading) { + if (!Menu.loading && this.initialized) { this.document.rerenderPromise(); } } From 7e7fa55694e00daefbde857db8ea78e8746bc6fe Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 11 Jun 2026 17:09:02 -0400 Subject: [PATCH 05/26] Make sure the parsers array is cleared for tex and text parsers. (#1474) --- ts/input/tex.ts | 1 + ts/input/tex/Configuration.ts | 2 +- ts/input/tex/TexParser.ts | 2 +- ts/input/tex/textmacros/TextMacrosConfiguration.ts | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ts/input/tex.ts b/ts/input/tex.ts index 91730585c..205ecd4ff 100644 --- a/ts/input/tex.ts +++ b/ts/input/tex.ts @@ -187,6 +187,7 @@ export class TeX extends AbstractInputJax { * @override */ public reset(tag: number = 0) { + this.parseOptions.clear(); this.parseOptions.tags.reset(tag); } diff --git a/ts/input/tex/Configuration.ts b/ts/input/tex/Configuration.ts index 6306dafe2..038680623 100644 --- a/ts/input/tex/Configuration.ts +++ b/ts/input/tex/Configuration.ts @@ -159,7 +159,7 @@ export class Configuration { } /** - * Creates an unnamed, ephemeral package configuration. It will not added to + * Creates an unnamed, ephemeral package configuration. It is not added to * the configuration handler. * * @param {object} config See `create` method. diff --git a/ts/input/tex/TexParser.ts b/ts/input/tex/TexParser.ts index 8e4b1603b..119d8cced 100644 --- a/ts/input/tex/TexParser.ts +++ b/ts/input/tex/TexParser.ts @@ -248,11 +248,11 @@ export default class TexParser { * @returns {MmlNode} The internal Mathml structure. */ public mml(): MmlNode { + this.configuration.popParser(); if (!this.stack.Top().isKind('mml')) { return null; } const node = this.stack.Top().First; - this.configuration.popParser(); const latex = this.trimTex(this.string); if (latex) { node.attributes.set(TexConstant.Attr.LATEX, latex); diff --git a/ts/input/tex/textmacros/TextMacrosConfiguration.ts b/ts/input/tex/textmacros/TextMacrosConfiguration.ts index 981362af7..462c41609 100644 --- a/ts/input/tex/textmacros/TextMacrosConfiguration.ts +++ b/ts/input/tex/textmacros/TextMacrosConfiguration.ts @@ -160,6 +160,7 @@ export const TextMacrosConfiguration = Configuration.create('textmacros', { // const config = data.data.packageData.get('textmacros'); config.parseOptions.nodeFactory.setMmlFactory(config.jax.mmlFactory); + config.parseOptions.clear(); }, ], [ConfigurationType.OPTIONS]: { From e69ef94ac9106ae1df5903dc6e4279883a147c17 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 11 Jun 2026 17:23:41 -0400 Subject: [PATCH 06/26] Fix `\bbox` problem with padding values that are decimals. (mathjax/MathJax#3568) --- ts/input/tex/bbox/BboxConfiguration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/input/tex/bbox/BboxConfiguration.ts b/ts/input/tex/bbox/BboxConfiguration.ts index 37838302e..02c7785b6 100644 --- a/ts/input/tex/bbox/BboxConfiguration.ts +++ b/ts/input/tex/bbox/BboxConfiguration.ts @@ -64,7 +64,7 @@ const BboxMethods: { [key: string]: ParseMethod } = { height: '+' + pad, depth: '+' + pad, lspace: pad, - width: '+' + 2 * parseInt(match[1], 10) + match[3], + width: '+' + 2 * parseFloat(match[1]) + match[3], }; } } else if (part.match(/^([a-z0-9]+|#[0-9a-f]{6}|#[0-9a-f]{3})$/i)) { From 68caffca88e7d7fc9b855f04b68315f3a412cca6 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 13 Jun 2026 16:23:33 -0400 Subject: [PATCH 07/26] Make sure multi-byte UTF8 characters are handled properly in data-latex attributes. (mathjax/MathJax#3575) --- ts/input/tex/TexParser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/input/tex/TexParser.ts b/ts/input/tex/TexParser.ts index 8e4b1603b..67136cba5 100644 --- a/ts/input/tex/TexParser.ts +++ b/ts/input/tex/TexParser.ts @@ -151,7 +151,7 @@ export default class TexParser { // // Back up one to pick up the parsed character (this.i is past it at this point). // - this.saveI = this.i - (kind === 'character' && input[1] !== '&' ? 1 : 0); + this.saveI = this.i - (kind === 'character' && input[1] !== '&' ? input[1].length : 0); const result = this.configuration.handlers.get(kind).parse(input); // // The macro gets processed by the \\ character later From a88c6e769946d4975d30aaa96a2edcea7a17140f Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sat, 13 Jun 2026 19:48:35 -0400 Subject: [PATCH 08/26] Set box-sizing in dialogs to avoid CSS bleed through that affects close and help buttons. --- ts/ui/dialog/DraggableDialog.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ts/ui/dialog/DraggableDialog.ts b/ts/ui/dialog/DraggableDialog.ts index 901b14b72..75310766f 100644 --- a/ts/ui/dialog/DraggableDialog.ts +++ b/ts/ui/dialog/DraggableDialog.ts @@ -210,6 +210,9 @@ export class DraggableDialog { position: 'fixed', top: '-4%', }, + '.mjx-dialog *': { + 'box-sizing': 'content-box', + }, '.mjx-dialog.mjx-moving': { cursor: 'grabbing', }, From ecfb01b8d48275081b158f884c109cbf03cb9fc6 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 14 Jun 2026 10:34:33 -0400 Subject: [PATCH 09/26] Fix label ids for expressions with forward refs. (mathjax/MathJax#3562) --- ts/input/tex/base/BaseMethods.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ts/input/tex/base/BaseMethods.ts b/ts/input/tex/base/BaseMethods.ts index f993da940..4fcf2badb 100644 --- a/ts/input/tex/base/BaseMethods.ts +++ b/ts/input/tex/base/BaseMethods.ts @@ -2177,13 +2177,13 @@ const BaseMethods: { [key: string]: ParseMethod } = { // @test Label Empty return; } + // @test Label, Ref, Ref Unknown + if (parser.tags.label) { + // @test Double Label Error + throw new TexError('MultipleCommand', 'Multiple %1', parser.currentCS); + } + parser.tags.label = label; if (!parser.tags.refUpdate) { - // @test Label, Ref, Ref Unknown - if (parser.tags.label) { - // @test Double Label Error - throw new TexError('MultipleCommand', 'Multiple %1', parser.currentCS); - } - parser.tags.label = label; if ( (parser.tags.allLabels[label] || parser.tags.labels[label]) && !parser.options['ignoreDuplicateLabels'] From f8a3f94bfbb5723a8311bd93b46a327e682b39c1 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 14 Jun 2026 11:03:55 -0400 Subject: [PATCH 10/26] Update tests --- .../input/tex/__snapshots__/Base.test.ts.snap | 12 +-- .../tex/__snapshots__/Physics.test.ts.snap | 88 +++++++++---------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap index bc59e9aa3..314cd73b8 100644 --- a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap @@ -3552,7 +3552,7 @@ exports[`Fenced Fenced Arrows 3 1`] = ` b - + c @@ -3660,7 +3660,7 @@ exports[`Fenced Middle 1`] = ` ( a - | + | b ) @@ -7931,7 +7931,7 @@ exports[`Spacing Nonscript scriptlevel 1`] = ` a - | + | b @@ -7948,7 +7948,7 @@ exports[`Spacing Nonscript toplevel 1`] = ` a - | + | b @@ -9156,7 +9156,7 @@ exports[`User Defined Macros Middle Color 1`] = ` A - | + | B ) @@ -9170,7 +9170,7 @@ exports[`User Defined Macros Right Color 1`] = ` ( A - | + | B diff --git a/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap index 218039580..fb892c287 100644 --- a/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Physics.test.ts.snap @@ -150,7 +150,7 @@ exports[`Bra-Ket Macros Rest innerproduct arg one 1`] = ` A - | + | A @@ -168,7 +168,7 @@ exports[`Bra-Ket Macros Rest innerproduct arg three 1`] = ` A - | + | B @@ -189,7 +189,7 @@ exports[`Bra-Ket Macros Rest innerproduct arg two 1`] = ` A - | + | B @@ -207,7 +207,7 @@ exports[`Bra-Ket Macros Rest ip arg one 1`] = ` A - | + | A @@ -225,7 +225,7 @@ exports[`Bra-Ket Macros Rest ip arg three 1`] = ` A - | + | B @@ -246,7 +246,7 @@ exports[`Bra-Ket Macros Rest ip arg two 1`] = ` A - | + | B @@ -4956,7 +4956,7 @@ exports[`Physics5_0 Derivatives_Deriv_9 1`] = ` f - / + / d @@ -4993,7 +4993,7 @@ exports[`Physics5_0 Derivatives_Deriv_10 1`] = ` f - / + / d @@ -5129,7 +5129,7 @@ exports[`Physics5_1 Derivatives_Partial_0 1`] = ` x - / + / y @@ -5146,7 +5146,7 @@ exports[`Physics5_1 Derivatives_Partial_1 1`] = ` 2 - / + / y @@ -5294,7 +5294,7 @@ exports[`Physics5_1 Derivatives_Partial_10 1`] = ` f - / + / x @@ -5315,7 +5315,7 @@ exports[`Physics5_1 Derivatives_Partial_11 1`] = ` f - / + / @@ -5393,7 +5393,7 @@ exports[`Physics5_1 Derivatives_Partial_14 1`] = ` f - / + / x @@ -5416,7 +5416,7 @@ exports[`Physics5_1 Derivatives_Partial_15 1`] = ` f - / + / x @@ -5634,7 +5634,7 @@ exports[`Physics5_2 Derivatives_Functional_8 1`] = ` δ F - / + / δ x @@ -5650,7 +5650,7 @@ exports[`Physics5_2 Derivatives_Functional_9 1`] = ` δ F - / + / δ x @@ -5666,7 +5666,7 @@ exports[`Physics5_2 Derivatives_Functional_10 1`] = ` δ F - / + / δ x @@ -5791,7 +5791,7 @@ exports[`Physics5_2 Derivatives_Functional_15 1`] = ` f - / + / δ @@ -5824,7 +5824,7 @@ exports[`Physics5_2 Derivatives_Functional_16 1`] = ` f - / + / δ @@ -6482,7 +6482,7 @@ exports[`Physics6_0 BraKet_Bra_0 1`] = ` ϕ - | + | ψ @@ -6500,7 +6500,7 @@ exports[`Physics6_0 BraKet_Bra_1 1`] = ` A - | + | B @@ -6548,7 +6548,7 @@ exports[`Physics6_0 BraKet_Bra_3 1`] = ` A - | + | @@ -6605,7 +6605,7 @@ exports[`Physics6_0 BraKet_Bra_6 1`] = ` A - | + | B @@ -6623,7 +6623,7 @@ exports[`Physics6_0 BraKet_Bra_7 1`] = ` A - | + | @@ -6639,7 +6639,7 @@ exports[`Physics6_0 BraKet_Bra_8 1`] = ` A - | + | @@ -6655,7 +6655,7 @@ exports[`Physics6_0 BraKet_Bra_9 1`] = ` A - | + | @@ -6675,7 +6675,7 @@ exports[`Physics6_0 BraKet_Bra_10 1`] = ` - | + | @@ -6777,7 +6777,7 @@ exports[`Physics6_1 BraKet_Braket_0 1`] = ` A - | + | A @@ -6798,7 +6798,7 @@ exports[`Physics6_1 BraKet_Braket_1 1`] = ` - | + | @@ -6853,7 +6853,7 @@ exports[`Physics6_1 BraKet_Braket_4 1`] = ` a - | + | a @@ -6885,7 +6885,7 @@ exports[`Physics6_1 BraKet_Braket_6 1`] = ` α - | + | α @@ -6906,7 +6906,7 @@ exports[`Physics6_1 BraKet_Braket_7 1`] = ` - | + | A @@ -6944,7 +6944,7 @@ exports[`Physics6_1 BraKet_Braket_9 1`] = ` - | + | @@ -6990,7 +6990,7 @@ exports[`Physics6_1 BraKet_Braket_11 1`] = ` - | + | @@ -7521,13 +7521,13 @@ exports[`Physics6_3 BraKet_Expect_7 1`] = ` - | + | A - | + | @@ -7632,13 +7632,13 @@ exports[`Physics6_3 BraKet_Expect_12 1`] = ` - | + | A - | + | @@ -7749,7 +7749,7 @@ exports[`Physics6_3 BraKet_Expect_16 1`] = ` - | + | @@ -7758,7 +7758,7 @@ exports[`Physics6_3 BraKet_Expect_16 1`] = ` - | + | @@ -7924,7 +7924,7 @@ exports[`Physics6_4 BraKet_MatrixEl_6 1`] = ` n - | + | @@ -7933,7 +7933,7 @@ exports[`Physics6_4 BraKet_MatrixEl_6 1`] = ` - | + | m @@ -7954,7 +7954,7 @@ exports[`Physics6_4 BraKet_MatrixEl_7 1`] = ` - | + | @@ -7963,7 +7963,7 @@ exports[`Physics6_4 BraKet_MatrixEl_7 1`] = ` - | + | From 5dc3abedcb2af85372653342c4995307453dd508 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Sun, 14 Jun 2026 19:28:44 -0400 Subject: [PATCH 11/26] Ignore braces in array preamble. (mathjax/MathJax#3565) --- testsuite/tests/input/tex/Base.test.ts | 4 ++++ .../tests/input/tex/__snapshots__/Base.test.ts.snap | 12 ++++++++++++ ts/input/tex/ColumnParser.ts | 2 ++ 3 files changed, 18 insertions(+) diff --git a/testsuite/tests/input/tex/Base.test.ts b/testsuite/tests/input/tex/Base.test.ts index 6e06df5d7..0052be20f 100644 --- a/testsuite/tests/input/tex/Base.test.ts +++ b/testsuite/tests/input/tex/Base.test.ts @@ -4002,6 +4002,10 @@ describe('Complete Array', () => { expect(tex2mml('\\begin{array}{> {x} c} X \\end{array}')).toMatchSnapshot(); }); + it('column { }', () => { + expect(tex2mml('\\begin{array}{{c}} X \\end{array}')).toMatchSnapshot(); + }); + it('BadPreamToken', () => { expectTexError('\\begin{array}a').toBe('Illegal pream-token (a)'); }); diff --git a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap index bc59e9aa3..db75f586c 100644 --- a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap @@ -1872,6 +1872,18 @@ exports[`Complete Array column @ p m 1`] = ` " `; +exports[`Complete Array column { } 1`] = ` +" + + + + X + + + +" +`; + exports[`Complete Array column b 1`] = ` " diff --git a/ts/input/tex/ColumnParser.ts b/ts/input/tex/ColumnParser.ts index a0beec563..e4c8a7133 100644 --- a/ts/input/tex/ColumnParser.ts +++ b/ts/input/tex/ColumnParser.ts @@ -94,6 +94,8 @@ export class ColumnParser { // Ignored // ' ': (_state) => {}, + '{': (_state) => {}, + '}': (_state) => {}, }; /** From 6ee75da164170e77bbff2b2ea8b63bfc129eba3b Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 18 Jun 2026 12:14:08 -0400 Subject: [PATCH 12/26] Work around issue with Safari 26 not processing math inside otherwise empty containers with overflow: auto. (mathjax/MathJax#3579) --- ts/ui/lazy/LazyHandler.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ts/ui/lazy/LazyHandler.ts b/ts/ui/lazy/LazyHandler.ts index 6bcf48afb..73c53ea93 100644 --- a/ts/ui/lazy/LazyHandler.ts +++ b/ts/ui/lazy/LazyHandler.ts @@ -32,6 +32,7 @@ import { HTMLHandler } from '../../handlers/html/HTMLHandler.js'; import { SpeechMathItem } from '../../a11y/speech.js'; import { handleRetriesFor } from '../../util/Retries.js'; import { OptionList } from '../../util/Options.js'; +import { StyleJson } from '../../util/StyleJson.js'; /** * Add the needed function to the window object. @@ -388,6 +389,19 @@ export function LazyMathDocumentMixin< */ protected lazySet: LazySet = new Set(); + /** + * Extra styles for lazy nodes. + */ + public static lazyStyles: StyleJson = { + 'mjx-lazy': { + // + // Needed for Safari 26 when the math appears inside an othewise empty + // node with overflow: auto. See issue #3579. + // + display: 'inline-block', + }, + }; + /** * Augment the MathItem class used for this MathDocument, * then create the intersection observer and lazy list, @@ -400,6 +414,7 @@ export function LazyMathDocumentMixin< */ constructor(...args: any[]) { super(...args); + this.addStyles((this.constructor as typeof BaseClass).lazyStyles); // // Use the LazyMathItem for math items // From 3142fe43a7d76a0aa0eca3b05879315ef2fb193a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 18 Jun 2026 19:21:19 -0400 Subject: [PATCH 13/26] Update handling of braces to be more like LaTeX --- testsuite/tests/input/tex/Base.test.ts | 18 ++++++++- .../input/tex/__snapshots__/Base.test.ts.snap | 34 +++++++++++++++-- ts/input/tex/ColumnParser.ts | 38 ++++++++++++++++--- 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/testsuite/tests/input/tex/Base.test.ts b/testsuite/tests/input/tex/Base.test.ts index 0052be20f..f51892f58 100644 --- a/testsuite/tests/input/tex/Base.test.ts +++ b/testsuite/tests/input/tex/Base.test.ts @@ -4002,8 +4002,22 @@ describe('Complete Array', () => { expect(tex2mml('\\begin{array}{> {x} c} X \\end{array}')).toMatchSnapshot(); }); - it('column { }', () => { - expect(tex2mml('\\begin{array}{{c}} X \\end{array}')).toMatchSnapshot(); + it('column {cc}', () => { + expect(tex2mml('\\begin{array}{{cc}} X Y \\end{array}')).toMatchSnapshot(); + }); + + it('column {c}', () => { + expect(tex2mml('\\begin{array}{c{c}} X Y \\end{array}')).toMatchSnapshot(); + }); + + it('column {{c}}', () => { + expect(tex2mml('\\begin{array}{{{c}}} X \\end{array}')).toMatchSnapshot(); + }); + + it('column brace errors', () => { + expectTexError(tex2mml('\\begin{array}{c{xx}} X Y \\end{array}')).toBe('Illegal pream-token (xx)'); + expectTexError(tex2mml('\\begin{array}{c{{c}}} X Y \\end{array}')).toBe('Illegal pream-token ({c})'); + expectTexError(tex2mml('\\begin{array}{c{c{c}}} X Y \\end{array}')).toBe('Illegal pream-token (c{c})'); }); it('BadPreamToken', () => { diff --git a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap index db75f586c..75eb4d1d9 100644 --- a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap @@ -1872,10 +1872,10 @@ exports[`Complete Array column @ p m 1`] = ` " `; -exports[`Complete Array column { } 1`] = ` -" - - +exports[`Complete Array column {{c}} 1`] = ` +" + + X @@ -1884,6 +1884,32 @@ exports[`Complete Array column { } 1`] = ` " `; +exports[`Complete Array column {c} 1`] = ` +" + + + + X + Y + + + +" +`; + +exports[`Complete Array column {cc} 1`] = ` +" + + + + X + Y + + + +" +`; + exports[`Complete Array column b 1`] = ` " diff --git a/ts/input/tex/ColumnParser.ts b/ts/input/tex/ColumnParser.ts index e4c8a7133..f8d7ef260 100644 --- a/ts/input/tex/ColumnParser.ts +++ b/ts/input/tex/ColumnParser.ts @@ -84,6 +84,7 @@ export class ColumnParser { '@': (state) => this.addAt(state, this.getBraces(state)), '!': (state) => this.addBang(state, this.getBraces(state)), '*': (state) => this.repeat(state), + '{': (state) => this.brace(state), // // Non-standard for math-mode versions // @@ -94,8 +95,7 @@ export class ColumnParser { // Ignored // ' ': (_state) => {}, - '{': (_state) => {}, - '}': (_state) => {}, + '\n': (_state_) => {}, }; /** @@ -111,6 +111,12 @@ export class ColumnParser { * @param {ArrayItem} array The ArrayItem for the template */ public process(parser: TexParser, template: string, array: ArrayItem) { + // + // Remove one pair of braces, if there are any + // + if (template.charAt(0) === '{' && template.slice(-1) === '}') { + template = template.slice(1, -1); + } // // Initialize the state // @@ -143,10 +149,7 @@ export class ColumnParser { const code = state.template.codePointAt(state.i); const c = (state.c = String.fromCodePoint(code)); state.i += c.length; - if (!Object.hasOwn(this.columnHandler, c)) { - throw new TexError('BadPreamToken', 'Illegal pream-token (%1)', c); - } - this.columnHandler[c](state); + this.processColumn(state, c); } // // Set array definition values @@ -158,6 +161,19 @@ export class ColumnParser { this.setPadding(state, array); } + /** + * Process a column specifier, or throw an error if not defined. + * + * @param {ColumnState} state The current state of the parser + * @param {string} c The column type to process + */ + protected processColumn(state: ColumnState, c: string) { + if (!Object.hasOwn(this.columnHandler, c)) { + throw new TexError('BadPreamToken', 'Illegal pream-token (%1)', c); + } + this.columnHandler[c](state); + } + /** * @param {ColumnState} state The current state of the parser * @param {ArrayItem} array The array stack item to adjust @@ -422,4 +438,14 @@ export class ColumnParser { new Array(n).fill(cols).join('') + state.template.substring(state.i); state.i = 0; } + + /** + * Process a braced column type + * + * @param {ColumnState} state The current state of the parser + */ + public brace(state: ColumnState) { + state.i--; + this.processColumn(state, this.getBraces(state)); + } } From bd9140e50e125a79a6823887ee6bb859c651f7df Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 18 Jun 2026 19:32:25 -0400 Subject: [PATCH 14/26] Remove else clauses after return, as requested in review --- ts/output/common/FontData.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ts/output/common/FontData.ts b/ts/output/common/FontData.ts index 26aaf4be9..4509595c5 100644 --- a/ts/output/common/FontData.ts +++ b/ts/output/common/FontData.ts @@ -1333,10 +1333,9 @@ export class FontData< if (mathjax.asyncIsSynchronous) { this.loadDynamicFileSync(delim); return this.getDelimiter(n); - } else { - retryAfter(this.loadDynamicFile(delim)); - return null; } + retryAfter(this.loadDynamicFile(delim)); + return null; } return delim as DelimiterData; } @@ -1386,10 +1385,9 @@ export class FontData< if (mathjax.asyncIsSynchronous) { this.loadDynamicFileSync(char); return this.getChar(name, n); - } else { - retryAfter(this.loadDynamicFile(char)); - return null; } + retryAfter(this.loadDynamicFile(char)); + return null; } return char as CharDataArray; } From 40eb098171bd6ea247cb85cf7d2292777c58e08a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 18 Jun 2026 21:22:40 -0400 Subject: [PATCH 15/26] Get order of repeated >{} or <{} directives correct and add tests --- testsuite/tests/input/tex/Base.test.ts | 8 +++++ .../input/tex/__snapshots__/Base.test.ts.snap | 34 +++++++++++++++++++ ts/input/tex/ColumnParser.ts | 4 +-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/input/tex/Base.test.ts b/testsuite/tests/input/tex/Base.test.ts index f51892f58..f31218918 100644 --- a/testsuite/tests/input/tex/Base.test.ts +++ b/testsuite/tests/input/tex/Base.test.ts @@ -4014,6 +4014,14 @@ describe('Complete Array', () => { expect(tex2mml('\\begin{array}{{{c}}} X \\end{array}')).toMatchSnapshot(); }); + it('column newline', () => { + expect(tex2mml('\\begin{array}{c\nc} X & Y\\end{array}')).toMatchSnapshot(); + }); + + it('column > > c < <', () => { + expect(tex2mml('\\begin{array}{>{a}>{b}c<{x}<{y}} X \\end{array}')).toMatchSnapshot(); + }); + it('column brace errors', () => { expectTexError(tex2mml('\\begin{array}{c{xx}} X Y \\end{array}')).toBe('Illegal pream-token (xx)'); expectTexError(tex2mml('\\begin{array}{c{{c}}} X Y \\end{array}')).toBe('Illegal pream-token ({c})'); diff --git a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap index 75eb4d1d9..745260a02 100644 --- a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap @@ -1820,6 +1820,22 @@ exports[`Complete Array column ! | @ 1`] = ` " `; +exports[`Complete Array column > > c < < 1`] = ` +" + + + + b + a + X + y + x + + + +" +`; + exports[`Complete Array column > space 1`] = ` " @@ -2217,6 +2233,24 @@ exports[`Complete Array column m 1`] = ` " `; +exports[`Complete Array column newline 1`] = ` +" + + + + X + + + Y + + + +" +`; + exports[`Complete Array column p 1`] = ` " diff --git a/ts/input/tex/ColumnParser.ts b/ts/input/tex/ColumnParser.ts index f8d7ef260..cc41977e4 100644 --- a/ts/input/tex/ColumnParser.ts +++ b/ts/input/tex/ColumnParser.ts @@ -77,10 +77,10 @@ export class ColumnParser { ':': (state) => this.addRule(state, 'dashed'), '>': (state) => (state.cstart[state.j] = - (state.cstart[state.j] || '') + this.getBraces(state)), + this.getBraces(state) + (state.cstart[state.j] || '')), '<': (state) => (state.cend[state.j - 1] = - (state.cend[state.j - 1] || '') + this.getBraces(state)), + this.getBraces(state) + (state.cend[state.j - 1] || '')), '@': (state) => this.addAt(state, this.getBraces(state)), '!': (state) => this.addBang(state, this.getBraces(state)), '*': (state) => this.repeat(state), From ad4abddf9a0ac811a71f0bb161f90a45d67b8a0a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 19 Jun 2026 07:33:38 -0400 Subject: [PATCH 16/26] Improve removal of outer braces and add a new test --- testsuite/tests/input/tex/Base.test.ts | 4 ++++ .../input/tex/__snapshots__/Base.test.ts.snap | 18 ++++++++++++++++++ ts/input/tex/ColumnParser.ts | 16 ++++++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/input/tex/Base.test.ts b/testsuite/tests/input/tex/Base.test.ts index f31218918..f31feae31 100644 --- a/testsuite/tests/input/tex/Base.test.ts +++ b/testsuite/tests/input/tex/Base.test.ts @@ -4014,6 +4014,10 @@ describe('Complete Array', () => { expect(tex2mml('\\begin{array}{{{c}}} X \\end{array}')).toMatchSnapshot(); }); + it('column {r}c{l}', () => { + expect(tex2mml('\\begin{array}{{r}c{l}} X & Y & Z \\end{array}')).toMatchSnapshot(); + }); + it('column newline', () => { expect(tex2mml('\\begin{array}{c\nc} X & Y\\end{array}')).toMatchSnapshot(); }); diff --git a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap index 745260a02..c579c43ed 100644 --- a/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap +++ b/testsuite/tests/input/tex/__snapshots__/Base.test.ts.snap @@ -1926,6 +1926,24 @@ exports[`Complete Array column {cc} 1`] = ` " `; +exports[`Complete Array column {r}c{l} 1`] = ` +" + + + + X + + + Y + + + Z + + + +" +`; + exports[`Complete Array column b 1`] = ` " diff --git a/ts/input/tex/ColumnParser.ts b/ts/input/tex/ColumnParser.ts index cc41977e4..5452bf0c8 100644 --- a/ts/input/tex/ColumnParser.ts +++ b/ts/input/tex/ColumnParser.ts @@ -111,12 +111,6 @@ export class ColumnParser { * @param {ArrayItem} array The ArrayItem for the template */ public process(parser: TexParser, template: string, array: ArrayItem) { - // - // Remove one pair of braces, if there are any - // - if (template.charAt(0) === '{' && template.slice(-1) === '}') { - template = template.slice(1, -1); - } // // Initialize the state // @@ -136,6 +130,16 @@ export class ColumnParser { cextra: array.cextra, }; // + // Remove one pair of braces, if there are any + // + if (template.charAt(0) === '{' && template.slice(-1) === '}') { + const braced = this.getBraces(state); + if (braced.length === template.length - 2) { + state.template = braced; + } + state.i = 0; + } + // // Loop through the template to process the column specifiers // let n = 0; From acf15701e3c5375806b2291b09e0c1c06f5b10cd Mon Sep 17 00:00:00 2001 From: zorkow Date: Mon, 22 Jun 2026 18:20:12 +0200 Subject: [PATCH 17/26] SRE version bump. --- package.json | 2 +- pnpm-lock.yaml | 17 +++++++++-------- pnpm-workspace.yaml | 2 ++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 1c39dd754..bbcb3068a 100644 --- a/package.json +++ b/package.json @@ -171,6 +171,6 @@ "@mathjax/mathjax-newcm-font": "4.1.2", "mhchemparser": "^4.2.1", "mj-context-menu": "^1.0.0", - "speech-rule-engine": "5.0.0-rc.1" + "speech-rule-engine": "5.0.0-rc.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 99de33ac7..67e83a5f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^1.0.0 version: 1.0.0 speech-rule-engine: - specifier: 5.0.0-rc.1 - version: 5.0.0-rc.1 + specifier: 5.0.0-rc.3 + version: 5.0.0-rc.3 devDependencies: '@eslint/js': specifier: ^9.39.2 @@ -59,7 +59,7 @@ importers: version: 6.1.3 terser-webpack-plugin: specifier: ^5.5.0 - version: 5.5.0(webpack@5.106.2(webpack-cli@7.0.2)) + version: 5.5.0(webpack@5.106.2) typedoc: specifier: ^0.28.19 version: 0.28.19(typescript@5.9.3) @@ -633,6 +633,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -2154,8 +2155,8 @@ packages: spdx-license-ids@3.0.22: resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} - speech-rule-engine@5.0.0-rc.1: - resolution: {integrity: sha512-WgxL1K0MXNXW7+4fn11B6rtJ+jZTnCQMkJ44yV3XmFDcpGBqFJrDEHouGuFryqB5hoG1ksE2zlss/m6KOWnbPA==} + speech-rule-engine@5.0.0-rc.3: + resolution: {integrity: sha512-w8RXP1lZkGzOW6x299g0PzCjjaDCVRvO0CGtpUz788Y5KHqu7tJYEnY5p5MSY/pUBdhWYJshzKX0XJdGZYaxlQ==} hasBin: true sprintf-js@1.0.3: @@ -4952,7 +4953,7 @@ snapshots: spdx-license-ids@3.0.22: {} - speech-rule-engine@5.0.0-rc.1: + speech-rule-engine@5.0.0-rc.3: dependencies: '@xmldom/xmldom': 0.9.10 commander: 14.0.3 @@ -5026,7 +5027,7 @@ snapshots: tapable@2.3.3: {} - terser-webpack-plugin@5.5.0(webpack@5.106.2(webpack-cli@7.0.2)): + terser-webpack-plugin@5.5.0(webpack@5.106.2): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 @@ -5232,7 +5233,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.5.0(webpack@5.106.2(webpack-cli@7.0.2)) + terser-webpack-plugin: 5.5.0(webpack@5.106.2) watchpack: 2.5.1 webpack-sources: 3.3.4 optionalDependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 3f7e54bfd..b35810fab 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,4 @@ packages: - 'testsuite' +minimumReleaseAgeExclude: + - speech-rule-engine@5.0.0-rc.3 From 067563ac4c7df6e14f85b872ed48c18b097e4a9e Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 26 Jun 2026 10:41:31 -0400 Subject: [PATCH 18/26] Allow label ids to pass ui/safe filters. (mathjax/MathJax#3580) --- ts/ui/safe/safe.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/ui/safe/safe.ts b/ts/ui/safe/safe.ts index 228b77575..77c4db190 100644 --- a/ts/ui/safe/safe.ts +++ b/ts/ui/safe/safe.ts @@ -82,7 +82,7 @@ export class Safe { // // Pattern for allowed ids // - idPattern: /^mjx-[-a-zA-Z0-9_.]+$/, + idPattern: /^mjx-(?:eqn:.+|[-a-zA-Z0-9_.]+)$/, // // Pattern for data attributes // From 1b25f170e37045d98151eefa6e4e0d975d797a6a Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 26 Jun 2026 12:42:37 -0400 Subject: [PATCH 19/26] Handle inline line breaking with nested embellished operators. (mathjax/MathJax#3581) --- ts/output/svg/Wrappers/mrow.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ts/output/svg/Wrappers/mrow.ts b/ts/output/svg/Wrappers/mrow.ts index 3be3fba9f..33e6ee3e4 100644 --- a/ts/output/svg/Wrappers/mrow.ts +++ b/ts/output/svg/Wrappers/mrow.ts @@ -233,8 +233,9 @@ export const SvgMrow = (function (): SvgMrowClass { public addChildren(parents: N[]) { let x = 0; let i = 0; + const isEmbellished = this.node.isEmbellished; for (const child of this.childNodes) { - const n = child.breakCount; + const n = isEmbellished ? 0 : child.breakCount; child.toSVG(parents.slice(i, i + n + 1)); if (child.dom) { let k = 0; From 84ac9c8148f08119c8ad4bb3849aa56cfeb31acd Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Thu, 2 Jul 2026 11:40:39 -0400 Subject: [PATCH 20/26] Don't add file:// to windows path in CommonJS files. (mathjax/MathJax#3585) --- ts/util/context.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ts/util/context.ts b/ts/util/context.ts index a18295ba3..8179b590b 100644 --- a/ts/util/context.ts +++ b/ts/util/context.ts @@ -22,12 +22,18 @@ */ declare const process: { platform: string }; +declare const exports: object; /** * True if there is a window object */ export const hasWindow = typeof window !== 'undefined'; +/** + * True if used from the cjs directory, false for mjs directory + */ +export const isCJS = typeof exports !== 'undefined'; + /** * The browsers window and document objects, if any */ @@ -75,6 +81,6 @@ export const context = { if (context.os === 'Windows') { context.path = (file: string) => file.match(/^[/\\]?[a-zA-Z]:[/\\]/) - ? 'file://' + file.replace(/\\/g, '/').replace(/^\//, '') + ? (isCJS ? '' : 'file://') + file.replace(/\\/g, '/').replace(/^\//, '') : file.replace(/^\//, 'file:///'); } From ead0ba5b7c9317b4368d9439717315ee7e06175b Mon Sep 17 00:00:00 2001 From: zorkow Date: Thu, 2 Jul 2026 21:23:20 +0200 Subject: [PATCH 21/26] Update SRE to v5-rc.4 --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index bbcb3068a..a42e42020 100644 --- a/package.json +++ b/package.json @@ -171,6 +171,6 @@ "@mathjax/mathjax-newcm-font": "4.1.2", "mhchemparser": "^4.2.1", "mj-context-menu": "^1.0.0", - "speech-rule-engine": "5.0.0-rc.3" + "speech-rule-engine": "5.0.0-rc.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67e83a5f2..95c32323d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^1.0.0 version: 1.0.0 speech-rule-engine: - specifier: 5.0.0-rc.3 - version: 5.0.0-rc.3 + specifier: 5.0.0-rc.4 + version: 5.0.0-rc.4 devDependencies: '@eslint/js': specifier: ^9.39.2 @@ -2155,8 +2155,8 @@ packages: spdx-license-ids@3.0.22: resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} - speech-rule-engine@5.0.0-rc.3: - resolution: {integrity: sha512-w8RXP1lZkGzOW6x299g0PzCjjaDCVRvO0CGtpUz788Y5KHqu7tJYEnY5p5MSY/pUBdhWYJshzKX0XJdGZYaxlQ==} + speech-rule-engine@5.0.0-rc.4: + resolution: {integrity: sha512-3dFcH2QtQNhtvUUc09TxoaEK4WG03B9Z57krFG9jocrKykKGu35BhIkWr0vgEAxZZomEWkeluff69y/EbYzP4Q==} hasBin: true sprintf-js@1.0.3: @@ -4953,7 +4953,7 @@ snapshots: spdx-license-ids@3.0.22: {} - speech-rule-engine@5.0.0-rc.3: + speech-rule-engine@5.0.0-rc.4: dependencies: '@xmldom/xmldom': 0.9.10 commander: 14.0.3 From 583f6259193761bd7a64d9009684cad234c1c3fe Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 3 Jul 2026 12:32:57 +0200 Subject: [PATCH 22/26] update docs workflow actions --- .github/workflows/docs.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 040bc1b6e..03af37067 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -29,9 +29,9 @@ jobs: name: Generate Code Docs steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v5 name: Install pnpm with: version: 10 @@ -44,11 +44,11 @@ jobs: run: pnpm typedoc - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v5 with: # Upload docs folder path: './docs' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 From 177bad616c52afce4a4306676df99d36ff1c209a Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 3 Jul 2026 12:37:06 +0200 Subject: [PATCH 23/26] update test workflow actions --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c8d6a72e..a5c416400 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,16 +14,16 @@ jobs: name: Compile and test MathJax steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@v5 name: Install pnpm with: version: 10 run_install: false - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: 24 cache: 'pnpm' From 8500e004db7056dd822a2ca657797f183f782050 Mon Sep 17 00:00:00 2001 From: zorkow Date: Fri, 3 Jul 2026 13:51:06 +0200 Subject: [PATCH 24/26] update code coverage action to v6 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a5c416400..bd4092528 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,7 @@ jobs: run: pnpm -s test:gh - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} slug: mathjax/MathJax-src From bef76e2bd07207afeb41b3207e6e6784d5df7ee5 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 3 Jul 2026 07:56:03 -0400 Subject: [PATCH 25/26] Update TexParser for prettier --- ts/input/tex/TexParser.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ts/input/tex/TexParser.ts b/ts/input/tex/TexParser.ts index fc6a3a008..48f27addc 100644 --- a/ts/input/tex/TexParser.ts +++ b/ts/input/tex/TexParser.ts @@ -151,7 +151,8 @@ export default class TexParser { // // Back up one to pick up the parsed character (this.i is past it at this point). // - this.saveI = this.i - (kind === 'character' && input[1] !== '&' ? input[1].length : 0); + this.saveI = + this.i - (kind === 'character' && input[1] !== '&' ? input[1].length : 0); const result = this.configuration.handlers.get(kind).parse(input); // // The macro gets processed by the \\ character later From 05c40556055b2a00606cbbf46d9cb61fd0c0eb22 Mon Sep 17 00:00:00 2001 From: "Davide P. Cervone" Date: Fri, 3 Jul 2026 09:21:33 -0400 Subject: [PATCH 26/26] Update to v4.1.3 --- package.json | 4 ++-- pnpm-lock.yaml | 26 +++++++++++++------------- testsuite/package.json | 2 +- ts/components/version.ts | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index a42e42020..bf29dbdfc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mathjax/src", - "version": "4.1.2", + "version": "4.1.3", "description": "Beautiful and accessible math in all browsers. MathJax is an open-source JavaScript display engine for LaTeX, MathML, and AsciiMath notation that works in all browsers and in server-side node applications. This package includes the source code as well as the packaged components.", "keywords": [ "MathJax", @@ -168,7 +168,7 @@ ] }, "dependencies": { - "@mathjax/mathjax-newcm-font": "4.1.2", + "@mathjax/mathjax-newcm-font": "4.1.3", "mhchemparser": "^4.2.1", "mj-context-menu": "^1.0.0", "speech-rule-engine": "5.0.0-rc.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95c32323d..029dda439 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@mathjax/mathjax-newcm-font': - specifier: 4.1.2 - version: 4.1.2 + specifier: 4.1.3 + version: 4.1.3 mhchemparser: specifier: ^4.2.1 version: 4.2.1 @@ -59,7 +59,7 @@ importers: version: 6.1.3 terser-webpack-plugin: specifier: ^5.5.0 - version: 5.5.0(webpack@5.106.2) + version: 5.5.0(webpack@5.106.2(webpack-cli@7.0.2)) typedoc: specifier: ^0.28.19 version: 0.28.19(typescript@5.9.3) @@ -91,8 +91,8 @@ importers: specifier: ^29.7.0 version: 29.7.0 '@mathjax/mathjax-bbm-font-extension': - specifier: ^4.1.2 - version: 4.1.2 + specifier: ^4.1.3 + version: 4.1.3 '@types/jest': specifier: ^29.5.14 version: 29.5.14 @@ -462,11 +462,11 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@mathjax/mathjax-bbm-font-extension@4.1.2': - resolution: {integrity: sha512-UJdm+Cueut0+FjYZYoBmjZp/Rci17OMyUGsaHoSpZ//1NJ7n4LsJm9/jqAM38UGIuZEcQYbksqIfSJLFu10ncw==} + '@mathjax/mathjax-bbm-font-extension@4.1.3': + resolution: {integrity: sha512-dhL8qBIA7COFAeB+ypxbmNtb85+E8Xgis1TaUP5SKpYMMhU0wLcbDwgpriZcpca4Jneo7r6Ty4qEN+0yu6FQyw==} - '@mathjax/mathjax-newcm-font@4.1.2': - resolution: {integrity: sha512-lZHMjNP2XbABHA3kVn40rbse5ERUeMEmrGH03qLkCwxq4/5Z/eNLr0akw1MmQcqTwCbvkx1BFcmJ7RCfbRlw3Q==} + '@mathjax/mathjax-newcm-font@4.1.3': + resolution: {integrity: sha512-gzAB3dFHilHX1l5x2xUqRL+1jDQt3Fyza1DkEMVXWC4E8SvsGdlgEza47HYi2WhVcgfkvf4zgUGzuhbq3Pjlew==} '@pkgr/core@0.2.9': resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} @@ -3041,9 +3041,9 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@mathjax/mathjax-bbm-font-extension@4.1.2': {} + '@mathjax/mathjax-bbm-font-extension@4.1.3': {} - '@mathjax/mathjax-newcm-font@4.1.2': {} + '@mathjax/mathjax-newcm-font@4.1.3': {} '@pkgr/core@0.2.9': {} @@ -5027,7 +5027,7 @@ snapshots: tapable@2.3.3: {} - terser-webpack-plugin@5.5.0(webpack@5.106.2): + terser-webpack-plugin@5.5.0(webpack@5.106.2(webpack-cli@7.0.2)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 @@ -5233,7 +5233,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.5.0(webpack@5.106.2) + terser-webpack-plugin: 5.5.0(webpack@5.106.2(webpack-cli@7.0.2)) watchpack: 2.5.1 webpack-sources: 3.3.4 optionalDependencies: diff --git a/testsuite/package.json b/testsuite/package.json index 99c79921f..9c0d3269a 100644 --- a/testsuite/package.json +++ b/testsuite/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@jest/globals": "^29.7.0", - "@mathjax/mathjax-bbm-font-extension": "^4.1.2", + "@mathjax/mathjax-bbm-font-extension": "^4.1.3", "@types/jest": "^29.5.14", "jest": "^29.7.0", "ts-jest": "^29.4.6", diff --git a/ts/components/version.ts b/ts/components/version.ts index ee0f23014..7f1411ee8 100644 --- a/ts/components/version.ts +++ b/ts/components/version.ts @@ -22,4 +22,4 @@ * @author dpvc@mathjax.org (Davide Cervone) */ -export const VERSION = '4.1.2'; +export const VERSION = '4.1.3';