Truncate Text By Grapheme
Shorten UI text by grapheme clusters so emoji and combining marks stay intact, with an ellipsis budget included.
Code
const segmenter = typeof Intl.Segmenter === "function"
? new Intl.Segmenter(undefined, { granularity: "grapheme" })
: null;
export function truncateGraphemes(text, maxGraphemes, ellipsis = "\u2026") {
if (!Number.isInteger(maxGraphemes) || maxGraphemes < 0) {
throw new RangeError("maxGraphemes must be a non-negative integer");
}
const value = String(text);
const graphemes = segmenter
? [...segmenter.segment(value)].map((part) => part.segment)
: Array.from(value);
if (graphemes.length <= maxGraphemes) return value;
if (maxGraphemes === 0) return "";
const suffix = ellipsis ? ellipsis : "";
const budget = Math.max(0, maxGraphemes - 1);
return graphemes.slice(0, budget).join("") + suffix;
}
export function truncateMiddle(text, maxGraphemes, marker = "\u2026") {
const value = String(text);
const graphemes = segmenter
? [...segmenter.segment(value)].map((part) => part.segment)
: Array.from(value);
if (graphemes.length <= maxGraphemes) return value;
if (maxGraphemes <= 1) return marker;
const keep = maxGraphemes - 1;
const head = Math.ceil(keep / 2);
const tail = Math.floor(keep / 2);
return graphemes.slice(0, head).join("") + marker + graphemes.slice(-tail).join("");
}Report a problem with this exampleOpens a pre-filled issue on GitHub.