/** * Abbreviate a long string in the middle so both the start and the end stay * visible, e.g. `long_media_name_like_this` -> `long_med…ike_this`. * * Unlike CSS `text-overflow: ellipsis` (which only clips the end), this keeps * the tail of a media name — often the most distinguishing part (episode * number, disambiguating suffix, etc.). * * @param value The string to abbreviate. * @param maxLength Maximum length of the returned string, including the ellipsis. * @param ellipsis The separator inserted in the middle (default `…`). */ export function truncateMiddle( value: string | null | undefined, maxLength = 32, ellipsis = "…", ): string { if (value == null) return ""; if (maxLength <= 0) return ""; if (value.length <= maxLength) return value; // Not enough room for any real content around the ellipsis: fall back to a // plain head-truncation so we never return more than maxLength characters. if (maxLength <= ellipsis.length) { return value.slice(0, maxLength); } const keep = maxLength - ellipsis.length; const head = Math.ceil(keep / 2); const tail = Math.floor(keep / 2); return value.slice(0, head) + ellipsis + (tail > 0 ? value.slice(value.length - tail) : ""); }