Node.js bindings for ttf-parser, a high-level, safe, zero-allocation TrueType font parser written in Rust.
- 🚀 Fast native performance using Rust
- 🔒 Memory-safe with zero-allocation parsing
- 📦 Support for TrueType (.ttf) and OpenType (.otf) fonts
- 🎨 Extract font metrics, glyph information, and more
- 💪 Built on the battle-tested ttf-parser library
- Node.js 14 or higher
Note for developers: If you want to build from source, you'll need the Rust toolchain (https://rustup.rs/)
npm install ttf-parser-node
# or
pnpm add ttf-parser-node
# or
yarn add ttf-parser-nodeThe package includes a pre-built native module that works out of the box - no Rust installation required!
Current platform support: macOS ARM64 (Apple Silicon)
For other platforms, see the "Multi-Platform Support" section below.
pnpm install
pnpm run buildFor development builds:
pnpm run build-debugconst Font = require('ttf-parser-node');
// Load font from file
const font = Font.fromFile('path/to/font.ttf');
// Get font information
console.log(font.familyName); // e.g., "Arial"
console.log(font.unitsPerEm); // e.g., 2048
console.log(font.numberOfGlyphs); // e.g., 1234
console.log(font.ascender); // e.g., 1854
console.log(font.descender); // e.g., -434const fs = require('fs');
const Font = require('ttf-parser-node');
const buffer = fs.readFileSync('path/to/font.ttf');
const font = new Font(buffer);// Get glyph ID for a character
const glyphId = font.glyphIndex('A'); // or font.glyphIndex(65)
console.log(glyphId); // e.g., 36
// Get horizontal advance width for a glyph
const advance = font.glyphHorAdvance(glyphId);
console.log(advance); // e.g., 1479 (in font units)
// Get all glyph advances at once
const advances = font.getAllAdvances();
console.log(advances.length); // Same as numberOfGlyphsThe Font object provides access to various font properties:
font.familyName // Font family name (e.g., "Arial")
font.postScriptName // PostScript name (e.g., "ArialMT")
font.unitsPerEm // Units per EM square
font.numberOfGlyphs // Total number of glyphs
font.ascender // Typographic ascender
font.descender // Typographic descender
font.lineGap // Line gap (may be undefined)
font.isBold // Whether font is bold
font.isItalic // Whether font is italic
font.isMonospaced // Whether font is monospaced
font.isVariable // Whether font is a variable font
font.underline // Underline metrics {position, thickness}const fontInfo = font.toJSON();
console.log(JSON.stringify(fontInfo, null, 2));This library includes full TypeScript type definitions. All APIs are fully typed for TypeScript projects:
import Font from 'ttf-parser-node';
const font = Font.fromFile('./font.ttf');
// All properties are properly typed
const name: string | undefined = font.familyName;
const glyphs: number = font.numberOfGlyphs;
const isBold: boolean = font.isBold;
// Methods have type-safe signatures
const glyphId: number | null = font.glyphIndex('A');
if (glyphId !== null) {
const advance: number = font.glyphHorAdvance(glyphId);
}
// Optional properties are typed correctly
if (font.underline) {
console.log(font.underline.position); // number
console.log(font.underline.thickness); // number
}See example.ts for a complete TypeScript example.
Load a font from a file path.
- Parameters:
path(string): Path to the font file
- Returns:
Fontinstance - Throws: Error if file cannot be read or parsed
Create a font instance from a buffer.
- Parameters:
buffer(Buffer): Font file data
- Returns:
Fontinstance - Throws: TypeError if not a Buffer, Error if parsing fails
Get the glyph ID for a character.
- Parameters:
char(string|number): Character or character code
- Returns:
number|null- Glyph ID or null if not found
Get the horizontal advance width for a glyph.
- Parameters:
glyphId(number): The glyph ID
- Returns:
number- Advance width in font units
Get all glyph horizontal advance widths.
- Returns:
number[]- Array of advance widths
Get all font information as a plain JavaScript object.
- Returns:
Object- Font properties
Run the included test:
# Test with default system font
node test.js
# Test with specific font
node test.js /path/to/your/font.ttfFont Information:
Family Name: DejaVu Sans
PostScript Name: DejaVuSans
Units per EM: 2048
Number of Glyphs: 6253
Ascender: 1901
Descender: -483
Line Gap: 0
Bold: false
Italic: false
Monospaced: false
Variable: false
Character | Glyph ID | Advance Width
--------------------------------------------------
A | 36 | 1479
B | 37 | 1479
C | 38 | 1405
# Clone the repository
git clone <your-repo-url>
cd ttf-parser-node
# Install dependencies
pnpm install
# Build the native module (builds automatically during install)
pnpm run build
# Run tests
pnpm testttf-parser-node leverages Rust's zero-allocation parsing, making it extremely fast:
- ⚡ Parsing a font: ~500 nanoseconds
- ⚡ Getting glyph advance: ~2 nanoseconds
- ⚡ Getting glyph index: ~16 nanoseconds
| Feature | ttf-parser-node | opentype.js | fontkit |
|---|---|---|---|
| Language | Rust + Node.js | JavaScript | JavaScript |
| Performance | ⚡ Fastest | Fast | Fast |
| Memory Safety | ✓ (Rust) | ~ | ~ |
| Zero Allocation | ✓ | ✗ | ✗ |
| Variable Fonts | ✓ | ✓ | ✓ |
Current bindings expose basic font information and glyph metrics. Future versions may include:
- Glyph outline extraction
- Font subsetting
- Advanced OpenType features
- Table-level access
The package currently includes a pre-built binary for macOS ARM64. To support multiple platforms, you have several options:
Build binaries for different platforms in your CI pipeline:
# On each platform (Linux, macOS x64, macOS ARM64, Windows)
pnpm run build-release
# Commit the index.node for that platformInstall prebuildify for cross-platform support:
pnpm add -D prebuildifyUpdate package.json:
{
"scripts": {
"prebuild": "prebuildify --napi --strip",
"install": "node-gyp-build"
}
}Then build for multiple platforms and publish pre-built binaries.
If consumers have Rust installed, they can build from source:
# In the consuming project
cd node_modules/ttf-parser-node
pnpm run build-releaseFor more information on native module distribution, see:
- prebuildify
- napi-rs (alternative approach)
Contributions are welcome! To add new features:
- Add the Rust function in
src/lib.rs - Export it in the
mainfunction - Add a JavaScript wrapper method in
index.js - Update tests and documentation
MIT
This project uses:
- ttf-parser by RazrFalcon
- Neon for Rust-Node.js bindings
Make sure the font file is:
- A valid TrueType (.ttf) or OpenType (.otf) font
- Not corrupted
- Readable by your application
Run npm run build to compile the native module.