MathJaxSwift
通过整合 MathJax1 源代码并使用 JavaScriptCore 框架,在 Swift 中转换和渲染数学表达式。它将 MathJax 的转换过程封装在便捷的 JavaScript 方法中,此处有描述,并将其暴露给 Swift,无需使用 WebKit
。
将依赖项添加到你的包清单文件中。
.package(url: "https://github.com/colinc86/MathJaxSwift", from: "3.4.0")
导入包,创建一个 MathJax
实例,并将输入字符串转换为支持的输出格式。
import MathJaxSwift
do {
let mathjax = try MathJax()
let svg = try mathjax.tex2svg("\\text{Hello}, \\TeX{}!")
}
catch {
print("MathJax error: \(error)")
}
上面的例子将 TeX 输入转换为 SVG 数据,该数据渲染出以下 PNG。 有关更多详细信息,请参见示例部分。
![]()
MathJaxSwift 实现了以下方法来将 TeX,MathML 和 AsciiMath 转换为 CommonHTML,MathML 和 SVG 数据。
方法 | 输入格式 | 输出格式 |
---|---|---|
tex2chtml |
TeX | cHTML |
tex2mml |
TeX | MathML |
tex2svg |
TeX | SVG |
mml2chtml |
MathML | cHTML |
mml2svg |
MathML | SVG |
am2chtml |
AsciiMath | cHTML |
am2mml |
AsciiMath | MathML |
不应在主队列上执行 MathJax
实例的初始化,以防止 UI 阻塞。 您还应尝试保持对实例的单个引用,并将函数调用提交给该实例,而不是每次需要转换时都创建一个新的 MathJax
实例。
import MathJaxSwift
class MyModel {
let mathjax: MathJax
init() throws {
mathjax = try MathJax()
}
func convertTex(_ input: String) throws -> String {
return try mathjax.tex2chtml(input)
}
}
您可以提交多个输入字符串进行转换。
do {
// Some input array of TeX strings
let input: [String] = [ ... ]
// Convert each string in the input array
let responses = try mathjax.tex2svg(input)
for response in responses {
if let error = response.error {
print("Error converting input value: \(error)")
}
else {
print("Got response value: \(response.value)")
}
}
}
catch {
print("MathJax error: \(error)")
}
MathJax
实例将返回一个 Response
类型的数组,其中错误从响应的 value
中解析出来,并设置在 error
属性上。
每个方法也都有一个 async
实现。
func myAsyncMethod() async throws {
let mml = try await mathjax.tex2mml("\\frac{2}{3}")
print(mml)
}
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mfrac>
<mn>2</mn>
<mn>3</mn>
</mfrac>
</math>
调用异步方法时,可以指定在其上执行的队列。 默认情况下,实例将使用 .global()
队列。
func myAsyncMethod() async throws {
let mml = try await mathjax.tex2mml("\\frac{2}{3}", queue: myQueue)
}
MathJaxSwift 将所有必要的 JavaScript 加载到其上下文中,以运行所有转换方法。 如果您只想利用该软件包输出格式的子集,则可以指示 MathJax
实例仅使用您的首选输出格式进行初始化。
do {
// Save some time and don't load the SVG output format.
let mathjax = try MathJax(preferredOutputFormats: [.chtml, .mml])
}
catch {
print("Error initializing MathJax: \(error)")
}
这种方法的好处是,它不是在初始化时将所有必要的 JavaScript 加载到实例的上下文中,而是立即加载首选的输出格式,然后在将来延迟加载可能需要执行转换方法的任何 JavaScript。
do {
// We _think_ we only need CommonHTML, so save some time by only loading that
// output format.
let mathjax = try MathJax(preferredOutputFormat: .chtml)
// It's ok to call `tex2mml` even though we set our preferred output format to
// `chtml`!
let mml = try mathjax.tex2mml("\\text{Hello}, \\TeX{}!")
}
catch {
print("MathJax error: \(error)")
}
有关更多详细信息,请参见注意事项部分。
文档选项使您可以控制 MathJax 创建的文档。 它们适用于每种转换方法,并允许您指定 MathJax 文档特定的选项。
// Add to the `skipHtmlTags` array.
var docOptions = DocumentOptions()
docOptions.skipHtmlTags.append("example")
// Process the input using the new options
let output = try! tex2chtml("\\text{Hello, }$\\LaTeX$\\text{!}", documentOptions: docOptions)
这些选项与文档选项一样,适用于每种转换方法。 但是,选项的 display
属性仅与采用 TeX 输入的方法有关。 它们使您可以设置输入转换选项,例如 em
和 ex
大小,容器和行宽以及 scale
。
// Process the TeX input as a block instead of inline
let convOptions = ConversionOptions(display: true)
let output = try! tex2chtml("\\text{Hello, }$\\LaTeX$\\text{!}", conversionOptions: convOptions)
可以通过各种处理器选项配置每种转换方法的输入和输出。 例如,如果您正在调用 tex2svg
转换方法,则可以分别使用 TexInputProcessorOptions
和 SVGOutputProcessorOptions
配置输入和输出。
let inputOptions = TexInputProcessorOptions(processEscapes: true)
let outputOptions = SVGOutputProcessorOptions(displayIndent: 0.5)
let svg = try! mathjax.tex2svg("\\text{Hello, }\\LaTeX\\text{!}", inputOptions: inputOptions, outputOptions: outputOptions)
每种转换方法都是抛出方法,但是您也可以使用选项从 MathJax 捕获错误。
let documentOptions = DocumentOptions { doc, math, err in
// Do something with the compile error...
}, typesetError: { doc, math, err in
// Do something with the typeset error...
}
let inputOptions = TexInputProcessorOptions { jax, err in
// Do something with the TeX format error...
}
要检查已加载的 MathJax 的版本,请使用静态 metadata() throws
方法。
do {
let metadata = try MathJax.metadata()
print(metadata.version)
}
catch {
print("Error getting MathJax version: \(error)")
}
您还可以使用返回的元数据来检查 MathJax 节点模块的 URL 及其 SHA-512。
以下示例类展示了如何
MathJax
实例,SVG
,class EquationRenderer {
// A reference to our MathJax instance
private var mathjax: MathJax
// The TeX input processor options - load all packages.
private let inputOptions = TeXInputProcessorOptions(loadPackages: TeXInputProcessorOptions.Packages.all)
// The SVG output processor options - align our display left.
private let outputOptions = SVGOutputProcessorOptions(displayAlign: SVGOutputProcessorOptions.DisplayAlignments.left)
// The conversion options - use block rendering.
private let convOptions = ConversionOptions(display: true)
init() throws {
// We only want to convert to SVG
mathjax = try MathJax(preferredOutputFormat: .svg)
}
/// Converts the TeX input to SVG.
///
/// - Parameter texInput: The input string.
/// - Returns: SVG file data.
func convert(_ texInput: String) async throws -> String {
return try await mathjax.tex2svg(
texInput,
conversionOptions: convOptions,
inputOptions: inputOptions,
outputOptions: outputOptions)
}
}
要使用该类,您可以执行以下操作:
let renderer = try EquationRenderer()
let svg = try await renderer.convert("$\\text{Hello, }\\TeX$!")
该软件包独有的类(即 MathJax
)应得到充分记录。 不包含有关 MathJax 选项和转换过程的文档。
请参阅官方 MathJax 文档 以获取更多信息。
为了解决 JSContext
类的局限性,该软件包使用 Webpack 创建可由上下文评估的捆绑文件。 包装器方法,MathJax 和 Webpack 依赖项捆绑在一个名为 mjn
的 npm 模块中。
mjn
的主要入口点是 index.js
,它公开了利用 MathJax 的转换器类和函数。 这些文件与 Webpack 打包在一起,并放置在 mjn/dist/
目录中。 chtml.bundle.js
,mml.bundle.js
和 svg.bundle.js
文件由 Swift 软件包的模块加载,并由 JavaScript 上下文评估以公开函数。
对 index.js
进行修改后,应在 mjn
目录中执行 npm run build
进行重建,这将重新创建捆绑文件。