cli-truncate 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/index.d.ts +96 -0
  2. package/index.js +76 -15
  3. package/package.json +12 -9
  4. package/readme.md +55 -10
package/index.d.ts ADDED
@@ -0,0 +1,96 @@
1
+ declare namespace cliTruncate {
2
+ interface Options {
3
+ /**
4
+ Position to truncate the string.
5
+
6
+ @default 'end'
7
+ */
8
+ readonly position?: 'start' | 'middle' | 'end';
9
+
10
+ /**
11
+ Add a space between the text and the ellipsis.
12
+
13
+ @default false
14
+
15
+ @example
16
+ ```
17
+ cliTruncate('unicorns', 5, {position: 'end', space: true});
18
+ //=> 'uni …'
19
+
20
+ cliTruncate('unicorns', 5, {position: 'end', space: false});
21
+ //=> 'unic…'
22
+
23
+ cliTruncate('unicorns', 6, {position: 'start', space: true});
24
+ //=> '… orns'
25
+
26
+ cliTruncate('unicorns', 7, {position: 'middle', space: true});
27
+ //=> 'uni … s'
28
+ ```
29
+ */
30
+ readonly space?: boolean;
31
+
32
+ /**
33
+ Truncate the string from a whitespace if it is within 3 characters from the actual breaking point.
34
+
35
+ @default false
36
+
37
+ @example
38
+ ```
39
+ cliTruncate('unicorns rainbow dragons', 20, {position: 'start', preferTruncationOnSpace: true});
40
+ //=> '…rainbow dragons'
41
+
42
+ cliTruncate('unicorns rainbow dragons', 20, {position: 'middle', preferTruncationOnSpace: true});
43
+ //=> 'unicorns…dragons'
44
+
45
+ cliTruncate('unicorns rainbow dragons', 6, {position: 'end', preferTruncationOnSpace: true});
46
+ //=> 'unico…'
47
+ ````
48
+ */
49
+ readonly preferTruncationOnSpace?: boolean;
50
+ }
51
+ }
52
+
53
+ /**
54
+ Truncate a string to a specific width in the terminal.
55
+
56
+ @param text - Text to truncate.
57
+ @param columns - Columns to occupy in the terminal.
58
+
59
+ @example
60
+ ```
61
+ import cliTruncate = require('cli-truncate');
62
+
63
+ cliTruncate('unicorn', 4);
64
+ //=> 'uni…'
65
+
66
+ // Truncate at different positions
67
+ cliTruncate('unicorn', 4, {position: 'start'});
68
+ //=> '…orn'
69
+
70
+ cliTruncate('unicorn', 4, {position: 'middle'});
71
+ //=> 'un…n'
72
+
73
+ cliTruncate('\u001B[31municorn\u001B[39m', 4);
74
+ //=> '\u001B[31muni\u001B[39m…'
75
+
76
+ // Truncate Unicode surrogate pairs
77
+ cliTruncate('uni\uD83C\uDE00corn', 5);
78
+ //=> 'uni\uD83C\uDE00…'
79
+
80
+ // Truncate fullwidth characters
81
+ cliTruncate('안녕하세요', 3);
82
+ //=> '안…'
83
+
84
+ // Truncate the paragraph to the terminal width
85
+ const paragraph = 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.';
86
+ cliTruncate(paragraph, process.stdout.columns));
87
+ //=> 'Lorem ipsum dolor sit amet, consectetuer adipiscing…'
88
+ ```
89
+ */
90
+ declare function cliTruncate(
91
+ text: string,
92
+ columns: number,
93
+ options?: cliTruncate.Options
94
+ ): string;
95
+
96
+ export = cliTruncate;
package/index.js CHANGED
@@ -2,16 +2,37 @@
2
2
  const sliceAnsi = require('slice-ansi');
3
3
  const stringWidth = require('string-width');
4
4
 
5
- module.exports = (input, columns, opts) => {
6
- opts = Object.assign({
7
- position: 'end'
8
- }, opts);
5
+ function getIndexOfNearestSpace(string, index, shouldSearchRight) {
6
+ if (string.charAt(index) === ' ') {
7
+ return index;
8
+ }
9
+
10
+ for (let i = 1; i <= 3; i++) {
11
+ if (shouldSearchRight) {
12
+ if (string.charAt(index + i) === ' ') {
13
+ return index + i;
14
+ }
15
+ } else if (string.charAt(index - i) === ' ') {
16
+ return index - i;
17
+ }
18
+ }
19
+
20
+ return index;
21
+ }
9
22
 
10
- const position = opts.position;
11
- const ellipsis = '…';
23
+ module.exports = (text, columns, options) => {
24
+ options = {
25
+ position: 'end',
26
+ preferTruncationOnSpace: false,
27
+ ...options
28
+ };
12
29
 
13
- if (typeof input !== 'string') {
14
- throw new TypeError(`Expected \`input\` to be a string, got ${typeof input}`);
30
+ const {position, space, preferTruncationOnSpace} = options;
31
+ let ellipsis = '…';
32
+ let ellipsisWidth = 1;
33
+
34
+ if (typeof text !== 'string') {
35
+ throw new TypeError(`Expected \`input\` to be a string, got ${typeof text}`);
15
36
  }
16
37
 
17
38
  if (typeof columns !== 'number') {
@@ -26,19 +47,59 @@ module.exports = (input, columns, opts) => {
26
47
  return ellipsis;
27
48
  }
28
49
 
29
- const length = stringWidth(input);
50
+ const length = stringWidth(text);
30
51
 
31
52
  if (length <= columns) {
32
- return input;
53
+ return text;
33
54
  }
34
55
 
35
56
  if (position === 'start') {
36
- return ellipsis + sliceAnsi(input, length - columns + 1, length);
37
- } else if (position === 'middle') {
57
+ if (preferTruncationOnSpace) {
58
+ const nearestSpace = getIndexOfNearestSpace(text, length - columns + 1, true);
59
+ return ellipsis + sliceAnsi(text, nearestSpace, length).trim();
60
+ }
61
+
62
+ if (space === true) {
63
+ ellipsis += ' ';
64
+ ellipsisWidth = 2;
65
+ }
66
+
67
+ return ellipsis + sliceAnsi(text, length - columns + ellipsisWidth, length);
68
+ }
69
+
70
+ if (position === 'middle') {
71
+ if (space === true) {
72
+ ellipsis = ' ' + ellipsis + ' ';
73
+ ellipsisWidth = 3;
74
+ }
75
+
38
76
  const half = Math.floor(columns / 2);
39
- return sliceAnsi(input, 0, half) + ellipsis + sliceAnsi(input, length - (columns - half) + 1, length);
40
- } else if (position === 'end') {
41
- return sliceAnsi(input, 0, columns - 1) + ellipsis;
77
+
78
+ if (preferTruncationOnSpace) {
79
+ const spaceNearFirstBreakPoint = getIndexOfNearestSpace(text, half);
80
+ const spaceNearSecondBreakPoint = getIndexOfNearestSpace(text, length - (columns - half) + 1, true);
81
+ return sliceAnsi(text, 0, spaceNearFirstBreakPoint) + ellipsis + sliceAnsi(text, spaceNearSecondBreakPoint, length).trim();
82
+ }
83
+
84
+ return (
85
+ sliceAnsi(text, 0, half) +
86
+ ellipsis +
87
+ sliceAnsi(text, length - (columns - half) + ellipsisWidth, length)
88
+ );
89
+ }
90
+
91
+ if (position === 'end') {
92
+ if (preferTruncationOnSpace) {
93
+ const nearestSpace = getIndexOfNearestSpace(text, columns - 1);
94
+ return sliceAnsi(text, 0, nearestSpace) + ellipsis;
95
+ }
96
+
97
+ if (space === true) {
98
+ ellipsis = ' ' + ellipsis;
99
+ ellipsisWidth = 2;
100
+ }
101
+
102
+ return sliceAnsi(text, 0, columns - ellipsisWidth) + ellipsis;
42
103
  }
43
104
 
44
105
  throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${position}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cli-truncate",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Truncate a string to a specific width in the terminal",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/cli-truncate",
@@ -10,13 +10,14 @@
10
10
  "url": "sindresorhus.com"
11
11
  },
12
12
  "engines": {
13
- "node": ">=4"
13
+ "node": ">=8"
14
14
  },
15
15
  "scripts": {
16
- "test": "xo && ava"
16
+ "test": "xo && ava && tsd"
17
17
  },
18
18
  "files": [
19
- "index.js"
19
+ "index.js",
20
+ "index.d.ts"
20
21
  ],
21
22
  "keywords": [
22
23
  "truncate",
@@ -29,14 +30,16 @@
29
30
  "term",
30
31
  "shell",
31
32
  "width",
32
- "ansi"
33
+ "ansi",
34
+ "string"
33
35
  ],
34
36
  "dependencies": {
35
- "slice-ansi": "^1.0.0",
36
- "string-width": "^2.0.0"
37
+ "slice-ansi": "^2.1.0",
38
+ "string-width": "^4.1.0"
37
39
  },
38
40
  "devDependencies": {
39
- "ava": "*",
40
- "xo": "*"
41
+ "ava": "^2.1.0",
42
+ "tsd": "^0.7.2",
43
+ "xo": "^0.24.0"
41
44
  }
42
45
  }
package/readme.md CHANGED
@@ -27,6 +27,9 @@ cliTruncate('unicorn', 4, {position: 'start'});
27
27
  cliTruncate('unicorn', 4, {position: 'middle'});
28
28
  //=> 'un…n'
29
29
 
30
+ cliTruncate('unicorns rainbow dragons', 6, {position: 'end'})
31
+ //=> 'unico…'
32
+
30
33
  cliTruncate('\u001B[31municorn\u001B[39m', 4);
31
34
  //=> '\u001B[31muni\u001B[39m…'
32
35
 
@@ -47,9 +50,9 @@ cliTruncate(paragraph, process.stdout.columns));
47
50
 
48
51
  ## API
49
52
 
50
- ### cliTruncate(input, columns, [options])
53
+ ### cliTruncate(text, columns, options?)
51
54
 
52
- #### input
55
+ #### text
53
56
 
54
57
  Type: `string`
55
58
 
@@ -63,23 +66,65 @@ Columns to occupy in the terminal.
63
66
 
64
67
  #### options
65
68
 
66
- Type: `Object`
69
+ Type: `object`
67
70
 
68
71
  ##### position
69
72
 
70
73
  Type: `string`<br>
71
- Default: `end`<br>
72
- Values: `start` `middle` `end`
74
+ Default: `'end'`<br>
75
+ Values: `'start'` `'middle'` `'end'`
73
76
 
74
77
  Position to truncate the string.
75
78
 
79
+ ##### space
76
80
 
77
- ## Related
81
+ Type: `boolean`<br>
82
+ Default: `false`
78
83
 
79
- - [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
80
- - [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
84
+ Add a space between the text and the ellipsis.
85
+
86
+ ```js
87
+ cliTruncate('unicorns', 5, {space: false});
88
+ //=> 'unic…'
81
89
 
90
+ cliTruncate('unicorns', 5, {space: true});
91
+ //=> 'uni …'
82
92
 
83
- ## License
93
+ cliTruncate('unicorns', 6, {position: 'start', space: true});
94
+ //=> '… orns'
84
95
 
85
- MIT © [Sindre Sorhus](https://sindresorhus.com)
96
+ cliTruncate('unicorns', 7, {position: 'middle', space: true});
97
+ //=> 'uni … s'
98
+ ```
99
+
100
+ ##### preferTruncationOnSpace
101
+
102
+ Type: `boolean`<br>
103
+ Default: `false`
104
+
105
+ Truncate the string from a whitespace if it is within 3 characters from the actual breaking point.
106
+
107
+ ```js
108
+ cliTruncate('unicorns rainbow dragons', 20, {position: 'start', preferTruncationOnSpace: true})
109
+ //=> '…rainbow dragons'
110
+
111
+ // without preferTruncationOnSpace
112
+ cliTruncate('unicorns rainbow dragons', 20, {position: 'start'})
113
+ //=> '…rns rainbow dragons'
114
+
115
+ cliTruncate('unicorns rainbow dragons', 20, {position: 'middle', preferTruncationOnSpace: true})
116
+ //=> 'unicorns…dragons'
117
+
118
+ cliTruncate('unicorns rainbow dragons', 6, {position: 'end', preferTruncationOnSpace: true})
119
+ //=> 'unico…'
120
+
121
+ // preferTruncationOnSpace would have no effect if space isn't found within next 3 indexes
122
+ cliTruncate('unicorns rainbow dragons', 6, {position: 'middle', preferTruncationOnSpace: true})
123
+ //=> 'uni…ns'
124
+ ```
125
+
126
+
127
+ ## Related
128
+
129
+ - [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
130
+ - [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes