-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
index.js
99 lines (76 loc) · 2.59 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import sliceAnsi from 'slice-ansi';
import stringWidth from 'string-width';
function getIndexOfNearestSpace(string, wantedIndex, shouldSearchRight) {
if (string.charAt(wantedIndex) === ' ') {
return wantedIndex;
}
const direction = shouldSearchRight ? 1 : -1;
for (let index = 0; index <= 3; index++) {
const finalIndex = wantedIndex + (index * direction);
if (string.charAt(finalIndex) === ' ') {
return finalIndex;
}
}
return wantedIndex;
}
export default function cliTruncate(text, columns, options = {}) {
const {
position = 'end',
space = false,
preferTruncationOnSpace = false,
} = options;
let {truncationCharacter = '…'} = options;
if (typeof text !== 'string') {
throw new TypeError(`Expected \`input\` to be a string, got ${typeof text}`);
}
if (typeof columns !== 'number') {
throw new TypeError(`Expected \`columns\` to be a number, got ${typeof columns}`);
}
if (columns < 1) {
return '';
}
if (columns === 1) {
return truncationCharacter;
}
const length = stringWidth(text);
if (length <= columns) {
return text;
}
if (position === 'start') {
if (preferTruncationOnSpace) {
const nearestSpace = getIndexOfNearestSpace(text, length - columns + 1, true);
return truncationCharacter + sliceAnsi(text, nearestSpace, length).trim();
}
if (space === true) {
truncationCharacter += ' ';
}
return truncationCharacter + sliceAnsi(text, length - columns + stringWidth(truncationCharacter), length);
}
if (position === 'middle') {
if (space === true) {
truncationCharacter = ` ${truncationCharacter} `;
}
const half = Math.floor(columns / 2);
if (preferTruncationOnSpace) {
const spaceNearFirstBreakPoint = getIndexOfNearestSpace(text, half);
const spaceNearSecondBreakPoint = getIndexOfNearestSpace(text, length - (columns - half) + 1, true);
return sliceAnsi(text, 0, spaceNearFirstBreakPoint) + truncationCharacter + sliceAnsi(text, spaceNearSecondBreakPoint, length).trim();
}
return (
sliceAnsi(text, 0, half)
+ truncationCharacter
+ sliceAnsi(text, length - (columns - half) + stringWidth(truncationCharacter), length)
);
}
if (position === 'end') {
if (preferTruncationOnSpace) {
const nearestSpace = getIndexOfNearestSpace(text, columns - 1);
return sliceAnsi(text, 0, nearestSpace) + truncationCharacter;
}
if (space === true) {
truncationCharacter = ` ${truncationCharacter}`;
}
return sliceAnsi(text, 0, columns - stringWidth(truncationCharacter)) + truncationCharacter;
}
throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${position}`);
}