cli-truncate
Advanced tools
+3
-1
@@ -96,4 +96,6 @@ export type Options = { | ||
| cliTruncate('\u001B[31municorn\u001B[39m', 4); | ||
| //=> '\u001B[31muni\u001B[39m…' | ||
| //=> '\u001B[31muni…\u001B[39m' | ||
| // Note: When truncating styled text (ANSI escapes), the truncation character inherits the style at the breaking point for `position: 'start'` and `position: 'end'`. This does not apply to `position: 'middle'`. | ||
| // Truncate Unicode surrogate pairs | ||
@@ -100,0 +102,0 @@ cliTruncate('uni\uD83C\uDE00corn', 5); |
+76
-7
@@ -52,17 +52,84 @@ import sliceAnsi from 'slice-ansi'; | ||
| // ANSI escape sequence constants | ||
| const ANSI = { | ||
| ESC: 27, | ||
| LEFT_BRACKET: 91, | ||
| LETTER_M: 109, | ||
| }; | ||
| const isSgrParameter = code => (code >= 48 && code <= 57) || code === 59; // 0-9 or ; | ||
| function leadingSgrSpanEndIndex(string) { | ||
| let index = 0; | ||
| while (index + 2 < string.length && string.codePointAt(index) === ANSI.ESC && string.codePointAt(index + 1) === ANSI.LEFT_BRACKET) { | ||
| let j = index + 2; | ||
| while (j < string.length && isSgrParameter(string.codePointAt(j))) { | ||
| j++; | ||
| } | ||
| if (j < string.length && string.codePointAt(j) === ANSI.LETTER_M) { | ||
| index = j + 1; | ||
| continue; | ||
| } | ||
| break; | ||
| } | ||
| return index; | ||
| } | ||
| function trailingSgrSpanStartIndex(string) { | ||
| let start = string.length; | ||
| while (start > 1 && string.codePointAt(start - 1) === ANSI.LETTER_M) { | ||
| let j = start - 2; | ||
| while (j >= 0 && isSgrParameter(string.codePointAt(j))) { | ||
| j--; | ||
| } | ||
| if (j >= 1 && string.codePointAt(j - 1) === ANSI.ESC && string.codePointAt(j) === ANSI.LEFT_BRACKET) { | ||
| start = j - 1; | ||
| continue; | ||
| } | ||
| break; | ||
| } | ||
| return start; | ||
| } | ||
| function appendWithInheritedStyleFromEnd(visible, suffix) { | ||
| const start = trailingSgrSpanStartIndex(visible); | ||
| if (start === visible.length) { | ||
| return visible + suffix; | ||
| } | ||
| return visible.slice(0, start) + suffix + visible.slice(start); | ||
| } | ||
| function prependWithInheritedStyleFromStart(prefix, visible) { | ||
| const end = leadingSgrSpanEndIndex(visible); | ||
| if (end === 0) { | ||
| return prefix + visible; | ||
| } | ||
| return visible.slice(0, end) + prefix + visible.slice(end); | ||
| } | ||
| if (position === 'start') { | ||
| if (preferTruncationOnSpace) { | ||
| const nearestSpace = getIndexOfNearestSpace(text, length - columns + 1, true); | ||
| return truncationCharacter + sliceAnsi(text, nearestSpace, length).trim(); | ||
| const right = sliceAnsi(text, nearestSpace, length).trim(); | ||
| return prependWithInheritedStyleFromStart(truncationCharacter, right); | ||
| } | ||
| if (space === true) { | ||
| if (space) { | ||
| truncationCharacter += ' '; | ||
| } | ||
| return truncationCharacter + sliceAnsi(text, length - columns + stringWidth(truncationCharacter), length); | ||
| const right = sliceAnsi(text, length - columns + stringWidth(truncationCharacter), length); | ||
| return prependWithInheritedStyleFromStart(truncationCharacter, right); | ||
| } | ||
| if (position === 'middle') { | ||
| if (space === true) { | ||
| if (space) { | ||
| truncationCharacter = ` ${truncationCharacter} `; | ||
@@ -89,10 +156,12 @@ } | ||
| const nearestSpace = getIndexOfNearestSpace(text, columns - 1); | ||
| return sliceAnsi(text, 0, nearestSpace) + truncationCharacter; | ||
| const left = sliceAnsi(text, 0, nearestSpace); | ||
| return appendWithInheritedStyleFromEnd(left, truncationCharacter); | ||
| } | ||
| if (space === true) { | ||
| if (space) { | ||
| truncationCharacter = ` ${truncationCharacter}`; | ||
| } | ||
| return sliceAnsi(text, 0, columns - stringWidth(truncationCharacter)) + truncationCharacter; | ||
| const left = sliceAnsi(text, 0, columns - stringWidth(truncationCharacter)); | ||
| return appendWithInheritedStyleFromEnd(left, truncationCharacter); | ||
| } | ||
@@ -99,0 +168,0 @@ |
+1
-1
| { | ||
| "name": "cli-truncate", | ||
| "version": "5.0.0", | ||
| "version": "5.1.0", | ||
| "description": "Truncate a string to a specific width in the terminal", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
+13
-9
@@ -28,8 +28,11 @@ # cli-truncate | ||
| cliTruncate('unicorns rainbow dragons', 6, {position: 'end'}) | ||
| cliTruncate('unicorns rainbow dragons', 6, {position: 'end'}); | ||
| //=> 'unico…' | ||
| cliTruncate('\u001B[31municorn\u001B[39m', 4); | ||
| //=> '\u001B[31muni\u001B[39m…' | ||
| //=> '\u001B[31muni…\u001B[39m' | ||
| > [!NOTE] | ||
| > When truncating styled text (ANSI escapes), the truncation character inherits the style at the breaking point for `position: 'start'` and `position: 'end'`. This does not apply to `position: 'middle'`. | ||
| // Truncate Unicode surrogate pairs | ||
@@ -110,17 +113,17 @@ cliTruncate('uni\uD83C\uDE00corn', 5); | ||
| cliTruncate('unicorns rainbow dragons', 20, {position: 'start', preferTruncationOnSpace: true}) | ||
| cliTruncate('unicorns rainbow dragons', 20, {position: 'start', preferTruncationOnSpace: true}); | ||
| //=> '…rainbow dragons' | ||
| // without preferTruncationOnSpace | ||
| cliTruncate('unicorns rainbow dragons', 20, {position: 'start'}) | ||
| // Without preferTruncationOnSpace | ||
| cliTruncate('unicorns rainbow dragons', 20, {position: 'start'}); | ||
| //=> '…rns rainbow dragons' | ||
| cliTruncate('unicorns rainbow dragons', 20, {position: 'middle', preferTruncationOnSpace: true}) | ||
| cliTruncate('unicorns rainbow dragons', 20, {position: 'middle', preferTruncationOnSpace: true}); | ||
| //=> 'unicorns…dragons' | ||
| cliTruncate('unicorns rainbow dragons', 6, {position: 'end', preferTruncationOnSpace: true}) | ||
| cliTruncate('unicorns rainbow dragons', 6, {position: 'end', preferTruncationOnSpace: true}); | ||
| //=> 'unico…' | ||
| // preferTruncationOnSpace would have no effect if space isn't found within next 3 indexes | ||
| cliTruncate('unicorns rainbow dragons', 6, {position: 'middle', preferTruncationOnSpace: true}) | ||
| // preferTruncationOnSpace has no effect if space isn't found within 3 characters | ||
| cliTruncate('unicorns rainbow dragons', 6, {position: 'middle', preferTruncationOnSpace: true}); | ||
| //=> 'uni…ns' | ||
@@ -147,2 +150,3 @@ ``` | ||
| //=> 'unico' | ||
| ``` | ||
@@ -149,0 +153,0 @@ |
13083
19.86%218
34.57%155
2.65%