· 3 min read
Typing typographic characters on Windows
Alt codes on the numeric keypad, the Win + . symbol panel, and Word’s own shortcuts — three ways to type every dash, quote and sign, with the full code table.
A library that fixes the typography of running text. Give it a string and a language. It gives the string back with the right quotation marks, dashes where there were hyphens, an ellipsis, and no-break spaces where a line should not break.
npm install @mokhniuk/typography
Version 0.11.0, a pre-release. Not on npm yet; it will be there at 1.0. Until then, pick git and install a release tag. The repository is private, so the machine needs SSH access.
“Curiouser and curiouser!” cried Alice (she was so much surprised, that for the moment she quite forgot how to speak good English); “now I’m opening out like the largest telescope that ever was! Good-bye, feet!” — for when she looked down at her feet, they seemed to be almost out of sight…
The engine is one function over a string. Everything else is a way of getting your text into it, or a way of seeing what it did.
explain returns every change with the rule that made it and the text before and after, so a surprise is a question with an answer, not a mystery. The rulespre and code are never touched. An unknown rule name throws instead of passing quietly.Each language has its own pack: its quotation marks and how they nest, its dash, its habits with spaces. These four are not translations of one sentence; each is written the way that language is.
Curly quotes and apostrophes, a spaced dash, a real ellipsis, an en dash in ranges, and a number kept with its month.
"It's five o'clock," she said - "and we're late..." The workshop runs 21-26 September, 10:00-12:00, in room 4B.Ukrainian guillemets, the dialogue dash with its no-break space, and initials kept with the surname.
- Зачекаємо? - спитав професор К. Новак. - Сказали: "вже п'ята година"... Квитки зі знижкою 15%.German marks, nested the German way, and a range that is a range.
Sie sagte: "Er rief 'Halt' - und blieb stehen" ... Seiten 12-14, ca. 20 Min. am Tag.Polish low-and-high quotes, and one-letter words held to the next word so no line ends on them.
Powiedział: "Idę do domu" - i poszedł. W sali nr 5 jest 20 osób, a w drugiej a w trzeciej 12.22 rules run by default, and 11 more you switch on. Here are some of them on one line each. A boxed space is a no-break space.
| Rule | You write | You get |
|---|---|---|
quote |
"Hello" |
“Hello” |
apostrophe |
don't |
don’t |
ellipsis |
Wait... |
Wait… |
dash.range |
pages 21-26 |
pages 21–26 |
dash.sentence |
Wait - what? |
Wait — what? |
dash.dialogue |
- Привіт, - сказала вона. |
— Привіт, — сказала вона. |
space.number |
10 km |
10 km |
space.initial |
T. H. Shevchenko |
T. H. Shevchenko |
space.orphan |
Jadę z Anią w góry |
Jadę z Anią w góry |
symbol.legal |
(c) 2026 |
© 2026 |
symbol.multiply |
1920x1080 |
1920×1080 |
symbol.minus |
-5 C |
−5 C |
number.group opt-in |
1000000 |
1,000,000 |
One function takes a string and a language. The other entry points do the same for HTML, Markdown, rehype trees, React and the DOM.
import { typographic, explain } from '@mokhniuk/typography';
typographic('He said "we\'re here" - and left.', 'en', { quoteStyle: 'us' });
// He said “we’re here” — and left.
explain('He said "hi"... 21-26', 'en', { quoteStyle: 'us' }).changes;
// quote “ · quote ” · ellipsis … · dash.range –
| Import | For |
|---|---|
@mokhniuk/typography | A string. explain lists each change and the rule behind it. |
…/html | An HTML string. Tags and code are untouched. |
…/markdown | A Markdown document. |
…/rehype | A unified or rehype pipeline, or any hast tree. |
…/react | Typeset and TypographyRoot, with hanging punctuation. |
…/dom | Hanging punctuation in the browser, without a framework. |
typo | The command line, for files and CI. |
Before you depend on it, you should know where it is weak.
quoteStyle: 'us' for “”.a 5" hole) is one. Such cases are listed as limits, not guessed at.“Typography is what language looks like. A straight quote, a hyphen standing in for a dash, a number torn from the word it counts: each is a small lie about the text, and a reader feels all of them at once without being able to name one.”
Where each decision came from, and what a reader should know about the marks themselves. Written while building the engine.
· 3 min read
Alt codes on the numeric keypad, the Win + . symbol panel, and Word’s own shortcuts — three ways to type every dash, quote and sign, with the full code table.
· 3 min read
Replacing straight quotes with curly ones looks like a dozen regexes. Here is what the dozen regexes get wrong, and what an engine has to do instead.
· 2 min read
The most useful typographic character is invisible. Where a no-break space belongs, why CSS cannot place it for you, and the rules that set it.
Typography Engine is a solo project by Oleg Mokhniuk: the rules, the language packs, the docs and this site are one person’s work.
If it is useful and you want to give something back, skip the coffee. The best way to support this project is a donation to Come Back Alive, the Ukrainian foundation that equips the people defending Ukraine.
Or support the author directly: paypal.me/mokhniuk.