wrap-ansi 5.0.0 → 6.2.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 (3) hide show
  1. package/index.js +41 -17
  2. package/package.json +7 -7
  3. package/readme.md +14 -6
package/index.js CHANGED
@@ -21,7 +21,7 @@ const wordLengths = string => string.split(' ').map(character => stringWidth(cha
21
21
  const wrapWord = (rows, word, columns) => {
22
22
  const characters = [...word];
23
23
 
24
- let insideEscape = false;
24
+ let isInsideEscape = false;
25
25
  let visible = stringWidth(stripAnsi(rows[rows.length - 1]));
26
26
 
27
27
  for (const [index, character] of characters.entries()) {
@@ -35,13 +35,13 @@ const wrapWord = (rows, word, columns) => {
35
35
  }
36
36
 
37
37
  if (ESCAPES.has(character)) {
38
- insideEscape = true;
39
- } else if (insideEscape && character === 'm') {
40
- insideEscape = false;
38
+ isInsideEscape = true;
39
+ } else if (isInsideEscape && character === 'm') {
40
+ isInsideEscape = false;
41
41
  continue;
42
42
  }
43
43
 
44
- if (insideEscape) {
44
+ if (isInsideEscape) {
45
45
  continue;
46
46
  }
47
47
 
@@ -60,11 +60,29 @@ const wrapWord = (rows, word, columns) => {
60
60
  }
61
61
  };
62
62
 
63
- // The wrap-ansi module can be invoked
64
- // in either 'hard' or 'soft' wrap mode
63
+ // Trims spaces from a string ignoring invisible sequences
64
+ const stringVisibleTrimSpacesRight = str => {
65
+ const words = str.split(' ');
66
+ let last = words.length;
67
+
68
+ while (last > 0) {
69
+ if (stringWidth(words[last - 1]) > 0) {
70
+ break;
71
+ }
72
+
73
+ last--;
74
+ }
75
+
76
+ if (last === words.length) {
77
+ return str;
78
+ }
79
+
80
+ return words.slice(0, last).join(' ') + words.slice(last).join('');
81
+ };
82
+
83
+ // The wrap-ansi module can be invoked in either 'hard' or 'soft' wrap mode
65
84
  //
66
- // 'hard' will never allow a string to take up more
67
- // than columns characters
85
+ // 'hard' will never allow a string to take up more than columns characters
68
86
  //
69
87
  // 'soft' allows long words to expand past the column length
70
88
  const exec = (string, columns, options = {}) => {
@@ -77,7 +95,7 @@ const exec = (string, columns, options = {}) => {
77
95
  let escapeCode;
78
96
 
79
97
  const lengths = wordLengths(string);
80
- const rows = [''];
98
+ let rows = [''];
81
99
 
82
100
  for (const [index, word] of string.split(' ').entries()) {
83
101
  if (options.trim !== false) {
@@ -87,18 +105,19 @@ const exec = (string, columns, options = {}) => {
87
105
  let rowLength = stringWidth(rows[rows.length - 1]);
88
106
 
89
107
  if (index !== 0) {
90
- if (rowLength === columns && (options.wordWrap === false || options.trim === false)) {
108
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
91
109
  // If we start with a new word but the current row length equals the length of the columns, add a new row
92
110
  rows.push('');
93
111
  rowLength = 0;
94
112
  }
95
113
 
96
- rows[rows.length - 1] += ' ';
97
- rowLength++;
114
+ if (rowLength > 0 || options.trim === false) {
115
+ rows[rows.length - 1] += ' ';
116
+ rowLength++;
117
+ }
98
118
  }
99
119
 
100
- // In 'hard' wrap mode, the length of a line is
101
- // never allowed to extend past 'columns'
120
+ // In 'hard' wrap mode, the length of a line is never allowed to extend past 'columns'
102
121
  if (options.hard && lengths[index] > columns) {
103
122
  const remainingColumns = (columns - rowLength);
104
123
  const breaksStartingThisLine = 1 + Math.floor((lengths[index] - remainingColumns - 1) / columns);
@@ -111,7 +130,7 @@ const exec = (string, columns, options = {}) => {
111
130
  continue;
112
131
  }
113
132
 
114
- if (rowLength + lengths[index] > columns && rowLength > 0) {
133
+ if (rowLength + lengths[index] > columns && rowLength > 0 && lengths[index] > 0) {
115
134
  if (options.wordWrap === false && rowLength < columns) {
116
135
  wrapWord(rows, word, columns);
117
136
  continue;
@@ -128,7 +147,11 @@ const exec = (string, columns, options = {}) => {
128
147
  rows[rows.length - 1] += word;
129
148
  }
130
149
 
131
- pre = rows.map(row => options.trim === false ? row : row.trim()).join('\n');
150
+ if (options.trim !== false) {
151
+ rows = rows.map(stringVisibleTrimSpacesRight);
152
+ }
153
+
154
+ pre = rows.join('\n');
132
155
 
133
156
  for (const [index, character] of [...pre].entries()) {
134
157
  ret += character;
@@ -156,6 +179,7 @@ const exec = (string, columns, options = {}) => {
156
179
  module.exports = (string, columns, options) => {
157
180
  return String(string)
158
181
  .normalize()
182
+ .replace(/\r\n/g, '\n')
159
183
  .split('\n')
160
184
  .map(line => exec(line, columns, options))
161
185
  .join('\n');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrap-ansi",
3
- "version": "5.0.0",
3
+ "version": "6.2.0",
4
4
  "description": "Wordwrap a string with ANSI escape codes",
5
5
  "license": "MIT",
6
6
  "repository": "chalk/wrap-ansi",
@@ -10,7 +10,7 @@
10
10
  "url": "sindresorhus.com"
11
11
  },
12
12
  "engines": {
13
- "node": ">=6"
13
+ "node": ">=8"
14
14
  },
15
15
  "scripts": {
16
16
  "test": "xo && nyc ava"
@@ -46,16 +46,16 @@
46
46
  "text"
47
47
  ],
48
48
  "dependencies": {
49
- "ansi-styles": "^3.2.0",
50
- "string-width": "^3.0.0",
51
- "strip-ansi": "^5.0.0"
49
+ "ansi-styles": "^4.0.0",
50
+ "string-width": "^4.1.0",
51
+ "strip-ansi": "^6.0.0"
52
52
  },
53
53
  "devDependencies": {
54
- "ava": "^1.2.1",
54
+ "ava": "^2.1.0",
55
55
  "chalk": "^2.4.2",
56
56
  "coveralls": "^3.0.3",
57
57
  "has-ansi": "^3.0.0",
58
- "nyc": "^13.3.0",
58
+ "nyc": "^14.1.1",
59
59
  "xo": "^0.24.0"
60
60
  }
61
61
  }
package/readme.md CHANGED
@@ -27,15 +27,15 @@ console.log(wrapAnsi(input, 20));
27
27
 
28
28
  ## API
29
29
 
30
- ### wrapAnsi(input, columns, [options])
30
+ ### wrapAnsi(string, columns, options?)
31
31
 
32
32
  Wrap words to the specified column width.
33
33
 
34
- #### input
34
+ #### string
35
35
 
36
36
  Type: `string`
37
37
 
38
- String with ANSI escape codes. Like one styled by [`chalk`](https://github.com/chalk/chalk).
38
+ String with ANSI escape codes. Like one styled by [`chalk`](https://github.com/chalk/chalk). Newline characters will be normalized to `\n`.
39
39
 
40
40
  #### columns
41
41
 
@@ -45,7 +45,7 @@ Number of columns to wrap the text to.
45
45
 
46
46
  #### options
47
47
 
48
- Type: `Object`
48
+ Type: `object`
49
49
 
50
50
  ##### hard
51
51
 
@@ -84,6 +84,14 @@ Whitespace on all lines is removed by default. Set this option to `false` if you
84
84
  - [Benjamin Coe](https://github.com/bcoe)
85
85
 
86
86
 
87
- ## License
87
+ ---
88
88
 
89
- MIT
89
+ <div align="center">
90
+ <b>
91
+ <a href="https://tidelift.com/subscription/pkg/npm-wrap_ansi?utm_source=npm-wrap-ansi&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
92
+ </b>
93
+ <br>
94
+ <sub>
95
+ Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
96
+ </sub>
97
+ </div>