wrap-ansi 6.2.0 → 7.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.js +51 -21
  2. package/license +1 -1
  3. package/package.json +8 -7
  4. package/readme.md +4 -10
package/index.js CHANGED
@@ -10,7 +10,14 @@ const ESCAPES = new Set([
10
10
 
11
11
  const END_CODE = 39;
12
12
 
13
- const wrapAnsi = code => `${ESCAPES.values().next().value}[${code}m`;
13
+ const ANSI_ESCAPE_BELL = '\u0007';
14
+ const ANSI_CSI = '[';
15
+ const ANSI_OSC = ']';
16
+ const ANSI_SGR_TERMINATOR = 'm';
17
+ const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
18
+
19
+ const wrapAnsi = code => `${ESCAPES.values().next().value}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
20
+ const wrapAnsiHyperlink = uri => `${ESCAPES.values().next().value}${ANSI_ESCAPE_LINK}${uri}${ANSI_ESCAPE_BELL}`;
14
21
 
15
22
  // Calculate the length of words split on ' ', ignoring
16
23
  // the extra characters added by ansi escape codes
@@ -22,6 +29,7 @@ const wrapWord = (rows, word, columns) => {
22
29
  const characters = [...word];
23
30
 
24
31
  let isInsideEscape = false;
32
+ let isInsideLinkEscape = false;
25
33
  let visible = stringWidth(stripAnsi(rows[rows.length - 1]));
26
34
 
27
35
  for (const [index, character] of characters.entries()) {
@@ -36,12 +44,19 @@ const wrapWord = (rows, word, columns) => {
36
44
 
37
45
  if (ESCAPES.has(character)) {
38
46
  isInsideEscape = true;
39
- } else if (isInsideEscape && character === 'm') {
40
- isInsideEscape = false;
41
- continue;
47
+ isInsideLinkEscape = characters.slice(index + 1).join('').startsWith(ANSI_ESCAPE_LINK);
42
48
  }
43
49
 
44
50
  if (isInsideEscape) {
51
+ if (isInsideLinkEscape) {
52
+ if (character === ANSI_ESCAPE_BELL) {
53
+ isInsideEscape = false;
54
+ isInsideLinkEscape = false;
55
+ }
56
+ } else if (character === ANSI_SGR_TERMINATOR) {
57
+ isInsideEscape = false;
58
+ }
59
+
45
60
  continue;
46
61
  }
47
62
 
@@ -61,8 +76,8 @@ const wrapWord = (rows, word, columns) => {
61
76
  };
62
77
 
63
78
  // Trims spaces from a string ignoring invisible sequences
64
- const stringVisibleTrimSpacesRight = str => {
65
- const words = str.split(' ');
79
+ const stringVisibleTrimSpacesRight = string => {
80
+ const words = string.split(' ');
66
81
  let last = words.length;
67
82
 
68
83
  while (last > 0) {
@@ -74,7 +89,7 @@ const stringVisibleTrimSpacesRight = str => {
74
89
  }
75
90
 
76
91
  if (last === words.length) {
77
- return str;
92
+ return string;
78
93
  }
79
94
 
80
95
  return words.slice(0, last).join(' ') + words.slice(last).join('');
@@ -90,16 +105,16 @@ const exec = (string, columns, options = {}) => {
90
105
  return '';
91
106
  }
92
107
 
93
- let pre = '';
94
- let ret = '';
108
+ let returnValue = '';
95
109
  let escapeCode;
110
+ let escapeUrl;
96
111
 
97
112
  const lengths = wordLengths(string);
98
113
  let rows = [''];
99
114
 
100
115
  for (const [index, word] of string.split(' ').entries()) {
101
116
  if (options.trim !== false) {
102
- rows[rows.length - 1] = rows[rows.length - 1].trimLeft();
117
+ rows[rows.length - 1] = rows[rows.length - 1].trimStart();
103
118
  }
104
119
 
105
120
  let rowLength = stringWidth(rows[rows.length - 1]);
@@ -151,28 +166,43 @@ const exec = (string, columns, options = {}) => {
151
166
  rows = rows.map(stringVisibleTrimSpacesRight);
152
167
  }
153
168
 
154
- pre = rows.join('\n');
169
+ const pre = [...rows.join('\n')];
155
170
 
156
- for (const [index, character] of [...pre].entries()) {
157
- ret += character;
171
+ for (const [index, character] of pre.entries()) {
172
+ returnValue += character;
158
173
 
159
174
  if (ESCAPES.has(character)) {
160
- const code = parseFloat(/\d[^m]*/.exec(pre.slice(index, index + 4)));
161
- escapeCode = code === END_CODE ? null : code;
175
+ const {groups} = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`).exec(pre.slice(index).join('')) || {groups: {}};
176
+ if (groups.code !== undefined) {
177
+ const code = Number.parseFloat(groups.code);
178
+ escapeCode = code === END_CODE ? undefined : code;
179
+ } else if (groups.uri !== undefined) {
180
+ escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
181
+ }
162
182
  }
163
183
 
164
184
  const code = ansiStyles.codes.get(Number(escapeCode));
165
185
 
166
- if (escapeCode && code) {
167
- if (pre[index + 1] === '\n') {
168
- ret += wrapAnsi(code);
169
- } else if (character === '\n') {
170
- ret += wrapAnsi(escapeCode);
186
+ if (pre[index + 1] === '\n') {
187
+ if (escapeUrl) {
188
+ returnValue += wrapAnsiHyperlink('');
189
+ }
190
+
191
+ if (escapeCode && code) {
192
+ returnValue += wrapAnsi(code);
193
+ }
194
+ } else if (character === '\n') {
195
+ if (escapeCode && code) {
196
+ returnValue += wrapAnsi(escapeCode);
197
+ }
198
+
199
+ if (escapeUrl) {
200
+ returnValue += wrapAnsiHyperlink(escapeUrl);
171
201
  }
172
202
  }
173
203
  }
174
204
 
175
- return ret;
205
+ return returnValue;
176
206
  };
177
207
 
178
208
  // For each newline, invoke the method separately
package/license CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
3
+ Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "wrap-ansi",
3
- "version": "6.2.0",
3
+ "version": "7.0.0",
4
4
  "description": "Wordwrap a string with ANSI escape codes",
5
5
  "license": "MIT",
6
6
  "repository": "chalk/wrap-ansi",
7
+ "funding": "https://github.com/chalk/wrap-ansi?sponsor=1",
7
8
  "author": {
8
9
  "name": "Sindre Sorhus",
9
10
  "email": "sindresorhus@gmail.com",
10
- "url": "sindresorhus.com"
11
+ "url": "https://sindresorhus.com"
11
12
  },
12
13
  "engines": {
13
- "node": ">=8"
14
+ "node": ">=10"
14
15
  },
15
16
  "scripts": {
16
17
  "test": "xo && nyc ava"
@@ -52,10 +53,10 @@
52
53
  },
53
54
  "devDependencies": {
54
55
  "ava": "^2.1.0",
55
- "chalk": "^2.4.2",
56
+ "chalk": "^4.0.0",
56
57
  "coveralls": "^3.0.3",
57
- "has-ansi": "^3.0.0",
58
- "nyc": "^14.1.1",
59
- "xo": "^0.24.0"
58
+ "has-ansi": "^4.0.0",
59
+ "nyc": "^15.0.1",
60
+ "xo": "^0.29.1"
60
61
  }
61
62
  }
package/readme.md CHANGED
@@ -1,15 +1,13 @@
1
- # wrap-ansi [![Build Status](https://travis-ci.org/chalk/wrap-ansi.svg?branch=master)](https://travis-ci.org/chalk/wrap-ansi) [![Coverage Status](https://coveralls.io/repos/github/chalk/wrap-ansi/badge.svg?branch=master)](https://coveralls.io/github/chalk/wrap-ansi?branch=master)
1
+ # wrap-ansi [![Build Status](https://travis-ci.com/chalk/wrap-ansi.svg?branch=master)](https://travis-ci.com/chalk/wrap-ansi) [![Coverage Status](https://coveralls.io/repos/github/chalk/wrap-ansi/badge.svg?branch=master)](https://coveralls.io/github/chalk/wrap-ansi?branch=master)
2
2
 
3
3
  > Wordwrap a string with [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles)
4
4
 
5
-
6
5
  ## Install
7
6
 
8
7
  ```
9
8
  $ npm install wrap-ansi
10
9
  ```
11
10
 
12
-
13
11
  ## Usage
14
12
 
15
13
  ```js
@@ -24,7 +22,6 @@ console.log(wrapAnsi(input, 20));
24
22
 
25
23
  <img width="331" src="screenshot.png">
26
24
 
27
-
28
25
  ## API
29
26
 
30
27
  ### wrapAnsi(string, columns, options?)
@@ -49,26 +46,25 @@ Type: `object`
49
46
 
50
47
  ##### hard
51
48
 
52
- Type: `boolean`<br>
49
+ Type: `boolean`\
53
50
  Default: `false`
54
51
 
55
52
  By default the wrap is soft, meaning long words may extend past the column width. Setting this to `true` will make it hard wrap at the column width.
56
53
 
57
54
  ##### wordWrap
58
55
 
59
- Type: `boolean`<br>
56
+ Type: `boolean`\
60
57
  Default: `true`
61
58
 
62
59
  By default, an attempt is made to split words at spaces, ensuring that they don't extend past the configured columns. If wordWrap is `false`, each column will instead be completely filled splitting words as necessary.
63
60
 
64
61
  ##### trim
65
62
 
66
- Type: `boolean`<br>
63
+ Type: `boolean`\
67
64
  Default: `true`
68
65
 
69
66
  Whitespace on all lines is removed by default. Set this option to `false` if you don't want to trim.
70
67
 
71
-
72
68
  ## Related
73
69
 
74
70
  - [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
@@ -76,14 +72,12 @@ Whitespace on all lines is removed by default. Set this option to `false` if you
76
72
  - [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
77
73
  - [jsesc](https://github.com/mathiasbynens/jsesc) - Generate ASCII-only output from Unicode strings. Useful for creating test fixtures.
78
74
 
79
-
80
75
  ## Maintainers
81
76
 
82
77
  - [Sindre Sorhus](https://github.com/sindresorhus)
83
78
  - [Josh Junon](https://github.com/qix-)
84
79
  - [Benjamin Coe](https://github.com/bcoe)
85
80
 
86
-
87
81
  ---
88
82
 
89
83
  <div align="center">