[LyX/master] Add support for MathJax (#8480)

Juergen Spitzmueller spitz at lyx.org
Sun Aug 16 07:24:12 UTC 2026


commit 14f12a88a4a088a0469685c808f4a5cac3d6d278
Author: Juergen Spitzmueller <spitz at lyx.org>
Date:   Sun Aug 16 09:20:45 2026 +0200

    Add support for MathJax (#8480)
    
    File format change.
---
 development/FORMAT              |  8 ++++++++
 lib/lyx2lyx/lyx_2_6.py          | 15 +++++++++++++--
 src/Buffer.cpp                  | 10 ++++++++++
 src/BufferParams.h              |  3 ++-
 src/OutputParams.h              |  3 ++-
 src/frontends/qt/ui/OutputUi.ui |  5 +++++
 src/mathed/InsetMathHull.cpp    | 16 ++++++++++++++++
 src/version.h                   |  4 ++--
 8 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/development/FORMAT b/development/FORMAT
index 1bbe350ffb..a798d73330 100644
--- a/development/FORMAT
+++ b/development/FORMAT
@@ -7,6 +7,14 @@ changes happened in particular if possible. A good example would be
 
 -----------------------
 
+2026-08-03 Jürgen Spitzmüller <spitz at lyx.org>
+	* Format incremented to 659: Add new option
+	\html_math_output 5
+	(= MathJax)
+
+2026-08-04 Udi Fogiel <ufogiel at lyx.org>
+	* Format incremented to 658: Support for aligned overset.
+
 2026-08-03 Jürgen Spitzmüller <spitz at lyx.org>
 	* Format incremented to 657: Support for \fronmatter, \mainmatter,
 	  and \backmatter via paragraph parameter
diff --git a/lib/lyx2lyx/lyx_2_6.py b/lib/lyx2lyx/lyx_2_6.py
index a1e0171b50..73c5c8b837 100644
--- a/lib/lyx2lyx/lyx_2_6.py
+++ b/lib/lyx2lyx/lyx_2_6.py
@@ -1978,7 +1978,16 @@ def convert_svmatters(document):
                 document.body[i : i + 1] = ["\\begin_layout Standard", "\\start_of_matter mainmatter"]
             elif matter == "Back Matter":
                 document.body[i : i + 1] = ["\\begin_layout Standard", "\\start_of_matter backmatter"]
-        
+
+
+def revert_mathjax(document):
+    """Revert MathJax XHTML math output to default (MathMLCore)"""
+    i = find_token(document.header, "\\html_math_output", 0)
+    if i == -1:
+        return
+    
+    if get_value(document.header, "\\html_math_output", i) == "5":
+        document.header[i] = "\\html_math_output 0"
 
 ##
 # Conversion hub
@@ -2000,11 +2009,13 @@ convert = [
     [655, []],
     [656, []],
     [657, [convert_svmatters]],
-    [658, [convert_use_alignedoverset, convert_alignedoverset_body]]
+    [658, [convert_use_alignedoverset, convert_alignedoverset_body]],
+    [659, []]
 ]
 
 
 revert = [
+    [658, [revert_mathjax]],
     [657, [revert_use_alignedoverset]],
     [656, [revert_matters]],
     [655, [revert_parfillskip]],
diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 64a471a60f..2c8cf086c9 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -2323,6 +2323,13 @@ Buffer::ExportStatus Buffer::writeLyXHTMLSource(odocstream & os,
 		         xml::escapeString(doctitle, XMLStream::ESCAPE_ALL))
 		   << "</title>\n";
 
+		if (params().html_math_output == BufferParams::MathJax)
+			os << "\n<script id=\"MathJax-script\" "
+			   << "async=\"async\" "
+			   << "src=\"https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js\">"
+			   << "</script>"
+			   << "\n\n";
+
 		docstring styles = features.getTClassHTMLPreamble();
 		if (!styles.empty())
 			os << "\n<!-- Text Class Preamble -->\n" << styles << '\n';
@@ -4632,6 +4639,9 @@ void Buffer::setMathFlavor(OutputParams & op) const
 	case BufferParams::LaTeX:
 		op.math_flavor = OutputParams::MathAsLaTeX;
 		break;
+	case BufferParams::MathJax:
+		op.math_flavor = OutputParams::MathAsMathJax;
+		break;
 	}
 }
 
diff --git a/src/BufferParams.h b/src/BufferParams.h
index 5a1a67341a..41a1c94583 100644
--- a/src/BufferParams.h
+++ b/src/BufferParams.h
@@ -646,7 +646,8 @@ public:
 		MathML3 = 4,
 		HTML = 1,
 		Images = 2,
-		LaTeX = 3
+		LaTeX = 3,
+		MathJax = 5
 	};
 	/// what to use for math output. present choices are above
 	MathOutput html_math_output;
diff --git a/src/OutputParams.h b/src/OutputParams.h
index f6d1830dc1..f76f44f177 100644
--- a/src/OutputParams.h
+++ b/src/OutputParams.h
@@ -58,7 +58,8 @@ public:
 		MathAsMathML3,
 		MathAsHTML,
 		MathAsImages,
-		MathAsLaTeX
+		MathAsLaTeX,
+		MathAsMathJax
 	};
 
 	enum TableCell {
diff --git a/src/frontends/qt/ui/OutputUi.ui b/src/frontends/qt/ui/OutputUi.ui
index 451ee27bda..958fd52817 100644
--- a/src/frontends/qt/ui/OutputUi.ui
+++ b/src/frontends/qt/ui/OutputUi.ui
@@ -322,6 +322,11 @@
                 <string>MathML 3</string>
                </property>
               </item>
+              <item>
+               <property name="text">
+                <string>MathJax</string>
+               </property>
+              </item>
              </widget>
             </item>
             <item>
diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp
index dd980f5640..731c57b06a 100644
--- a/src/mathed/InsetMathHull.cpp
+++ b/src/mathed/InsetMathHull.cpp
@@ -2803,6 +2803,22 @@ void InsetMathHull::xhtml(XMLStream & xs, OutputParams const & op) const
 		}
 		// In case of failure, generate an image.
 	}
+	if (mathtype == BufferParams::MathJax) {
+		// Unfortunately, we cannot use latexString() because we want
+		// \(...\) rather than $...$.
+		// The returned value already has the correct escaping for HTML.
+		docstring const latex = mathAsLatex();
+
+		// FIXME XHTML
+		// probably should allow for some kind of customization here
+		docstring const starttag = (getType() == hullSimple) ? from_ascii("\\(") : from_ascii("\\[");
+		docstring const endtag = (getType() == hullSimple) ? from_ascii("\\)") : from_ascii("\\]");
+		xs << starttag
+		   << XMLStream::ESCAPE_NONE << latex
+		   << endtag
+		   << xml::CR();
+		success = true;
+	}
 
 	// what we actually want is this:
 	// if (
diff --git a/src/version.h b/src/version.h
index 3a5466b998..0dd6564083 100644
--- a/src/version.h
+++ b/src/version.h
@@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 658 // ufogiel: aligned-overset
-#define LYX_FORMAT_TEX2LYX 658
+#define LYX_FORMAT_LYX 659 // spitz: MathJax
+#define LYX_FORMAT_TEX2LYX 659
 
 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
 #ifndef _MSC_VER


More information about the lyx-cvs mailing list