( text: string, maxWidth: number, ellipsis: string = "...", pad: boolean = false, )
| 939 | * @returns Truncated text, optionally padded to exactly maxWidth |
| 940 | */ |
| 941 | export function truncateToWidth( |
| 942 | text: string, |
| 943 | maxWidth: number, |
| 944 | ellipsis: string = "...", |
| 945 | pad: boolean = false, |
| 946 | ): string { |
| 947 | if (maxWidth <= 0) { |
| 948 | return ""; |
| 949 | } |
| 950 | |
| 951 | if (text.length === 0) { |
| 952 | return pad ? " ".repeat(maxWidth) : ""; |
| 953 | } |
| 954 | |
| 955 | const ellipsisWidth = visibleWidth(ellipsis); |
| 956 | if (ellipsisWidth >= maxWidth) { |
| 957 | const textWidth = visibleWidth(text); |
| 958 | if (textWidth <= maxWidth) { |
| 959 | return pad ? text + " ".repeat(maxWidth - textWidth) : text; |
| 960 | } |
| 961 | |
| 962 | const clippedEllipsis = truncateFragmentToWidth(ellipsis, maxWidth); |
| 963 | if (clippedEllipsis.width === 0) { |
| 964 | return pad ? " ".repeat(maxWidth) : ""; |
| 965 | } |
| 966 | return finalizeTruncatedResult("", 0, clippedEllipsis.text, clippedEllipsis.width, maxWidth, pad); |
| 967 | } |
| 968 | |
| 969 | if (isPrintableAscii(text)) { |
| 970 | if (text.length <= maxWidth) { |
| 971 | return pad ? text + " ".repeat(maxWidth - text.length) : text; |
| 972 | } |
| 973 | const targetWidth = maxWidth - ellipsisWidth; |
| 974 | return finalizeTruncatedResult(text.slice(0, targetWidth), targetWidth, ellipsis, ellipsisWidth, maxWidth, pad); |
| 975 | } |
| 976 | |
| 977 | const targetWidth = maxWidth - ellipsisWidth; |
| 978 | let result = ""; |
| 979 | let pendingAnsi = ""; |
| 980 | let visibleSoFar = 0; |
| 981 | let keptWidth = 0; |
| 982 | let keepContiguousPrefix = true; |
| 983 | let overflowed = false; |
| 984 | let exhaustedInput = false; |
| 985 | const hasAnsi = text.includes("\x1b"); |
| 986 | const hasTabs = text.includes("\t"); |
| 987 | |
| 988 | if (!hasAnsi && !hasTabs) { |
| 989 | for (const { segment } of graphemeSegmenter.segment(text)) { |
| 990 | const width = graphemeWidth(segment); |
| 991 | if (keepContiguousPrefix && keptWidth + width <= targetWidth) { |
| 992 | result += segment; |
| 993 | keptWidth += width; |
| 994 | } else { |
| 995 | keepContiguousPrefix = false; |
| 996 | } |
| 997 | visibleSoFar += width; |
| 998 | if (visibleSoFar > maxWidth) { |
no test coverage detected