DEV Community

Cover image for trimoji — Unicode and emoji-aware text truncation for JavaScript
Kunal Tanwar
Kunal Tanwar

Posted on

trimoji — Unicode and emoji-aware text truncation for JavaScript

The problem

Most text truncation in JavaScript looks like this:

str.slice(0, 100) + "..."
Enter fullscreen mode Exit fullscreen mode

Looks fine until you hit real-world content. This breaks in several ways:

  • Emoji — 👨‍👩‍👧 is multiple codepoints. Slicing mid-sequence produces garbage characters.
  • Accented characters — é can be e + a combining accent codepoint. Naive slicing splits them.
  • Word boundaries — you get "Hello, W..." instead of "Hello,..."
  • Ellipsis budget — the ... itself takes space that most implementations don't account for.

The solution

trimoji uses the native Intl.Segmenter API — no regex hacks, no dependencies — to truncate strings at proper grapheme, word, or sentence boundaries.

import { trimoji } from "trimoji"

// word boundary (default)
trimoji("Hello 👋, World!", 10)
// ➡️ "Hello 👋,…"

// grapheme boundary
trimoji("Café 🎉 World!", {
    maxLength: 7,
    boundary: "grapheme"
})
// ➡️ "Café 🎉…"

// sentence boundary
trimoji("Hello, World! How are you?", {
    maxLength: 15,
    boundary: "sentence"
})
// ➡️ "Hello, World!…"

// custom ellipsis
trimoji("Hello, World!", {
    maxLength: 10,
    ellipsis: "..."
})
// ➡️ "Hello,..."

// empty ellipsis — hard cut
trimoji("Hello, World!", {
    maxLength: 5,
    ellipsis: ""
})
// ➡️ "Hello"
Enter fullscreen mode Exit fullscreen mode

Why Intl.Segmenter?

Intl.Segmenter is a native browser API that understands Unicode text segmentation rules. It knows that 👨‍👩‍👧 is one visible character, that é (as e + combining accent) is one grapheme, and where word and sentence boundaries actually are across different languages.

It's supported in all modern browsers, Node.js 16+, Bun, and Deno — so no polyfills needed.

Fallback behavior

When the budget is tight, trimoji falls back gracefully:

  • sentence ➡️ falls back to word if the first sentence doesn't fit
  • word ➡️ falls back to grapheme if the first word doesn't fit

So you never get an empty string or a crash.

API

trimoji(str: string, options: number | TrimOptions): string
Enter fullscreen mode Exit fullscreen mode
Option Type Default Description
maxLength number Max visible length including ellipsis
ellipsis string "…" Appended at the cut point
boundary `"grapheme" \ "word" \ "sentence"`
locale string "en" BCP 47 locale for Intl.Segmenter

There's also a utility export:

import { graphemeLength } from "trimoji"

graphemeLength("café")   // 4
graphemeLength("👨‍👩‍👧")     // 1
graphemeLength("Hi 👋!")  // 5
Enter fullscreen mode Exit fullscreen mode

Install

bun add trimoji
# or
npm install trimoji
Enter fullscreen mode Exit fullscreen mode

4.4 kB packed. Zero dependencies.

📦 npm
🐙 GitHub

Top comments (0)