Skip to the text

Docs Reference

Rules

The engine has 33 rules, 22 on by default (the rest are off until named in enable). typographic runs them in the order below, each on the output of the one before. An id can be switched off with disable (see api.md); a group name switches off every rule that starts with it (space is every space.* rule, dash every dash.*, symbol every symbol.*).

This file is generated by bun run docs:rules from RULES in src/core/rules.ts and from the examples in scripts/gen-rules-doc.ts. Do not edit it by hand: src/docs.test.ts fails when it is out of date.

Each example runs the engine with every rule except the one shown switched off, so it shows what that rule does and nothing else. In a full run the other rules also act (an English " is turned into a quote by quote before anything else sees it). The text of each example is plain; a no-break space is shown as ~ (the character U+00A0 in the real output; an ordinary space stays a space). Text in a code span, a web address and an email are never changed by any rule.

Categories

Each rule has a category that says what it is for; the id names the mechanism and is what disable and enable take. A category is a label only: it is not a group name for disable.

Order

# Rule Category Default
1 quote tradition on
2 apostrophe tradition on
3 ellipsis tradition on
4 space.before-punctuation tradition off
5 space.after-comma tradition off
6 punctuation.double tradition off
7 arrow symbols on
8 symbol.implies math off
9 symbol.legal symbols on
10 dash.dialogue tradition on
11 phone.bind data off
12 number.group data off
13 dash.range data on
14 dash.sentence tradition on
15 symbol.plusminus math off
16 symbol.minus math on
17 symbol.multiply math on
18 symbol.fraction math off
19 space.collapse tradition on
20 space.title tradition on
21 space.initial tradition on
22 space.abbreviation tradition on
23 space.number data on
24 space.percent data on
25 symbol.degree data off
26 space.section symbols on
27 space.association tradition on
28 space.copyright symbols on
29 space.operator symbols on
30 space.short-word tradition off
31 space.orphan tradition on
32 space.arrow symbols on
33 space.trailing tradition off

quote

Quotation marks by language, register and nesting level, from any source style

Category: tradition.

Why: sources.md, disputed.

Characters it can insert, in any language: « » „ “ ‚ ‘ ’ ” › ‹ ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
He said "stone" and left.
After
He said «stone» and left.

Display register, the default.

en
Before
He said "we said 'no' twice" and left.
After
He said «we said „no“ twice» and left.

Nesting level two. Source marks may be straight, curly or guillemets.

en, literary
Before
He said "we said 'no' twice" and left.
After
He said ‘we said “no” twice’ and left.

British English in the literary register.

de
Before
Er sagte "Sie rief 'Haus' laut" und ging.
After
Er sagte »Sie rief ›Haus‹ laut« und ging.

apostrophe

A straight ' in a word or before a year becomes ’

Category: tradition.

Why: sources.md, verified.

Characters it can insert, in any language: ’. A font that lacks one of them is handled by avoid (see api.md).

en
Before
It's Maria's turn, don't wait.
After
It’s Maria’s turn, don’t wait.

Inside a word.

en
Before
The '90s were loud.
After
The ’90s were loud.

Before a year.

ellipsis

… becomes …

Category: tradition.

Why: sources.md, verified.

Characters it can insert, in any language: …. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Wait... what?
After
Wait… what?
en, avoid …
Before
Wait... what?
After
Wait... what?

With the ellipsis in avoid (a font that cannot draw it), the text stays as typed.

space.before-punctuation

Removes a space before , . ; : ! ? ) (French keeps the space before : ; ! ?)

Category: tradition.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

en
Before
Hello , world . Is it ready ? (yes )
After
Hello, world. Is it ready? (yes)

Off by default.

fr
Before
Oui : non , bon !
After
Oui : non, bon !

French keeps its space before : ; ! ?, the rest is tidied.

space.after-comma

A comma followed directly by a letter gets a space (a,b becomes a, b)

Category: tradition.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

en
Before
apples,pears,plums
After
apples, pears, plums

Digits are left alone: 1,5 stays.

de
Before
Hallo,Welt und 3,14
After
Hallo, Welt und 3,14

punctuation.double

A run of ! or ? becomes one mark (Wow!!! becomes Wow!); ?! and !? stay

Category: tradition.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

en
Before
Wow!!! Really??
After
Wow! Really?
en
Before
What?!! No!!!? Stop!!!
After
What?!! No!? Stop!

?! and !? stay as a pair; a run beside one collapses.

arrow

→ and ← become → and ←

Category: symbols.

Why: sources.md, general-knowledge.

Characters it can insert, in any language: → ←. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Read more ->
After
Read more →
en
Before
<- Back
After
← Back

symbol.implies

=> becomes ⇒

Category: math.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

Characters it can insert, in any language: ⇒. A font that lacks one of them is handled by avoid (see api.md).

en
Before
A => B
After
A ⇒ B
en
Before
if x=>y then z
After
if x⇒y then z

Not =>>, ==>, =>= or <=>.

(c) before a year, ©, ® and ™ become © ® ™

Category: symbols.

Why: sources.md, verified.

Characters it can insert, in any language: © ® ™. A font that lacks one of them is handled by avoid (see api.md).

en
Before
(c) 2026 Studio (R) (TM)
After
© 2026 Studio ® ™

(c) needs a year after it; © does not.

dash.dialogue

A paragraph opening with a dash is a line of dialogue, in languages that write dialogue that way: their dash and a no-break space (Ukrainian — Привіт)

Category: tradition.

Why: sources.md, verified.

Characters it can insert, in any language: — ~ –. A font that lacks one of them is handled by avoid (see api.md).

uk
Before
- Привіт, - сказав він.
After
— Привіт, - сказав він.

Only the dash that opens the paragraph; the second one belongs to dash.sentence. Both registers.

es
Before
- ¿Esperamos? - preguntó.
After
—¿Esperamos? - preguntó.

Spanish writes the raya attached to the turn.

fi
Before
- Odotetaanko? kysyi hän.
After
– Odotetaanko? kysyi hän.

An en dash where the language uses one. A paragraph whose later line also opens with a dash is a list and is left alone.

phone.bind

An international phone number (+ or 00, at least seven digits) is kept whole: no-break spaces between its groups and non-breaking hyphens inside it, with the digits as typed

Category: data.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

Characters it can insert, in any language: ~ ‑. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Call +380 44 123 45 67 or +1 (555) 123-4567
After
Call +380 44 123 45 67 or +1 (555) 123‑4567

Off by default. The digits are not reformatted; the hyphen becomes U+2011, which does not break.

en
Before
Not 555-1234, not 2026-10-20, not DE89 3704 0044 0532 0130 00
After
Not 555-1234, not 2026-10-20, not DE89 3704 0044 0532 0130 00

A local number, a date and an IBAN are left alone: the number must open with + or 00 and hold seven to fifteen digits.

number.group

Digits of an integer of five or more are grouped in threes with the language separator (1,000,000; 1 000 000)

Category: data.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

Characters it can insert, in any language: , ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
We sold 1234567 copies in 2026.
After
We sold 1,234,567 copies in 2026.

A run of five or more digits; years are left.

de
Before
Wir verkauften 1234567 Exemplare, Pi ist 3,14159265.
After
Wir verkauften 1 234 567 Exemplare, Pi ist 3,14159265.

A no-break space; the fraction is left alone.

uk
Before
Продано 12345 примірників, код v1000000.
After
Продано 12 345 примірників, код v1000000.

A name glued to digits is left.

dash.range

A hyphen between two numbers (21–26, 10:00–12:00) becomes an unspaced en dash

Category: data.

Why: sources.md, general-knowledge.

Characters it can insert, in any language: –. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Open 21-26 September, 10:00-12:00.
After
Open 21–26 September, 10:00–12:00.
en
Before
Pages 5 - 9
After
Pages 5–9

Spaced, too.

dash.sentence

A spaced hyphen, dash or double hyphen becomes a spaced dash (em; en in German and literary British English), no-break before it

Category: tradition.

Why: sources.md, verified.

Characters it can insert, in any language: — ~ –. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Wait - what happened -- really?
After
Wait — what happened — really?

An em dash in English.

de
Before
Warte - was ist passiert?
After
Warte – was ist passiert?

A spaced en dash in German.

en, literary
Before
Wait - what happened?
After
Wait – what happened?

A spaced en dash in British English, literary register.

symbol.plusminus

+- before a digit becomes ± (+-5 becomes ±5)

Category: math.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

Characters it can insert, in any language: ±. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Tolerance +-5 mm
After
Tolerance ±5 mm
en
Before
(+-0.2) and +-10%
After
(±0.2) and ±10%

Not a+-b or 1+-5.

symbol.minus

A hyphen before a digit (−5) becomes a minus sign (−5)

Category: math.

Why: sources.md, general-knowledge.

Characters it can insert, in any language: −. A font that lacks one of them is handled by avoid (see api.md).

en
Before
It was -5 degrees (-3 inside).
After
It was −5 degrees (−3 inside).

symbol.multiply

The letter x between numbers (1920×1080, 3 × 4) becomes ×

Category: math.

Why: sources.md, verified.

Characters it can insert, in any language: ×. A font that lacks one of them is handled by avoid (see api.md).

en
Before
A 1920x1080 screen, a 3 x 4 grid.
After
A 1920×1080 screen, a 3 × 4 grid.

symbol.fraction

1/2, 1/4 and 3/4 become ½ ¼ ¾, as whole numbers only (not 11/2, 1/20 or a date)

Category: math.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

Characters it can insert, in any language: ½ ¼ ¾. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Add 1/2 cup and 3/4 of the milk, then 1/4.
After
Add ½ cup and ¾ of the milk, then ¼.

Only whole numbers: 11/2, 1/20, a1/2 and a date such as 1/2/2026 stay. A short word after the fraction gets the no-break space.

en
Before
Take 2 1/2 hours
After
Take 2 ½ hours

A mixed number keeps its integer: 2 ½.

space.collapse

A run of spaces becomes one

Category: tradition.

Why: sources.md, verified.

en
Before
Two spaces, four.
After
Two spaces, four.

space.title

No-break space after Prof., Dr., Mr. …

Category: tradition.

Why: sources.md, verified.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Prof. Dr. Oksana opens.
After
Prof. Dr. Oksana opens.

space.initial

No-break space after an initial (K. Słoboda)

Category: tradition.

Why: sources.md, general-knowledge.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Written by K. Słoboda.
After
Written by K. Słoboda.

space.abbreviation

Parts of an abbreviation stay together (z. B.), and Nr., ul., S. stay with what follows

Category: tradition.

Why: sources.md, verified.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

de
Before
z. B. Nr. 5 auf S. 12
After
z. B. Nr. 5 auf S. 12
uk
Before
вул. Хрещатик, т. д.
After
вул. Хрещатик, т. д.
en
Before
See Fig. 2 and p. 14.
After
See Fig. 2 and p. 14.

space.number

No-break space between a number and a short word or unit after it, up to nine letters (21 September, 5 %); money stays whole: the sign or code before the amount (USD 5 000, € 49.99) and the digit groups of an amount written in threes (1 000 грн)

Category: data.

Why: sources.md, verified.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
On 21 September, 15 people paid 5 %.
After
On 21 September, 15 people paid 5 %.

space.percent

German, French, Czech, Spanish, Italian, Portuguese, Irish, Maltese, Bulgarian, Croatian, Slovenian, Lithuanian, Latvian, Estonian, Danish, Finnish and Greek: a no-break space between a number and % (5 %); German, French, Czech, Spanish, Italian, Bulgarian, Croatian, Slovenian, Danish, Finnish and Greek: also before € after the number (49 €)

Category: data.

Why: sources.md, verified.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

de
Before
5% and 49€
After
5 % and 49 €

The rule does nothing in other languages.

fr
Before
5% and 49€
After
5 % and 49 €

symbol.degree

20 C, 20°C and 20 °C become 20 °C, with a no-break space before the unit

Category: data.

Why: sources.md, verified.

Off by default: switch it on with enable (--enable on the command line).

Characters it can insert, in any language: ° ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
It was 20°C, then 68 F and 20 C.
After
It was 20 °C, then 68 °F and 20 °C.

Every spelling becomes number, no-break space, °C or °F.

en
Before
Vitamin C 5 C and 5 °C
After
Vitamin C 5 C and 5 °C

A bare C or F after a label or a single letter is not a temperature.

space.section

No-break space after § and ¶, doubled or not, before a number

Category: symbols.

Why: sources.md, verified.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
See § 5 and ¶¶ 3, 4
After
See § 5 and ¶¶ 3, 4

space.association

No-break space before e.V.

Category: tradition.

Why: sources.md, general-knowledge.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

de
Before
Kulturverein e.V.
After
Kulturverein e.V.

No-break space after ©

Category: symbols.

Why: sources.md, verified.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
© 2026 Studio
After
© 2026 Studio

space.operator

No-break spaces around & + = standing alone between two words

Category: symbols.

Why: sources.md, general-knowledge.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Tom & Jerry, rock + roll
After
Tom & Jerry, rock + roll

space.short-word

English, Ukrainian, Polish, Czech and Slovak: a short word of two or three letters stays with the word after it (to~the shop), for titles and headings; never more than two words in a row

Category: tradition.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Welcome to the city of light
After
Welcome to the city of light

For titles and headings; off by default. Never more than two words in a row, so a chain cannot grow into a line.

pl
Before
Zapraszamy do Gdańska
After
Zapraszamy do Gdańska
uk
Before
Ласкаво просимо до міста
After
Ласкаво просимо до міста

space.orphan

No-break space after a one-letter word the language must not strand at a line end

Category: tradition.

Why: sources.md, verified.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
A cat and I
After
A cat and I
uk
Before
Він і я в домі
After
Він і я в домі
pl
Before
Idę w las i z nim
After
Idę w las i z nim

space.arrow

No-break space before → and after ←

Category: symbols.

Why: sources.md, general-knowledge.

Characters it can insert, in any language: ~. A font that lacks one of them is handled by avoid (see api.md).

en
Before
Read more →
After
Read more →
en
Before
← Back
After
← Back

space.trailing

Spaces and tabs at the end of a line are removed

Category: tradition.

Why: sources.md, general-knowledge.

Off by default: switch it on with enable (--enable on the command line).

en
Before
First line Second line Third
After
First line Second line Third

Spaces and tabs at the end of a line; the lines stay.

en
Before
One trailing space
After
One trailing space

Something wrong or unclear here? Report an issue.