@logtape/pretty
Version:
Beautiful text formatter for LogTape—perfect for local development
91 lines (82 loc) • 2.69 kB
text/typescript
/**
* Truncation strategies for category names.
*
* @since 1.0.0
*/
export type TruncationStrategy = "middle" | "end" | false;
/**
* Truncates a category array to fit within a maximum width using the specified strategy.
*
* This function intelligently shortens long hierarchical category names while
* preserving important context. The truncation behavior depends on the chosen
* strategy:
*
* - `"middle"`: Keeps the first and last segments with "…" in between
* - `"end"`: Truncates at the end with "…" suffix
* - `false`: No truncation (returns full category string)
*
* When the category is too long even for middle truncation (first + "…" + last
* exceeds maxWidth), it falls back to end truncation.
*
* @param category The category segments to truncate.
* @param maxWidth Maximum width for the category string.
* @param separator Category separator (default: ".").
* @param strategy Truncation strategy to use (default: "middle").
* @returns The truncated category string.
*
* @example
* ```typescript
* // Middle truncation
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "middle");
* // Returns: "app…auth"
*
* // End truncation
* truncateCategory(["app", "server", "http", "auth"], 15, ".", "end");
* // Returns: "app.server.h…"
*
* // No truncation
* truncateCategory(["app", "auth"], 20, ".", false);
* // Returns: "app.auth"
* ```
*
* @since 1.0.0
*/
export function truncateCategory(
category: readonly string[],
maxWidth: number,
separator: string = ".",
strategy: TruncationStrategy = "middle",
): string {
if (!strategy || maxWidth <= 0) {
return category.join(separator);
}
const full = category.join(separator);
if (full.length <= maxWidth) {
return full;
}
// Minimum width needed for truncation with ellipsis
const minWidth = 5; // e.g., "a…z"
if (maxWidth < minWidth) {
return "…";
}
if (strategy === "end") {
return full.substring(0, maxWidth - 1) + "…";
}
// Middle truncation strategy
if (category.length <= 2) {
// For short categories, just truncate the end
return full.substring(0, maxWidth - 1) + "…";
}
// Try to keep first and last segments
const first = category[0];
const last = category[category.length - 1];
const ellipsis = "…";
// Check if we can at least fit first…last
const minimalLength = first.length + ellipsis.length + last.length;
if (minimalLength > maxWidth) {
// Even minimal format is too long, fallback to end truncation
return full.substring(0, maxWidth - 1) + "…";
}
// For simple case with limited space, just do first…last
return `${first}${ellipsis}${last}`;
}