Universe

Typst Packages for easy and extensible chemical formula formatting. This provide a ch function for writing chemical notations. Chemformula uses Typst’s math mode to evaluate the input string (or raw) in the ch function and render them into the document.

Import this pacakge by

#import "@preview/chemformula:0.1.3": ch

Examples

Chemical Formulae

The number preceding by other letters is subscripted by default.

#ch("H2O")

#ch("Sb2O3")
simple molecule typesetting

Chemical Equations

You can use -> to draw arrow. The length will changes according to the content being above or below the arrow. The arrow is rendered using Typst’s stretch function.

#ch("CO2 + C -> 2 CO")

// Multilines are allowed!
#ch("Hg^2+ ->[I^-] HgI2
           ->[I^-] [Hg^II I4]^2- ")
writing reactions can be done by typing an arrow.

Charges

Plus and minus signs coming after the text are superscript positioned by default. However, you may use ^ operator to raise them upper. The ^ operator will superscript the content until a space or a semicolon (;) is typed.

#ch("H+")

#ch("CrO4^2-") // or 
#ch("CrO4 ^2-") // IUPAC recommended

#ch("[AgCl2]-")

#ch("Y^99+") // or
#ch("Y^(99+)") // Same
charges can be typed by plus, minus, or superscripted by a caret.

Oxidation States

Typing ^^ gives the ability to put things above the elements. This operator captures content in parenthesis/or until black space is met.

#ch("Fe^^II Fe^^III_2 O4") // or 
#ch("Fe^^(II)Fe^^(III)_(2)O4") // Same
above text can be written by using double carets

Stoichiometric Numbers

Since the content is evaluated in math mode, the fractions are rendered by default. If one space is present between the compound and digits, then thin space is used. If more than one spaces are typed, then full one normal space will be used.

#ch("2H2O") // Tight 

#ch("2 H2O") // Spaced 

#ch("2  H2O") // Very Spaced 

#ch("1/2 H2O") // Automatic Fractions 

#ch("1\/2 H2O") // 
stoichiometry typing

Nuclides, Isotopes

The syntax writing nuclides is preceding the ^ for mass number or _ for atomic number with space/or begining of the string. Otherwise, the operator will attach to the preceding content.

#ch("^227_90 Th+")

#ch("^227_(90)Th+")

#ch("^0_-1 n-")

#ch("_-1^0 n-")
how to type nuclides is trivial

Parenthesis, Braces, Brackets

In Typst, parentheses are automatically sized by default. If you finding this ugly, you can disrupt them by typing \ before the parentheses group. To force a group of parenthesis between substances to big-size, wrap the whole reaction with display function.

#ch("(NH4)2S") // Automatic sizing 

#ch("[{(X2)3}2]^3+") 

#ch("\[{(X2)3}2]^3+") // To disable this behavior, just type `\`

$display(ch("CH4 + 2(O2 + 7/2N2)"))$ // Hack with math mode
escaping parenthesis not to be auto sized

States of Aggregation

Normally, lower case letters are considered math variables, and multiple form of them will be symbol/variable call. This follows the Typst’s naive math syntax. However, (aq) is preserved by the parser as math variable that evaluates to "aq".

#ch("H2(g)")

#ch("CO3^2-_((aq))")

#ch("NaOH(aq, $oo$)")

#ch("NaHCO3(s)")
states of matter can be typed directly.

You can use $..$ syntax for escaping the parser so that the content inside will be directly evaluated by math mode.

Radical Dots

* or . in superscript and subscript mode will be used as radical notation. This uses sym.bullet to display.

#ch("OCO^*-")

#ch("NO^((2*)-)")
radical can be typed by using an asterisk or a dot.

Escaped Modes

Contents inside $..$ will be escaped by the parser and evaluated in math mode directly bypassing other grammars. So you can type greek letters or other variables in math in this mode, for example.

// Use Math Mode!
#ch("NO_x") is the same as #ch("NO_$x$")

#ch("Fe^n+") is the same as #ch("Fe^$n+$")

#ch("Fe(CN)_$6/2$") // Fractions!

#ch("$#[*CO*]$_2^3") // bold text 

// Or just type texts...
#ch("mu\"-\"Cl") // Hyphen Escaped
escaping the parser can be done by using double quotes or dollar signs

Reaction Arrows

#ch("A -> B")

#ch("A <- B")

#ch("A <-> B")

#ch("A <=> B")
there are multiple supported reaction arrows

Above/Below Arrow Text

#ch("A ->[Delta] B")

#ch("A <=>[Above][Below] B")

#ch("CH3COOH <=>[+ OH-][+ H+] CH3COO-")
above and below text on an arrow can be typed next to the arrow.

Precipitation and Gas

This feature has very dedicate syntax: the ^ or v must precede -and- folows by white space.

#ch("SO4^2- + Ba^2+ -> BaSO4 v")

#ch("A v B v -> B ^ B ^")
precipitation and gas are also supported by typing a v or a caret character.

Alignments

$ ch("A &-> B") \
  ch("B &-> C + D")
$
Equation alignments are trivially supported

Bonds

You can use a double dash --, to indicate single bond, double equal sign == for double bonds, and double tilde ~~ for triple bonds.

#ch("CH3--CH2--O-Na+")

#ch("CH3C==CH--CH3")

#ch("HC~~CH")
Double bonds uses double equal signs, single bond uses double dashes, and triple bond uses double tilde.

The styling of the bonds can be set by using the following keys:

  bond-length: 1em,
  bond-sep: 0.3em,
  bond-baseline: 0.15em,
  bond-stroke: 1pt,
  bond-styles: (:),
  bond-inset: 0.1em,

in the argument of ch function. For example,

#ch("CH3--CH2", bond-stroke: 3pt + red)

#ch("O==C(CH3)3", bond-sep: 5pt,)

#ch("O==C(CH3)3", bond-sep: 2pt,)
Stying bonds by bond- as prefix

More Examples

Integration seamlessly with Typst’s math mode.

$  
  ch("Zn^2+ <=>[+ 2 OH-][+ 2 H+]")
  limits(ch("Zn(OH)2 v"))_"amphoteres Hydroxid"
  ch("<=>[+ 2 OH-][+ 2H+]")
  limits(ch("[Zn(OH)4]^2-"))_"Hydroxozikat"
$
advanced example 1, typing reactions with multiple charges and names

You can use user-defined functions in ch. However, you must add the definition of this function into the scope parameter of ch.

#let tg = text.with(fill: olive)
#let ch = ch.with(scope: (tg: tg, ch: ch))
$ ch("Cu^^II Cl2 + K2CO3 -> tg(Cu^^II)CO3 v + 2 KCl") $

$ ch("Hg^2+ ->[I-] HgI2
            ->[I-] [Hg^II I4]^2-
") $
advance example 2, typing multiple reactions at once and coloring

This packages’ examples and syntax are highly inspired by mhchem package. Please feel free to give any suggestions for improving the feature of this package!