LaTeX数式 to MathML を考える その2

LaTeX数式 to MathML を考える

の続き。

目次

LaTeX vs MathML (continued)

前の記事では、「LaTeXではカッコは必ずしも対応してなくてもいいけどMathMLではカッコの対応が大事」ということを書いた。

MathML特有の概念(マークアップ)は他にも色々あるので、この記事ではそれらを掘り下げていく。

トークン (<mi>, <mn>, <mo>, <mtext>)

TeXの数式中に xyz という文字の並びを書いた時に、これが「一つの識別子か、乗算記号を省略した複数の変数か」というのが明らかではないという問題がある。MathMLへ変換する際は、識別子であれば一つの<mi>タグを生成し、複数の変数であれば複数の<mi>タグとそれを区切る<mo>&InvisibleTimes;</mo>を生成する必要がある。

「識別子か複数の変数か」の判断に関しては、\mathrm等のフォントに関する指定を考慮すれば良いだろう。つまり、\mathrmの中であれば識別子と判断し、そうでなければ複数の変数と判断する。

数値リテラルに関しても同様の問題がある。MathMLでは数値リテラルは<mn>タグによりひとまとまりのトークンとして扱うが、TeXでは 123.4 という数値リテラルを書いてもひとまとまりとしては扱われず、ただ数字やピリオドが並んでいるだけである。(xの10乗のつもりでx^10と書いてxの指数が1だけ、つまり \(x^10\) になってしまう、というような経験は誰にでもあるだろう。)

<mn>に関しては変換器の側で「数字とピリオドの並びをひとまとまりとして解釈する」という方針である程度カバーできそうだ。ただ、数字とピリオドだけではなく、桁区切りの記号としてカンマを 1{,}234.5 という風に使っている場合も考えられるので注意が必要である。(桁区切りにカンマ , を使う場合はクラスが\mathpunctではなく\mathordになるように{}で囲う、というのはTeXに詳しい皆さんならよく知っているだろう。筆者は最近知った。)

不可視演算子

前の記事では INVISIBLE TIMES, INVISIBLE PLUS, INVISIBLE SEPARATOR 等の不可視演算子について触れた。

実はTeXにも「不可視の乗算記号」に近いものはあり、 \* がそれである。これは「通常は何も表示しないが、そこで行分割が必要になった場合には掛け算記号が挿入される」という代物である。

この \* を INVISIBLE TIMES に対応させるのは妥当な発想だろう。ただ、\*には「行分割するならここ」という意味があるので、MathMLに対応させるならただのINVISIBLE TIMESではなくて

<mo linebreak="goodbreak">&InvisibleTimes;</mo>

という風にlinebreak属性を指定したものになるだろう。

というわけで「行分割に関する指定を伴わない INVISIBLE TIMES」を出力するには、やはりLaTeXソースの段階でマークアップしておくか、変換器が推測する必要があるだろう。

<mmultiscripts>

(この記事ではsubscript/superscriptの類をまとめて「添字」と呼ぶことにする)

TeXでは(limitsではない)添字は基本的に右上と右下に1個ずつで、より柔軟な配置をしたければ、核が空のアトム {} を作ってそれに対する添字として実現する。

例:テンソル \(A_i{}^j\) (j が i の真上ではなく、右上に配置されていることに注意)

A_i{}^j

例:組合せの数(高校で使う表記) \({}_nC_r\) もしくは \({}_n\mathrm{C}_r\)

{}_nC_r, {}_n\mathrm{C}_r

例:行列の転置記号(左上に書く流儀) \({}^t\!A\)

{}^t\!A

転置記号を左上に書く流儀の中でも、人によって空白の量は異なるかもしれない。

一方、MathMLには<mmultiscripts>というタグがあり、このような柔軟な位置の添字をより直接的に表現できる。

https://www.w3.org/TR/MathML3/chapter3.html#presm.mmultiscripts

LaTeX数式をMathMLに変換する際には、核が空のアトム {} にの添字を <mmultiscripts> に変換することが望ましい。処理系の側では追加のマークアップを用意すると良いかもしれない。

これと近いものとしてamsmathには \sideset{}{}{} があり、\mathopアトムの四隅に添字を配置できる。これも<mmultiscripts>に対応させると良いだろう。(\sidesetは\sum等の\mathopクラスのアトムに適用することを前提としており、汎用的には使えない。)

例:\(\displaystyle\sideset{_a^b}{_c^d}{\sum}\)

\sideset{_a^b}{_c^d}{\sum}

<maction>

MathMLでは <maction> タグによって数式の一部をインタラクティブにできる。例えば、複数の数式を切り替え(トグル)たり、ツールチップを表示したりできる。

https://www.w3.org/TR/MathML3/chapter3.html#presm.maction

変換の際にこれらのMathML要素を出力できるようなTeXコマンドを用意しておくと良いかもしれない。

MathJax

Webサイトにおいて手抜きで簡単に数式を書けるようにする、みんな大好きMathJaxであるが、MathJaxではLaTeXの記法を拡張しており、MathML出力を意識した拡張が使えるようになっている。

TeX/LaTeXに対する拡張一覧:https://docs.mathjax.org/en/latest/tex.html

MathMLの機能とLaTeXコマンドの対応:

  • <maction>: \mathtip{math}{tip}, \texttip{math}{tip}, \toggle{}{}…\endtoggle
  • <menclose>: \enclose{notation}[attributes]{math}
  • ハイパーリンク:\href{url}{math}
  • CSSクラス・id等:\class{name}{math}, \cssId{id}{math}, \style{css}{math}
    • CSSクラスを与えるLaTeXコマンドは、前の記事で取り上げたLaTeXMLにもあった(\lxWithClass{}{})
  • \unicode{}: Unicode文字をコードポイントにより入力できる。

itex2MML

この “itex” はLaTeXの方言のことで、Knuthによるジョークのことではない。

オリジナル:http://pear.math.pitt.edu:80/mathzilla/itex2mml.html

最新版(?):https://golem.ph.utexas.edu/~distler/blog/itex2MML.html

みなさんnLabには日頃からお世話になっていると思うが、nLabで使われているWikiエンジン(Instiki)で数式をLaTeX記法からMathMLに変換するのに使われているのがこのitex2MMLである。

コマンド一覧:https://golem.ph.utexas.edu/~distler/blog/itex2MMLcommands.html

MathMLの機能とLaTeXコマンドの対応:

  • <mn>: \itexnumコマンドにより、一つの<mn>タグに入るべき数値表記を明示できる。
  • ハイパーリンク:\href
  • <maction>: \statusline, \tooltip, \fghilight, \bghilight, \toggle, \begintoggle{}..\endtoggle
    • \toggleの記法がMathJaxと互換性がないものになっている。

TeXZilla

http://fred-wang.github.io/TeXZilla/

コマンド一覧:https://github.com/fred-wang/TeXZilla/wiki/TeXZilla-Commands

系譜としては、itex2MMLの姉妹に相当するだろうか。

JavaScript製だが、ページ出力ではなく単体のプログラムとして動作するようだ。

MathMLの機能とLaTeXコマンドの対応:

  • <mn>: \itexnum(itex2MML互換)、 \mn
  • <mi>: \mi
  • <mo>: \mo
  • <ms>: \ms
  • <mtext>: \mtext

TeX4ht

TeX4htはTeXが出力したDVIを対象に処理を行うらしい。

DVIから処理して得られるHTMLはどうしても構造化から縁遠いイメージがあり、そこをどうやって処理しているのか気になる。\Configureコマンドというのがあるようだが、どうなっているのか。

The LaTeX Web Companionという本にTeX4htとLaTeX2HTMLについての解説があるらしいが、移り変わりが激しいWeb分野について、前世紀の本をお金を出して買う価値があるか疑わしい。

オリジナルの作者(E. Gurari)は2009年に亡くなっているようで、そのせいか知らないが、ドキュメントに載っているリンクがいくつかリンク切れしている。(まあInternet Archiveによると2004年初頭を最後にリンク切れを起こしているので、リンク切れと作者の死は関係ないのかもしれない)

リンク切れしている資料の、Internet Archiveのリンク:

その他・要調査

変換ツール – TeX Wiki には LaTeX と HTML/MathML/etc. の変換ツールが沢山載っている。皆さん車輪の再発明しすぎでは、感がなくもない。まあ人によって「LaTeX→HTML/MathML/etc.」の思想が異なる以上、実装が乱立するのも仕方がないのだ。

KaTeX

https://khan.github.io/KaTeX/function-support.html

KaTeXはあまりMathMLのことを考えていないイメージがあり、MathML出力を意識した拡張は見受けられない。

強いて言えば \href によって生成されるハイパーリンクはハイパーテキスト特有の概念であろう(しかしハイパーリンクならPDFにもあるわけだが)。

LaTeXMathML

オリジナル:https://www.maths.nottingham.ac.uk/personal/drw/lm.html

拡張:http://math.etsu.edu/LaTeXMathML/

Perl版:http://pillars.che.pitt.edu/LaTeXMathML/

オリジナルと拡張版はJavaScript製である。Webブラウザ上で動的にページを変換することを目指しているように見える。

Perl版は単体のコマンドとして使えて、LaTeXiTのMathML出力で使われているようである。

MathML出力用の独自コマンドの類は、ドキュメントを見る限りでは特に見当たらない。

plasTeX

http://tiarno.github.io/plastex/

Python製。

数式についてはあまり真面目に考慮されていないようで、システムにインストールされたLaTeX処理系で画像化しているらしい(?)。なのでこの記事で取り上げても得るものは少なそうである。

LaTeX2HTML

http://www.latex2html.org/

https://github.com/latex2html/latex2html/

Perl製。前世紀から開発が続いている。

数式をHTML(4以前)に変換する機能はありそうだが、MathMLには対応していないように見える。なのでこの記事で取り上げても(ry

HeVeA

http://hevea.inria.fr/

OCaml製のやつ。

一応MathMLを出力するオプションがあるようだ。

どうでもいいけどLaTeXにあるような上付き文字、下付き文字を<sup>や<sub>で表すと見た目が貧相に見えるからやめたほうがいいと思う。

TtM

http://hutchinson.belmont.ma.us/tth/mml/

C言語で実装されている。

数式のマークアップに関する独自拡張は特に見受けられない。

どうでもいいけどLaTeXにあるような上付き文字、下付き文字を<sup>や<sub>で表すと見た目が貧相に見えるから(ry

Webtex

http://pkgw.github.io/webtex/

JavaScriptで動的にDOMを生成する。MathJaxやKaTeXと異なり、文書全体が対象である。

数式はMathMLを使わず、<canvas>に描画されるようだ。なのでこの文書の対象外である。

筆者が作りたいもの

簡易的なLaTeX→HTML/MathML変換プログラムには、LaTeXの文法をマークアップ言語のような感じででっち上げてそれを解釈する、というものが多いだろう。しかし実際のLaTeX文書ではマクロの定義を始めとして、色々厄介な凝ったことをしていることが考えられ、より精度良くTeX/LaTeXを模倣しないとうまくいかない可能性が高い。

それに、言語オタク的な趣味として、あるいはTeX言語のより良い理解を得るために、TeX処理系を高精度で再現したい。

TeXの処理には大きく分けて4つの段階があり、

  • input processor: 字句解析
  • expansion processor: マクロ等の展開
  • execution processor: マクロ等の定義、各種代入、そして horizontal/vertical/math list の構築
  • visual processor: 組版

の4つが密結合している(例:execution processorでの処理が字句解析のレイヤーに介入できる)。

筆者の当面の目標としては、execution processorまでを模倣し、(必要に応じて追加のメタデータを載せた)math listを生成する。そして、生成されたmath listを解釈し、MathMLに変換することである。

そういうわけでここ最近TeXの重箱の隅をぐいぐいつついているわけである。

TeXっぽいものを実装するにあたっての雑記

実装の方針:

  • LaTeX文書全体ではなく、数式の部分を対象とする。
    • Markdown中にLaTeX記法で書いた数式を処理できるようにするため。
    • LaTeX文書の数式以外の部分をHTMLに変換する機能を実装するのも面白いのかもしれないが、優先的なゴールではない。
  • ソフトウェアとして再利用可能な構成を目指す。
    • 第一級モジュールのような高級な言語機構を備える言語であればこれは可能だと信じる。(再利用可能にしたところでどう使うのかという話だが)
    • 組版エンジンを追加で実装すればそのままTeX互換処理系ができる…レベルになるといいなあ(妄想)
  • TeXとの完全な互換性よりも、合理的だと思われる仕様を目指す。
  • LuaTeX等の先進的なエンジンから良さそうな仕様を無理のない範囲で取り込んでいく。
  • 入力に間違いや推奨されない書き方がある場合に、TeXよりもわかりやすいエラーメッセージ・警告メッセージが出るようにする。
    • KnuthのTeXはエラー時にトークンを挿入したりしてある程度エラーリカバリーができるようになっているが、そんなものは実装しない。

(箇条書きの中で言ってることが矛盾してなくもない気がするが気にしない。)

生成するMathMLであるが、WebKitのようなMathML対応が比較的貧弱な環境でもある程度まともに表示されるように、CSSと組み合わせてどうにかしたい。(WebKitの実装がどの程度まともでどの程度だったらCSSでカバーできるのか、確かめる必要がある。)

https://github.com/minoki/yurumath

鹿野氏の「TeXユーザの集い2015」でのスライド「TeX原稿からEPUBを作りたい」

の18ページ目

の分類で言えば「2. TeXエミュレート型」に相当するだろう。

すでに「TeXエミュレート型」の変換器はいくつかあるので、わざわざ新しいものを作る価値があるのか…と言われると答えづらいが、まあ詰まるところ筆者のエゴなのでどうでもいい。

その他

LaTeXからXML (HTML,MathML) を生成しようという動きは前世紀からあったわけだが、「MathML特有の概念とかXMLの属性をLaTeXでマークアップする記法(コマンド)を標準化しよう」という動きはなかったのだろうか。

少なくとも

  • トークンの明示
  • 不可視演算子の指定
  • <mmultiscripts>
  • <maction>
  • XML属性の指定:id, class, style

に関する処理系横断のコマンド群はあっても良かったはずで、現状では各処理系が独自にコマンドを定義し、しかも一部では互換性がない(同じコマンド名で異なる挙動を示す)という事態になっている。

ちなみにLaTeX文書にハイパーリンク等を挿入する機構としてはLaTeXのhyperrefパッケージがあり、実際に、LaTeXからHTMLを吐くような処理系はだいたい共通して\hrefコマンド等を実装している。そのような共通するコマンドがMathML出力でも欲しかった。

あとは、この「LaTeX数式→MathML」というトピックについてまとめられた文献(論文等)があるようなら漁ってみるべきかもしれない。(面倒くさい)


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です