;;; mathml-from-tex.el --- Generate MathML from TeX -*- lexical-binding: t; -*- ;; Copyright (C) 2025 Philip Kaludercic ;; Author: Philip Kaludercic ;; Maintainer: Philip Kaludercic ;; URL: https://wwwcip.cs.fau.de/~oj14ozun/src+etc/mathml-from-tex.el ;; Version: $Id: mathml-from-tex.el,v 1.5 2025/04/19 08:17:42 oj14ozun Exp $ ;; Package-Version: 1 ;; Keywords: tex ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; This script implements a function that extracts a TeX math-mode ;; string from a string and turns it into a MathML ;; (https://developer.mozilla.org/en-US/docs/Web/MathML) expression. ;; You can use it to write mathematical expressions in a familiar way ;; within HTML documents, without having to write MathML by hand. ;; The heavy-lifting of converting TeX to MathML is handled by the ;; "latexmlmath" executable, which is part of the LaTeXML suite (see ;; https://math.nist.gov/~BMiller/LaTeXML/). ;;; Code: (defgroup mathml-from-tex () "Generate MathML from TeX." :group 'tex) (defcustom mathml-from-tex-flags '("--preload=mathtools.sty" "--preload=stmaryrd.sty" "--preload=amsfonts.sty" "--preload=amssymb.sty" "--preload=amsmath.sty") "Additional flags for `mathml-from-tex'. See man page `latexmlmath(1)' for an overview." :type '(repeat string)) (defun mathml-from-tex (&optional inline) "Convert TeX in a comment to MathML in a buffer. The TeX has to be written in a single-line comment prefixed with a \"MathML:\" string. For example in HTML one would have a comment like: Everything until the end of the comment (or line) is passed to \"latexmlmath\" and injected into the next line of the buffer. Remember to keep the tag on the next line, so that when repeating the command, the previous output can be recognised and replaced. If INLINE is non-nil, then the generated tag will have a display=\"inline\" attribute. Interactively, INLINE is non-nil if the next line contains a in display=\"inline\" attribute. The value can be toggled using a prefix argument." (interactive (save-excursion (forward-line) (list (xor (looking-at-p (rx "" eol)) current-prefix-arg)))) (save-excursion (goto-char (line-beginning-position)) (unless (search-forward-regexp (rx (literal comment-start) (* space) "MathML: " (group (* nonl)) (literal comment-end)) (line-end-position) t) (user-error "No MathML comment found")) (forward-line 1) (save-excursion (let ((math (match-string 1)) (start (point))) (cond ((looking-at-p (rx (* space) "\n") nil t) (error "Unmatched tag!")) (delete-region start (point)))) (apply #'call-process-region math nil "latexmlmath" nil t t (append mathml-from-tex-flags (list "-"))))) ;; Due to the last `save-excursion', we are at the beginning of ;; the block right now. (when inline (replace-regexp-in-region (rx "display=\"block\">" eol) "display=\"inline\">" (point) (line-end-position))))) (provide 'mathml-from-tex) ;;; mathml-from-tex.el ends here