MathJaxSwift

MathJax Version Unit Tests

Powered by MathJax

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。 有关更多详细信息,请参见示例部分。

Hello, Tex!

🧰 可用方法

MathJaxSwift 实现了以下方法来将 TeXMathMLAsciiMath 转换为 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 输入的方法有关。 它们使您可以设置输入转换选项,例如 emex 大小,容器和行宽以及 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 转换方法,则可以分别使用 TexInputProcessorOptionsSVGOutputProcessorOptions 配置输入和输出。

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 版本

要检查已加载的 MathJax 的版本,请使用静态 metadata() throws 方法。

do {
  let metadata = try MathJax.metadata()
  print(metadata.version)
}
catch {
  print("Error getting MathJax version: \(error)") 
}

您还可以使用返回的元数据来检查 MathJax 节点模块的 URL 及其 SHA-512。

📗 示例

以下示例类展示了如何

  1. 创建一个 MathJax 实例,
  2. 将首选输出设置为 SVG
  3. 创建输入,输出和转换选项,
  4. 并从 TeX 输入中渲染 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.jsmml.bundle.jssvg.bundle.js 文件由 Swift 软件包的模块加载,并由 JavaScript 上下文评估以公开函数。

index.js 进行修改后,应在 mjn 目录中执行 npm run build 进行重建,这将重新创建捆绑文件。

脚注

  1. MathJaxSwift 不隶属于 MathJax 或其任何相关实体。