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" |
转义符号
输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | # | \# | $ | \$ | @ | \@ | _ | \_ |
字体大小
输出 | 源码 | 输出 | 源码 | text | tiny "text" | text | small "text" |
text | large "text" | text | huge "text" |
语法糖
输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 输出 | 源码 | 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 |