从v2升级到v3
mathjax v3是对mathjax的彻底重写(请参见 mathjax v3.0的新特性 ,因此它的内部结构与版本2有很大不同。这意味着mathjax v3是 not 替换mathjax v2并升级到版本3需要对web页面进行一些调整。下面的部分描述了您需要进行的更改,以及v2和v3之间最重要的区别。
警告
如果您正在使用 latest.js
cdn上mathjax v2的特性,注意这将 not 自动更新到版本3,因为版本3中存在重大且可能中断的更改。但是,有一个错误 latest.js
在2.7.5及以下版本中;当当前版本为3.0或更高版本时, latest.js
将不使用2.x的最高版本,而是使用 latest.js
已经被带走了。例如,如果加载 latest.js
从版本2.7.3开始,它目前提供的是最新版本2.7.5,当版本3发布到CDN时,您的页面将再次恢复使用版本2.7.3。此行为已在版本2.7.6中更正,因此如果更改为加载 latest.js
从版本2.7.6,您应该得到最新的2.x版本,而不管cdn上是否存在版本3。
mathjax v3仍在进行中;并不是版本2的所有特性都已转换为版本3,有些特性可能还没有。随着我们将更多的特性移到版本3中,mathjax v2将继续得到维护,但是一旦mathjax v3完全转换,mathjax v2可能不会看到更多的开发,仅仅是维护。
配置更改
版本3中有许多更改会影响mathjax的配置方式。在版本2中,有几种方法可以为mathjax提供配置;在mathjax 3中,当您使用 MathJax components ,现在只有一个,就是设置 MathJax
全局以在加载mathjax之前包含配置信息。尤其是,你不再打电话 MathJax.Hub.Config()
,并且此函数在mathjax v3中不存在。见章节 配置mathjax 有关如何配置mathjax的详细信息。
除了要求使用 MathJax
用于设置配置的全局变量、配置选项的组织已更改以适应mathjax的新内部结构,并且它们的某些名称也已更改。为了帮助您将现有的版本2配置转换为版本3,我们提供了 conversion tool 您可以使用它来获得与当前版本尽可能接近的版本3配置。
但是,并非所有配置参数都可以直接转换。对于其中一些,这是因为版本2的特性还没有移植到版本3,但是对于其他一些,版本2的特性可能根本不存在于版本3的新体系结构中。例如,mathjax v2分阶段更新页面,首先删除数学源表达式(例如,tex代码),然后插入预览表达式(创建速度快,但布局不准确),然后返回并生成高质量的排版版本,它在页面更新。mathjax版本3不是这样工作的(在数学完全排版之前,它不会更改页面),因此控制数学预览和要显示的公式分块的选项在版本3中没有对应项。
最后,通过扩展现有的mathjax对象来更改mathjax代码的配置,或者通过 MathJax.Hub.Register.StartupHook()
或者其他钩子机制中的一个将不会转移到版本3。mathjax v3不使用第2版的核心队列、信号和回调,因此依赖它们的代码必须更新。见 配置和加载mathjax 第节了解解决这些问题的一些方法。
加载mathjax的更改
正如mathjax的配置方式发生了变化一样,mathjax的加载方式也发生了变化。对于版本2,您可以加载 MathJax.js
并使用 ?config=
后跟配置文件的名称。这总是需要至少加载两个文件(通常不止两个),而第二个文件总是异步加载,这意味着mathjax总是异步操作。
在版本3中,不再有 MathJax.js
文件,然后直接加载组合的组件文件。例如,你装载 tex-chtml.js
使用commonhtml输出获取tex。这减少了需要请求的文件数量,并提高了性能。见 加载mathjax 了解更多详细信息。
就像没有必要使用 ?config=
在版本3中,可以用这种方式设置的其他参数也不在版本3中。例如,你不能 delayStartupUntil
在加载mathjax的脚本中。
在版本3中,启动顺序的操作方式与版本2中的操作方式有根本的不同。在版本2中,mathjax将在加载mathjax后立即开始其启动过程,排队操作以执行配置块、加载扩展和jax、执行初始排版等。很难将您自己的操作插入到这个序列中,如果您没有将配置放在正确的位置,则可能会出现计时问题。
在版本3中,与mathjax的同步是通过es6 promises完成的,而不是mathjax的队列和信号,mathjax的启动过程更为直接。您可以更容易地将自己的代码插入到启动过程中,并且可以完全替换默认的启动操作(如果您愿意的话)。mathjax在启动期间采取的操作最好分开,这样您可以选择要执行的操作。见 启动操作 有关如何完成此任务的详细信息,请参阅第节。
mathjax api中的更改
因为内部已经完全重新设计了, API 已经更改,因此如果您一直在调用mathjax函数,或者通过扩展现有的mathjax对象修改了mathjax内部,则该代码将不再适用于版本3,必须进行修改。下面将讨论一些更重要的更改。
这个
Mathjax.Hub.Typeset()
函数已被替换为MathJax.typesetPromise()
和MathJax.typeset()
功能。事实上,MathJax.Hub
已完全移除。
版本2的核心队列、信号和回调已被版本3中的es6承诺所取代。特别是,您可以使用
MathJax.startup.promise
作为替代品MathJax.Hub.Queue()
. 见 处理异步排版 这是怎么做的。见 版本2兼容性示例 下面的代码可能使您能够在版本3中使用版本2代码。
这个
MathJax.Hub.Register.StartupHook()
其他相关的钩子已经被ready()
中的函数 加载器 组件。因此,依赖这些钩子来改变mathjax的代码需要重新编写。这个 启动操作 部分显示了可用于此操作的一些机制。
版本2配置可以包括
Augment()
可用于在主mathjax对象中添加(或重写)方法和数据的块。在版本3中,应该通过对mathjax对象类进行子类化并将新类传递给使用它们的对象来处理。这可以在 startup 组件的ready()
函数,当mathjax类可用时,但在创建它们的任何实例之前。见 启动操作 关于如何做到这一点的一些想法。
这个
Augment
配置块和StartupHooks()
上面描述的函数可以在版本2中用于扩展mathjax的功能,特别是通过添加新的基于javascript的宏来扩展tex输入jax。这些版本2机制在版本3中不可用;相反,tex扩展在版本3中更正式。见 构建自定义组件 一节中的示例。
在版本2中,由mathjax定位的数学将从页面中删除并存储在
<script>
页面内的标记。读者看不到这些,但在页面上标记数学的位置和内容。在版本2中,程序可以创建这些<script>
标记本身,避免了mathjax查找数学分隔符的需要,也避免了页面作者对html特殊字符进行编码,如<
,>
和&
在他们的数学中。版本3不以这种方式修改文档,也不存储它在页面中的标记中的数学值。相反,它保留了一个外部的数学对象列表(属于MathItem
班级)。因此,如果您希望在开始时使用这些脚本将数学存储在页面中,可以替换find
中的操作 renderActions 列表以使用一个函数来定位脚本并创建所需的MathItem
物体。例如MathJax = { options: { renderActions: { find: [10, function (doc) { for (const node of document.querySelectorAll('script[type^="math/tex"]')) { const display = !!node.type.match(/; *mode=display/); const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display); const text = document.createTextNode(''); node.parentNode.replaceChild(text, node); math.start = {node: text, delim: '', n: 0}; math.end = {node: text, delim: '', n: 0}; doc.math.push(math); } }, ''] } } };
应该找到mathjax版本2通常会创建的脚本。
注意这将 代替 标准
find
操作查找数学分隔符,而此操作则查找MathJax v2脚本标记。如果你愿意的话 both 原始分隔符搜索 and 搜索脚本标记,然后更改find:
以上至findScript:
这样就不会取代默认值find
行动。这样,两个动作都会发生。
输入和输出jax的变化
输入和输出处理器(称为“jax”)是mathjax的核心部分。版本2的所有三个输入处理器都在版本3中,但是 AsciiMath 处理器尚未完全移植到版本3,当前由修补到版本3框架上的旧版本2代码组成。这比完整的版本3端口更大,效率更低,后者应该包含在将来的版本中。
在版本2中,mathjax使用了预处理器 (tex2jax , mml2jax , asciimath2jax 和 jsMath2jax )在页面中定位数学并为输入jax做好准备。实际上不需要将它们分开,所以在版本3中,它们被折叠到各自的输入jax中。这意味着您不需要单独加载它们,预处理器和输入jax的配置选项已经组合在一起。例如, tex2jax
和 TeX
选项现在都出现在 tex
配置块。
MathJax版本2包括六个不同的输出jax,它们是随着时间的推移而开发的,用于不同的目的。最初的HTML-CSS输出jax具有最大的浏览器覆盖率,但其输出依赖于浏览器,其字体检测非常脆弱,并且是输出处理器中最慢的。CommonHTML输出jax是HTML输出的一个更现代的翻版,它既独立于浏览器,又相当快。SVG输出jax生成SVG图像而不是htmldom树,并且不需要web字体来显示数学,因此结果可以是自包含的。MathJax版本3包含了CommonHTML和SVG输出jax,但是放弃了旧的、较慢的HTML-CSS输出格式。
mathjax 2还包含一个输出格式,该格式为支持它的浏览器生成mathml。由于目前只有firefox和safari实现了mathml呈现(在ie、edge或chrome中没有支持),并且由于mathjax无法控制浏览器中mathml支持的质量或覆盖范围,mathjax版本3暂时放弃了nativemml输出格式。如果将来浏览器的状况有所改善,可以重新添加。见 mathml支持 关于这方面的更多信息,以及如何自己实现mathml输出的示例。
支持的输入和输出jax中很少有更改,如下所述:
输入更改
tex输入jax中有两个更改,它们会影响页面中现有tex内容的向后兼容性。
第一个问题是 \color
宏;在版本2中, \color
是一个非标准的,因为它需要两个参数(颜色和数学显示在该颜色中的颜色),而真正的 Latex 版本是一个开关,可以改变它后面的所有内容的颜色。 Latex 兼容的一个是作为一个扩展。在版本3中,两个版本都是扩展(请参见),与 Latex 兼容的版本在 \color
是第一次使用。见 颜色 和 颜色2 有关更多信息以及如何配置mathjax以使用原始版本2的扩展 \color
宏。
另一个不兼容性是在版本3中更改了一些扩展名。例如, AMScd 在版本2中现在是 amscd 在版本3中。这意味着你需要使用 \require{{amscd}}
而不是 \require{{AMScd}}
加载 CD 环境。为了支持使用 \require
,您可以使用 版本2兼容性示例 下面部分。
其他一些变化包括:
这个 autoload-all 扩展名已重命名 autoload ,并且比原来的更灵活和可配置。
用于控制方程式编号格式的配置选项已移动到扩展名;请参见 标记格式 有关详细信息的文档。
这个
useMathMLspacing
不同输入jax的选项已经被移到输出jax,而不是mathmlSpacing
选择权。
这个
processEscapes
选项为 tex2jax 预处理器(现在用于TeX input jax)的默认值为false
在版本2中,但有默认值true
在版本3中。
的功能 MathChoice 扩展名已移动到基本tex包。
非标准
UPDIAGONALARROW
和ARROW
符号已从menclose
元素。这些已经被标准northeastarrow
表示法。
输出变化
版本3中的输出jax有几个重要的更改,还有一些尚未实现但将在将来的版本中实现。其中一个功能是linebreaking,它还没有移植到版本3。另一个是,目前只有mathjax-tex字体在版本3中可用。见 尚未移植到版本3 对于仍在转换的功能列表。
此外,还有一些其他重要的变化:
不再有图像字体。这些是用于html-css输出jax的,而且由于mathjax版本3中没有包含这些内容,因此图像字体也不包含。由于它们占用了大量的磁盘空间,这应该会使本地托管的mathjax安装更小。
对于带有等式号的表达式,svg输出jax现在让这些表达式随着容器元素的大小浮动,就像在html输出中那样。在版本2中不是这样的,所以这是动态页面的一个重要改进。
用于不在mathjax使用的字体中的字符的字体过去由
undefinedFont
版本2中的配置参数,但在版本3中,您应该使用css来设置此参数。例如,mjx-container mjx-utext { font-family: my-favorite-font; } mjx-container svg text { font-family: my-favorite-font; }
将选择
my-favorite-font
用于未知字符。第一个声明用于commonhtml输出,第二个声明用于svg输出。一旦这种方法的优点是,您可以为每个变量分别指定css;例如,mjx-container mjx-utext[variant="sans-serif"] { font-family: my-sans-serif-font; } mjx-container svg text[data-variant="sans-serif"] { font-family: my-sans-serif-font; }
将设置字体以用于不在mathjax字体中且已请求sans-serif变量的字符。
版本3只实现commonhtml和svg输出jax。原始的html-css输出jax已被删除,a具有nativemml。PreviewHTML和Plainsource输出JAX尚未移植到版本3,不过如果有兴趣的话,它们可能会在将来移植。
不再适用于版本3
作为mathjax版本3重新设计的一部分,一些版本2特性已经被删除。下面将对其进行描述。
在版本3中,mathjax不再以小的“块”更新页面,而是作为一个整体更新页面(未来的版本可能包含一个以较小的块更新的扩展)。这会对版本2的许多功能产生影响。首先,由于没有增量更新,指示排版进度的mathjax消息栏(通常在左下角)不再需要,也不再是mathjax版本3的一部分。当然,控制它的配置选项也被删除,用于公式分块的选项也被删除(用于控制屏幕更新之间要处理多少个公式)。
同样,由于页面更新是一次完成的,所以不需要在排版公式时显示数学预览版本。所以 fast-preview 扩展和 PreviewHTML 输出jax和它们的配置选项已经被删除。
这个 PlainSource 输出jax尚未移植到版本3,尽管它可能在将来;它可以在版本3中以其他方式处理。如上所述, NativeMML 已从版本3中删除,但不难 implement a replacement 如果你愿意的话。
这个 autobold tex扩展在版本3中不再可用,将来也不太可能移植。
这个 mhchem 版本2中的tex扩展有两种形式:一种是与 Latex 实现不完全匹配的原始扩展,另一种是由原始 Latex 包的作者重写的,使其与 Latex 兼容。可以通过配置选项选择旧版本。这在版本3中不再可能(不再提供旧版本)。
这个 handle-floats HTML输出的扩展已经被删除,因为它的功能现在是标准CommonHTML输出的一部分。
这个 jsMath2jax 预处理器已被删除。这是用来帮助将jsmath用户连接到mathjax的,但是自从mathjax被引入已经十年了,此时对jsmath转换的需求应该非常小。
这个 MatchWebFonts 分机不再可用。HTML-CSS输出有时需要这样做,这取决于运行时字体的位置。CommonHTML输出不太容易受到字体问题的影响,因此不再需要这样做。
这个 FontWarnings 扩展不再可用,因为它是用于html-css输出jax的,它不是mathjax版本3的一部分。
这个 HelpDialog 版本3中不包含扩展名。其功能包含在 用户界面/菜单 直接。
这个 toMathML 版本3中不再提供扩展名。相反,你可以使用
MathJax.startup.toMML()
如果您使用的是mathjax组件,或者可以使用SerializedMMLVisitor
对象,如果直接调用mathjax模块。
配置块不再允许
style
版本2中提供的选项。相反,您应该直接使用css样式表和css样式文件。
版本2中与mathjax的同步是通过队列、信号和回调处理的。在版本3中,这些已经被es6承诺所取代。见 将代码与mathjax同步 了解更多详细信息。
尚未移植到版本3
由于mathjax 3仍在进行中,所以并不是所有的版本2特性都已经转换为新的代码库,尽管我们希望在将来的版本中将它们包含在版本3中。其中最重要的是以下几点。
目前,版本3中缺少自动换行支持。这是将来版本中要包含的一个关键特性。
mathjax v3输出jax目前只支持一种字体mathjax-tex字体。改进字体支持是版本3的一个重要目标,这是下一个需要解决的功能之一。我们将重新构建用于mathjax的字体,并在将来的版本中提供其他web字体。我们还计划将用于创建必要字体数据的工具用于移植您自己的字体以与mathjax一起使用。
版本2中提供的本地化机制尚未并入版本3,因此目前mathjax v3仅提供英语版本。这是一个重要的特性,将在未来的版本中添加到mathjax v3中。
这个 begingroup 和 mediawiki-texvc tex扩展还没有移植到版本3,但应该在将来。
这个 auto-collapse 版本3尚未提供辅助扩展。如果有足够的兴趣,它也将被移植到新的代码库中。
节点中的mathjax
mathjax的版本2是为在浏览器中工作而设计的,并且在很大程度上依赖于浏览器窗口、文档、dom和其他特定于浏览器的对象的存在。在版本2中,在服务器上使用mathjax预处理数学(例如,将tex字符串转换为svg图像)并不容易。这个 mathjax-node <https://github.com/mathjax/mathjax-node> 这个项目使得这成为可能,但是需要一种与mathjax完全不同的交互方式,并且不像我们希望的那样容易使用或可靠。
版本3将服务器端使用作为一个重要的用例来支持,因此可以在 node 应用程序与浏览器中的应用程序基本相同,只需对配置进行一些小的调整即可实现。这将使在服务器上使用mathjax更加容易,因为它在服务器上的工作方式与基于web的应用程序相同。也可以在较低的级别链接到mathjax并直接访问mathjax模块。请参阅 using MathJax in node 和 MathJax API 更多关于这些可能性的信息。
版本2兼容性示例
以下示例导致 \color
宏是版本2中的原始宏,并设置 \require
宏将旧包名转换为新包名。这将使mathjax v3能够正确地处理现有内容。
请确保通过 conversion tool 我们提供的。
<script>
MathJax = {
startup: {
//
// Mapping of old extension names to new ones
//
requireMap: {
AMSmath: 'ams',
AMSsymbols: 'ams',
AMScd: 'amscd',
HTML: 'html',
noErrors: 'noerrors',
noUndefined: 'noundefined'
},
ready: function () {
//
// Replace the require command map with a new one that checks for
// renamed extensions and converts them to the new names.
//
var CommandMap = MathJax._.input.tex.SymbolMap.CommandMap;
var requireMap = MathJax.config.startup.requireMap;
var RequireLoad = MathJax._.input.tex.require.RequireConfiguration.RequireLoad;
var RequireMethods = {
Require: function (parser, name) {
var required = parser.GetArgument(name);
if (required.match(/[^_a-zA-Z0-9]/) || required === '') {
throw new TexError('BadPackageName', 'Argument for %1 is not a valid package name', name);
}
if (requireMap.hasOwnProperty(required)) {
required = requireMap[required];
}
RequireLoad(parser, required);
}
};
new CommandMap('require', {require: 'Require'}, RequireMethods);
//
// Do the usual startup
//
return MathJax.startup.defaultReady();
}
},
tex: {
autoload: {
color: [], // don't autoload the color extension
colorv2: ['color'], // do autoload the colorv2 extension
}
}
};
</script>
<script id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
这使用了 tex-chtml.js
组合组件,因此将其更改为所需的任何组件。
如果您的网站使用mathjax api通过
MathJax.Hub.Queue(['Typeset', MathJax.Hub]);
例如,需要转换这些调用才能使用 MathJax 3 API . 您可以使用以下代码来修补mathjax版本3,该版本为 MathJax.Hub.Typeset()
和 MathJax.Hub.Queue()
. 它还标记了 MathJax.Hub.Register.StartupHook()
以及其他钩子注册命令,并且您已经转换了 MathJax.Hub.Config()
和 x-mathjax-config
scripts to their version 3 counterparts (use the conversion tool )
在 new CommandMap()
调用上面的代码:
//
// Add a replacement for MathJax.Callback command
//
MathJax.Callback = function (args) {
if (Array.isArray(args)) {
if (args.length === 1 && typeof(args[0]) === 'function') {
return args[0];
} else if (typeof(args[0]) === 'string' && args[1] instanceof Object &&
typeof(args[1][args[0]]) === 'function') {
return Function.bind.apply(args[1][args[0]], args.slice(1));
} else if (typeof(args[0]) === 'function') {
return Function.bind.apply(args[0], [window].concat(args.slice(1)));
} else if (typeof(args[1]) === 'function') {
return Function.bind.apply(args[1], [args[0]].concat(args.slice(2)));
}
} else if (typeof(args) === 'function') {
return args;
}
throw Error("Can't make callback from given data");
};
//
// Add a replacement for MathJax.Hub commands
//
MathJax.Hub = {
Queue: function () {
for (var i = 0, m = arguments.length; i < m; i++) {
var fn = MathJax.Callback(arguments[i]);
MathJax.startup.promise = MathJax.startup.promise.then(fn);
}
return MathJax.startup.promise;
},
Typeset: function (elements, callback) {
var promise = MathJax.typesetPromise(elements);
if (callback) {
promise = promise.then(callback);
}
return promise;
},
Register: {
MessageHook: function () {console.log('MessageHooks are not supported in version 3')},
StartupHook: function () {console.log('StartupHooks are not supported in version 3')},
LoadHook: function () {console.log('LoadHooks are not supported in version 3')}
},
Config: function () {console.log('MathJax configurations should be converted for version 3')}
};
//
// Warn about x-mathjax-config scripts
//
if (document.querySelector('script[type="text/x-mathjax-config"]')) {
throw Error('x-mathjax-config scripts should be converted to MathJax global variable');
}
这样,您就可以使用现有的版本2代码与版本3进行交互。但如果没有,要么需要一个更复杂的兼容模块,要么更好的是,转换成新的3版api。