Asciimath 是什么?
一种 JavaScript 实现的简易的数学公式标记语言,相比 LATEX 更加易学易用。
如何使用
API
你可以使用 asciimath-parser 或者 asciimath-parser-nearley,如果想要使用前者,阅读本文档即可,而如果是后者,可能存在一些区别,请参照其 README.
基本使用
使用 npm/yarn/pnpm 包管理工具安装。
pnpm i -D asciimath-parser
引入 AsciiMath,创建实例,使用 toTex 方法来生成 LaTeX 代码。
import { AsciiMath } from 'asciimath-parser'
const am = new AsciiMath()
console.log(am.toTex('sum_(n=1)^(+oo)1/n^2=pi^2/6'))
// \displaystyle{ \sum _{ n = 1 } ^{ + \infty } \frac{ 1 }{ n ^{ 2 } } = \frac{ \pi ^{ 2 } }{ 6 } }
配置参数与扩展语法
以下为 AsciiMath 在构造时接受的参数类型
type ReplaceLaw = [RegExp | string, string | ((substring: string, ...args: any[]) => string)]
interface AsciiMathConfig {
display?: boolean
replaceBeforeTokenizing?: ReplaceLaw[]
symbols?: Array<[string, SymbolValueType]> | Record<string, SymbolValueType>
}
display
指定生成的公式是否被包含在 \displaystyle 环境下,默认值为 true
replaceBeforeTokenizing
在公式被处理之前,将匹配到的字符串替换为目标串,然后再传入 AsciiMath 处理
点击查看详情
例如这样指定它
const cfg: AsciiMathConfig = {
replaceBeforeTokenizing: [
[/d0/g, '{:"d"theta:}'],
[/x(\d+)/g, (_, $1) => `x^(${$1})`],
]
}
const am = new AsciiMath(cfg) // 实例化
console.log(am.toTex('...'))
那么,在公式被解析之前,会先进行如下操作
- 将字符串
d0 转换为 {:"d"theta:},然后 AsciiMath 将 {:"d"theta:} 处理为 { \text{d} \theta }
- 将类似
x2, x10 转换为 x^(2) 以及 x^(10),然后 AsciiMath 再将其分别转换为 x^{ 2 } 和 x^{ 10 }
symbols
指定扩展的 TokenType,所有的 Token 类型可参考 symbols.ts,但是不建议随意扩展 Token。下面列出建议扩展的类型:
enum TokenTypes {
Const, // 将匹配到的字符串翻译为目标 tex 代码
OperatorOA, // 带有一个参数的操作符,例如绝对值 `abs(a)`
OperatorOAB, // 带有两个参数的操作符,例如分数 `frac(a)(b)`
OperatorAOB, // 中缀操作符,例如除法 `a / b`
OperatorAO, // 后缀操作符,例如阶乘 `!`
}
点击查看详情
例如,指定 symbols 的值为
const cfg: AsciiMathConfig = {
symbols: {
dx: { type: TokenTypes.Const, tex: '{\\mathrm{d}x}' },
rm: { type: TokenTypes.OperatorOA, tex: '\\mathrm{$1}', eatNext: true },
frac: { type: TokenTypes.OperatorOAB, tex: '\\frac{ $1 }{ $2 }' },
over: { type: TokenTypes.OperatorAOB, tex: '{ $1 \\over $2 }' },
}
}
const am = new AsciiMath(cfg) // 实例化
console.log(am.toTex('...'))
那么 dx, rm, frac, over 将会成为对应的 Token 被识别,最终会达到下面的效果
-
dx 生成的代码就是 {\mathrm{d}x}
-
rm(absc) 生成的代码为 \mathrm{absc},其中 absc 即为 rm 这个操作符的参数,$1 将会被 absc 替换
其中 eatNext 的作用是,直接将下一个单词读取为字符串,而不识别其中的任何 token.
上面的例子中,absc 包含的关键字 abs,但是程序并不会将它读取为 abs 和 c,而将它直接处理为 absc 字符串,并用它替换掉模板中的 $1.
如果不设置 eatNext 为 true,那么得到的结果就是 \mathrm{ \left|c\right| }.
如果你想要读取更长的字符串,可以用双引号或者圆括号来包裹这个串,例如 rm "here is a mathrm block".
eatNext 参数只建议与 OperatorOA 和 OperatorOAB 两种类型一起使用.
-
frac(m)(n) 生成的代码为 \frac{ m }{ n },$1 和 $2 会分别被 m 和 n 替换
-
a over b 生成的代码为 { a \over b },$1 和 $2 会分别被 a 和 b 替换
Cli
使用包管理工具安装,可以使用全局安装或本工作环境安装。
pnpm add -g asciimath-parser-cli
输入一个文件,将所有被 反引号 ` 包裹的公式都转换为被 美元符 $ 包裹的 LaTeX 公式。
am-parse input.txt
# 将会生成 input_parsed_xxx.tex
使用场景
注意
- 这个库是由我个人重构的,一些语法可能与 asciimath.org 原版不同,尤其是矩阵,使用时请格外注意。
- Asciimath parser 只是简单的将输入的公式转换为 LaTeX 代码,并不依赖于 DOM 和 mathml,如果你需要可视化呈现这些公式,请与 KaTeX 或 mathjax 等这些工具一起使用。
特别感谢
zmx0142857 的笔记以及他的帮助。
遇到问题
请至 GitHub issue 提供能够稳定复现的情况并给出适当的报错信息。
样例
| 主题 | 输出 | 源码 |
| 上下标 | a12+b12=c12 | a_1^2 + b_1^2 = c_1^2 |
| 文本 | hello world | "hello world" |
| 分式 | ba,a/b | a/b, a//b |
| 根式 | n,nx,ba2 | sqrt n, root n x, a^2/sqrt b |
| 极限 | n→∞lim(1+n1)n | lim_(n->oo) (1+1/n)^n |
| 积分 | ∫abf(x)dx | int_a^b f(x) dx |
| 隐形括号 | sin2x | sin {: x/2 :} |
| 微分 | dxdy,dθdr,f′′(x) | dy/dx, ("d"r)/("d"theta), f''(x) |
| 微分(实验性) | dxdf,dx2d2f,x¨ | ddfx , dd^2 f x , ddot x |
| 偏微分 | ∂x∂f,∂x∂y2∂3f | (del f)/(del x), (del^3 f)/(del x del y^2) |
| 偏微分(实验性) | ∂x∂f,∂x∂y2∂3f,∂x∂ | ppfx, pp^3 f (x y^2), pp {::} x |
| 矩阵 | [acbd],[adbecf] | [a, b; c, d], [a, b | c; d, e | f] |
| 分段函数 | ∣x∣={x−xifx>0otherwise | |x| = { x, if x > 0; -x, otherwise :} |
符号对照手册
希腊字母
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| α | alpha | β | beta | χ | chi | δ | delta |
| Δ | Delta | ε | epsi | ϵ | epsilon | η | eta |
| γ | gamma | Γ | Gamma | ι | iota | κ | kappa |
| λ | lambda | Λ | Lambda | μ | mu | ν | nu |
| ω | omega | Ω | Omega | ϕ | phi | φ | varphi |
| Φ | Phi | Φ | varPhi | π | pi | Π | Pi |
| ψ | psi | Ψ | Psi | ρ | rho | σ | sigma |
| Σ | Sigma | τ | tau | θ | theta | ϑ | vartheta |
| Θ | Theta | υ | upsilon | ξ | xi | Ξ | Xi |
| ζ | zeta |
括号
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| ( | ( | ) | ) | | {: | . | :} |
| [ | [ | ] | ] | { | { | } | } |
| ⟨ | (: | ⟩ | :) | ⌊ | |__ | ⌋ | __| |
| ⌈ | |~ | ⌉ | ~| | ∣ | | | ∣x∣ | abs(x) |
| ∥v∥ | norm(bb(v)) | ⌊2x⌋ | floor(x/2) | ⌈3x⌉ | ceil(x/3) |
算数运算符
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| + | + | − | - | ⋅ | * | ∗ | ** |
| / | // | \ | \\ | × | xx | ÷ | -: |
| ∘ | @ | ⊕ | o+ | ⊗ | ox | ⊙ | o. |
| ∑ | sum | ∏ | prod | ∧ | ^^ | ⋀ | ^^^ |
| ∨ | vv | ⋁ | vvv | ∩ | nn | ⋂ | nnn |
| ∪ | uu | ⋃ | uuu | % | % |
关系运算符
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| = | = | = | != | ≡ | -= | ≡ | !-= |
| ≅ | ~= | ≈ | ~~ | < | lt | > | gt |
| ≥ | ge | ≤ | le | ⩽ | <= | ⩾ | >= |
| ≺ | -< | ≻ | >- | ∈ | in | ∈/ | !in |
| ⊂ | sub | ⊃ | sup | ⊆ | sube | ⊇ | supe |
| ⊆ | !sube | ⫋ | subne | ⊴ | normal | ⊵ | rnormal |
| ⊲ | lhd | ⊳ | rhd | ∽ | S~ | ∝ | prop |
| ∁ | complement |
逻辑运算符
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| and | and | or | or | ¬ | not | ⇒ | rArr |
| if | if | ⟺ | iff | ∀ | AA | ∃ | EE |
| ⊥ | _|_ | ⊤ | TT | ⊢ | |-- | ⊨ | |== |
杂项
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| ∫ | int | ∬ | iint | ∭ | iiint | ∮ | oint |
| ∂ | del | ∇ | grad | ± | +- | ∅ | O/ |
| ∞ | oo | ℵ | aleph | ∠ | /_ | ∴ | :. |
| ∵ | :' | … | ... | ⋯ | cdots | ⋮ | vdots |
| ⋱ | ddots | □ | square | N | NN | Q | QQ |
| R | RR | C | CC | Z | ZZ | (kN) | N choose k |
数学函数
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| sin | sin | cos | cos | tan | tan | cot | cot |
| sec | sec | csc | csc | sinh | sinh | cosh | cosh |
| tanh | tanh | coth | coth | csch | csch | sech | sech |
| arcsin | arcsin | arccos | arccos | arctan | arctan | log | log |
| ln | ln | det | det | dim | dim | lim | lim |
| mod | mod | gcd | gcd | lcm | lcm | min | min |
| max | max | sgn | sgn | sup | Sup | inf | inf |
| exp | exp |
箭头
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| ↑ | uarr | ↓ | darr | → | rarr | ← | larr |
| → | -> | ↦ | |-> | ↔ | harr | ⇒ | rArr |
| ⇐ | lArr | ⇔ | hArr | ↠ | ->> | ↣ | >-> |
| ↶ | curvArrLt | ↷ | curvArrRt | ↺ | circArrLt | ↻ | circArrRt |
| ⇝ | ~> | ↛ | -/-> | ↚ | <-/- | ↮ | <-/-> |
字体
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| A | bb A | A | bm A | A | bbb A | A | cc A |
| A | tt A | A | fr A | A | sf A | A | scr A |
注音符号
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| x^ | hat x | xˉ | bar x | x | ul x | x | vec x |
| x˙ | dot x | x¨ | ddot x | x⌢ | arc x | x~ | tilde x |
| AB | Vec(AB) | AB | Hat(AB) | AB | Tilde(AB) |
上下叠合
| 输出 | 源码 | 输出 | 源码 |
| xbala | overset("bala")(x) | 12345n | overbrace(12345)^n |
| n12345 | underbrace(12345)_n | 456123 | ==_(123)^(456) |
| ba | -->_(a)^(b) | ba | a atop b |
特殊
| 输出 | 源码 | 输出 | 源码 |
| I’m here | text(I'm here) | ℏ | tex"\hbar" |
| abc | color(red)(abc) | hello world | "hello world" |
| arg | arg | Arg | Arg |
| cyc | cyc |
转义符号
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| # | \# | $ | \$ | @ | \@ | _ | \_ |
字体大小
| 输出 | 源码 | 输出 | 源码 |
| text | tiny "text" | text | small "text" |
| text | large "text" | text | huge "text" |
化学
在 LaTeX 中加载 mchm 和 chemfig 包,以使用 ce"H2SO4" 等化学符号
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| Ksp | Ksp | Ka1 | Ka1 | Ka2 | Ka2 | Ka3 | Ka3 |
| Ka | Ka | Kb | Kb | Kh1 | Kh1 | Kh2 | Kh2 |
| Kh3 | Kh3 | Kh | Kh | Kw | Kw | pH | pH |
| pOH | pOH |
语法糖
| 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 |
| dx | dx | dy | dy | dz | dz | dt | dt |
使用 # 来插入 displaystyle
| 输出 | 源码 |
| ∂x2∂2f∂y∂x∂2f∂x∂y∂2f∂y2∂2f | [#part^2 f x, part^2 f (x y); part^2 f (y x), #part^2 f y] |
使用 aligned 环境
f(x) & = x "e"^x
<-- 一个空行
f'(x) & = (x + 1) "e"^x
<-- 一个空行
f''(x) & = (x + 2) "e"^x
f(x)f′(x)f′′(x)=xex=(x+1)ex=(x+2)ex 注意 & 相当于 LaTeX 中的 &,而上述的空行相当于 LaTeX 中的 \\ 换行
空白
| 输出 | 源码 | 宽度 |
| ab | a quad b | 1 em |
| ab | a qquad b | 2 em |
| ab | a enspace b | 0.5 em |
| ab | a \; b | 5/18 em |
| ab | a \: b | 4/18 em |
| ab | a \, b | 3/18 em |
| ab | a \! b | -3/18 em |
| ab | a hspace(12pt) b | 12 pt |