@rushstack/terminal 0.7.8 → 0.7.10
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.
- package/LICENSE +24 -24
- package/README.md +53 -53
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/CallbackWritable.js.map +1 -1
- package/lib/DiscardStdoutTransform.js.map +1 -1
- package/lib/ITerminalChunk.js.map +1 -1
- package/lib/MockWritable.js.map +1 -1
- package/lib/NormalizeNewlinesTextRewriter.js.map +1 -1
- package/lib/PrintUtilities.js.map +1 -1
- package/lib/RemoveColorsTextRewriter.js.map +1 -1
- package/lib/SplitterTransform.js.map +1 -1
- package/lib/StdioLineTransform.js.map +1 -1
- package/lib/StdioSummarizer.js.map +1 -1
- package/lib/StdioWritable.js.map +1 -1
- package/lib/TerminalTransform.js.map +1 -1
- package/lib/TerminalWritable.js.map +1 -1
- package/lib/TextRewriter.js.map +1 -1
- package/lib/TextRewriterTransform.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
package/LICENSE
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
@rushstack/terminal
|
|
2
|
-
|
|
3
|
-
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
-
|
|
5
|
-
MIT License
|
|
6
|
-
|
|
7
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
8
|
-
a copy of this software and associated documentation files (the
|
|
9
|
-
"Software"), to deal in the Software without restriction, including
|
|
10
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
11
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
12
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
13
|
-
the following conditions:
|
|
14
|
-
|
|
15
|
-
The above copyright notice and this permission notice shall be
|
|
16
|
-
included in all copies or substantial portions of the Software.
|
|
17
|
-
|
|
18
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
19
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
20
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
21
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
22
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
23
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
24
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
@rushstack/terminal
|
|
2
|
+
|
|
3
|
+
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
|
|
5
|
+
MIT License
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
8
|
+
a copy of this software and associated documentation files (the
|
|
9
|
+
"Software"), to deal in the Software without restriction, including
|
|
10
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
11
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
12
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
13
|
+
the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be
|
|
16
|
+
included in all copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
19
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
20
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
21
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
22
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
23
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
24
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
# @rushstack/terminal
|
|
2
|
-
|
|
3
|
-
This library implements a system for processing human readable text that
|
|
4
|
-
will be output by console applications.
|
|
5
|
-
|
|
6
|
-
The design is based loosely on the `WritableStream` and `TransformStream` classes from
|
|
7
|
-
the system [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Concepts),
|
|
8
|
-
except that instead of asynchronous byte streams, the `TerminalWritable` system synchronously transmits
|
|
9
|
-
human readable messages intended to be rendered on a text console or log file.
|
|
10
|
-
|
|
11
|
-
Consider a console application whose output may need to be processed in different ways
|
|
12
|
-
before finally being output. The conceptual block diagram might look like this:
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
[Terminal API]
|
|
16
|
-
|
|
|
17
|
-
V
|
|
18
|
-
[normalize newlines]
|
|
19
|
-
|
|
|
20
|
-
V
|
|
21
|
-
+----[splitter]-------+
|
|
22
|
-
| |
|
|
23
|
-
V V
|
|
24
|
-
[shell console] [remove ANSI colors]
|
|
25
|
-
|
|
|
26
|
-
V
|
|
27
|
-
[write to build.log]
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
The application uses the `Terminal` API to print `stdout` and `stderr` messages, for example with standardized
|
|
31
|
-
formatting for errors and warnings, and ANSI escapes to make nice colors. Maybe it also includes text
|
|
32
|
-
received from external processes, whose newlines may be inconsistent. Ultimately we want to write the
|
|
33
|
-
output to the shell console and a `build.log` file, but we don't want to put ANSI colors in the build log.
|
|
34
|
-
|
|
35
|
-
For the above example, `[shell console]` and `[write to build.log]` would be modeled as subclasses of
|
|
36
|
-
`TerminalWritable`. The `[normalize newlines]` and `[remove ANSI colors]` steps are modeled as subclasses
|
|
37
|
-
of `TerminalTransform`, because they output to a "destination" object. The `[splitter]` would be
|
|
38
|
-
implemented using `SplitterTransform`.
|
|
39
|
-
|
|
40
|
-
The stream of messages are {@link ITerminalChunk} objects, which can represent both `stdout` and `stderr`
|
|
41
|
-
channels. The pipeline operates synchronously on each chunk, but by processing one chunk at a time,
|
|
42
|
-
it avoids storing the entire output in memory. This means that operations like `[remove ANSI colors]`
|
|
43
|
-
cannot be simple regular expressions -- they must be implemented as state machines (`TextRewriter` subclasses)
|
|
44
|
-
capable of matching substrings that span multiple chunks.
|
|
45
|
-
|
|
46
|
-
## Links
|
|
47
|
-
|
|
48
|
-
- [CHANGELOG.md](
|
|
49
|
-
https://github.com/microsoft/rushstack/blob/main/libraries/terminal/CHANGELOG.md) - Find
|
|
50
|
-
out what's new in the latest version
|
|
51
|
-
- [API Reference](https://rushstack.io/pages/api/terminal/)
|
|
52
|
-
|
|
53
|
-
`@rushstack/terminal` is part of the [Rush Stack](https://rushstack.io/) family of projects.
|
|
1
|
+
# @rushstack/terminal
|
|
2
|
+
|
|
3
|
+
This library implements a system for processing human readable text that
|
|
4
|
+
will be output by console applications.
|
|
5
|
+
|
|
6
|
+
The design is based loosely on the `WritableStream` and `TransformStream` classes from
|
|
7
|
+
the system [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Concepts),
|
|
8
|
+
except that instead of asynchronous byte streams, the `TerminalWritable` system synchronously transmits
|
|
9
|
+
human readable messages intended to be rendered on a text console or log file.
|
|
10
|
+
|
|
11
|
+
Consider a console application whose output may need to be processed in different ways
|
|
12
|
+
before finally being output. The conceptual block diagram might look like this:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
[Terminal API]
|
|
16
|
+
|
|
|
17
|
+
V
|
|
18
|
+
[normalize newlines]
|
|
19
|
+
|
|
|
20
|
+
V
|
|
21
|
+
+----[splitter]-------+
|
|
22
|
+
| |
|
|
23
|
+
V V
|
|
24
|
+
[shell console] [remove ANSI colors]
|
|
25
|
+
|
|
|
26
|
+
V
|
|
27
|
+
[write to build.log]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The application uses the `Terminal` API to print `stdout` and `stderr` messages, for example with standardized
|
|
31
|
+
formatting for errors and warnings, and ANSI escapes to make nice colors. Maybe it also includes text
|
|
32
|
+
received from external processes, whose newlines may be inconsistent. Ultimately we want to write the
|
|
33
|
+
output to the shell console and a `build.log` file, but we don't want to put ANSI colors in the build log.
|
|
34
|
+
|
|
35
|
+
For the above example, `[shell console]` and `[write to build.log]` would be modeled as subclasses of
|
|
36
|
+
`TerminalWritable`. The `[normalize newlines]` and `[remove ANSI colors]` steps are modeled as subclasses
|
|
37
|
+
of `TerminalTransform`, because they output to a "destination" object. The `[splitter]` would be
|
|
38
|
+
implemented using `SplitterTransform`.
|
|
39
|
+
|
|
40
|
+
The stream of messages are {@link ITerminalChunk} objects, which can represent both `stdout` and `stderr`
|
|
41
|
+
channels. The pipeline operates synchronously on each chunk, but by processing one chunk at a time,
|
|
42
|
+
it avoids storing the entire output in memory. This means that operations like `[remove ANSI colors]`
|
|
43
|
+
cannot be simple regular expressions -- they must be implemented as state machines (`TextRewriter` subclasses)
|
|
44
|
+
capable of matching substrings that span multiple chunks.
|
|
45
|
+
|
|
46
|
+
## Links
|
|
47
|
+
|
|
48
|
+
- [CHANGELOG.md](
|
|
49
|
+
https://github.com/microsoft/rushstack/blob/main/libraries/terminal/CHANGELOG.md) - Find
|
|
50
|
+
out what's new in the latest version
|
|
51
|
+
- [API Reference](https://rushstack.io/pages/api/terminal/)
|
|
52
|
+
|
|
53
|
+
`@rushstack/terminal` is part of the [Rush Stack](https://rushstack.io/) family of projects.
|
package/dist/tsdoc-metadata.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallbackWritable.js","sourceRoot":"","sources":["../src/CallbackWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAsD;AAWtD;;;;;;;;;;;;;GAaG;AACH,MAAa,gBAAiB,SAAQ,mCAAgB;IAGpD,YAAmB,OAAiC;QAClD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC;IACxC,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;CACF;AAXD,4CAWC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { TerminalWritable } from './TerminalWritable';\nimport type { ITerminalChunk } from './ITerminalChunk';\n\n/**\n * Constructor options for {@link CallbackWritable}.\n * @public\n */\nexport interface ICallbackWritableOptions {\n onWriteChunk: (chunk: ITerminalChunk) => void;\n}\n\n/**\n * This class enables very basic {@link TerminalWritable.onWriteChunk} operations to be implemented\n * as a callback function, avoiding the need to define a subclass of `TerminalWritable`.\n *\n * @remarks\n * `CallbackWritable` is provided as a convenience for very simple situations. For most cases,\n * it is generally preferable to create a proper subclass.\n *\n * @privateRemarks\n * We intentionally do not expose a callback for {@link TerminalWritable.onClose}; if special\n * close behavior is required, it is better to create a subclass.\n *\n * @public\n */\nexport class CallbackWritable extends TerminalWritable {\n private readonly _callback: (chunk: ITerminalChunk) => void;\n\n public constructor(options: ICallbackWritableOptions) {\n super();\n this._callback = options.onWriteChunk;\n }\n\n protected onWriteChunk(chunk: ITerminalChunk): void {\n this._callback(chunk);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CallbackWritable.js","sourceRoot":"","sources":["../src/CallbackWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAsD;AAWtD;;;;;;;;;;;;;GAaG;AACH,MAAa,gBAAiB,SAAQ,mCAAgB;IAGpD,YAAmB,OAAiC;QAClD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC;IACxC,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;CACF;AAXD,4CAWC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { TerminalWritable } from './TerminalWritable';\r\nimport type { ITerminalChunk } from './ITerminalChunk';\r\n\r\n/**\r\n * Constructor options for {@link CallbackWritable}.\r\n * @public\r\n */\r\nexport interface ICallbackWritableOptions {\r\n onWriteChunk: (chunk: ITerminalChunk) => void;\r\n}\r\n\r\n/**\r\n * This class enables very basic {@link TerminalWritable.onWriteChunk} operations to be implemented\r\n * as a callback function, avoiding the need to define a subclass of `TerminalWritable`.\r\n *\r\n * @remarks\r\n * `CallbackWritable` is provided as a convenience for very simple situations. For most cases,\r\n * it is generally preferable to create a proper subclass.\r\n *\r\n * @privateRemarks\r\n * We intentionally do not expose a callback for {@link TerminalWritable.onClose}; if special\r\n * close behavior is required, it is better to create a subclass.\r\n *\r\n * @public\r\n */\r\nexport class CallbackWritable extends TerminalWritable {\r\n private readonly _callback: (chunk: ITerminalChunk) => void;\r\n\r\n public constructor(options: ICallbackWritableOptions) {\r\n super();\r\n this._callback = options.onWriteChunk;\r\n }\r\n\r\n protected onWriteChunk(chunk: ITerminalChunk): void {\r\n this._callback(chunk);\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscardStdoutTransform.js","sourceRoot":"","sources":["../src/DiscardStdoutTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAG3D,2DAAwF;AASxF,IAAK,KAIJ;AAJD,WAAK,KAAK;IACR,iCAAI,CAAA;IACJ,qDAAc,CAAA;IACd,qDAAc,CAAA;AAChB,CAAC,EAJI,KAAK,KAAL,KAAK,QAIT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAa,sBAAuB,SAAQ,qCAAiB;IAG3D,YAAmB,OAAuC;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;IAC3B,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;SACnF;QAED,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAC3C,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,cAAc,EAAE;gBACxC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACjC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;iBACpC;aACF;SACF;aAAM,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAClD,IAAI,aAAqB,CAAC;YAC1B,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,cAAc,EAAE;gBACxC,aAAa,GAAG,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;aACnC;iBAAM;gBACL,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC;aAC5B;YAED,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,IAAI,oCAA0B,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;YAErF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC5B,IAAI,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;oBACpD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;iBAC1B;qBAAM;oBACL,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;iBACpC;aACF;SACF;aAAM;YACL,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;SACpC;IACH,CAAC;CACF;AAzCD,wDAyCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\nimport { TerminalTransform, type ITerminalTransformOptions } from './TerminalTransform';\n\n/**\n * Constructor options for {@link DiscardStdoutTransform}\n *\n * @beta\n */\nexport interface IDiscardStdoutTransformOptions extends ITerminalTransformOptions {}\n\nenum State {\n Okay,\n StderrFragment,\n InsertLinefeed\n}\n\n/**\n * `DiscardStdoutTransform` discards `stdout` chunks while fixing up malformed `stderr` lines.\n *\n * @remarks\n * Suppose that a poorly behaved process produces output like this:\n *\n * ```ts\n * process.stdout.write('Starting operation...\\n');\n * process.stderr.write('An error occurred');\n * process.stdout.write('\\nFinishing up\\n');\n * process.stderr.write('The process completed with errors\\n');\n * ```\n *\n * When `stdout` and `stderr` are combined on the console, the mistake in the output would not be noticeable:\n * ```\n * Starting operation...\n * An error occurred\n * Finishing up\n * The process completed with errors\n * ```\n *\n * However, if we discard `stdout`, then `stderr` is missing a newline:\n * ```\n * An error occurredThe process completed with errors\n * ```\n *\n * Tooling scripts can introduce these sorts of problems via edge cases that are difficult to find and fix.\n * `DiscardStdoutTransform` can discard the `stdout` stream and fix up `stderr`:\n *\n * ```\n * An error occurred\n * The process completed with errors\n * ```\n *\n * @privateRemarks\n * This class is experimental and marked as `@beta`. The algorithm may need some fine-tuning, or there may\n * be better solutions to this problem.\n *\n * @beta\n */\nexport class DiscardStdoutTransform extends TerminalTransform {\n private _state: State;\n\n public constructor(options: IDiscardStdoutTransformOptions) {\n super(options);\n\n this._state = State.Okay;\n }\n\n protected onWriteChunk(chunk: ITerminalChunk): void {\n if (chunk.text.indexOf('\\r') >= 0) {\n throw new Error('DiscardStdoutTransform expects chunks with normalized newlines');\n }\n\n if (chunk.kind === TerminalChunkKind.Stdout) {\n if (this._state === State.StderrFragment) {\n if (chunk.text.indexOf('\\n') >= 0) {\n this._state = State.InsertLinefeed;\n }\n }\n } else if (chunk.kind === TerminalChunkKind.Stderr) {\n let correctedText: string;\n if (this._state === State.InsertLinefeed) {\n correctedText = '\\n' + chunk.text;\n } else {\n correctedText = chunk.text;\n }\n\n this.destination.writeChunk({ kind: TerminalChunkKind.Stderr, text: correctedText });\n\n if (correctedText.length > 0) {\n if (correctedText[correctedText.length - 1] === '\\n') {\n this._state = State.Okay;\n } else {\n this._state = State.StderrFragment;\n }\n }\n } else {\n this.destination.writeChunk(chunk);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DiscardStdoutTransform.js","sourceRoot":"","sources":["../src/DiscardStdoutTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAG3D,2DAAwF;AASxF,IAAK,KAIJ;AAJD,WAAK,KAAK;IACR,iCAAI,CAAA;IACJ,qDAAc,CAAA;IACd,qDAAc,CAAA;AAChB,CAAC,EAJI,KAAK,KAAL,KAAK,QAIT;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAa,sBAAuB,SAAQ,qCAAiB;IAG3D,YAAmB,OAAuC;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;IAC3B,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;SACnF;QAED,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAC3C,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,cAAc,EAAE;gBACxC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACjC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;iBACpC;aACF;SACF;aAAM,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAClD,IAAI,aAAqB,CAAC;YAC1B,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,cAAc,EAAE;gBACxC,aAAa,GAAG,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;aACnC;iBAAM;gBACL,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC;aAC5B;YAED,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,IAAI,oCAA0B,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;YAErF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC5B,IAAI,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,EAAE;oBACpD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;iBAC1B;qBAAM;oBACL,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC;iBACpC;aACF;SACF;aAAM;YACL,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;SACpC;IACH,CAAC;CACF;AAzCD,wDAyCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\r\nimport { TerminalTransform, type ITerminalTransformOptions } from './TerminalTransform';\r\n\r\n/**\r\n * Constructor options for {@link DiscardStdoutTransform}\r\n *\r\n * @beta\r\n */\r\nexport interface IDiscardStdoutTransformOptions extends ITerminalTransformOptions {}\r\n\r\nenum State {\r\n Okay,\r\n StderrFragment,\r\n InsertLinefeed\r\n}\r\n\r\n/**\r\n * `DiscardStdoutTransform` discards `stdout` chunks while fixing up malformed `stderr` lines.\r\n *\r\n * @remarks\r\n * Suppose that a poorly behaved process produces output like this:\r\n *\r\n * ```ts\r\n * process.stdout.write('Starting operation...\\n');\r\n * process.stderr.write('An error occurred');\r\n * process.stdout.write('\\nFinishing up\\n');\r\n * process.stderr.write('The process completed with errors\\n');\r\n * ```\r\n *\r\n * When `stdout` and `stderr` are combined on the console, the mistake in the output would not be noticeable:\r\n * ```\r\n * Starting operation...\r\n * An error occurred\r\n * Finishing up\r\n * The process completed with errors\r\n * ```\r\n *\r\n * However, if we discard `stdout`, then `stderr` is missing a newline:\r\n * ```\r\n * An error occurredThe process completed with errors\r\n * ```\r\n *\r\n * Tooling scripts can introduce these sorts of problems via edge cases that are difficult to find and fix.\r\n * `DiscardStdoutTransform` can discard the `stdout` stream and fix up `stderr`:\r\n *\r\n * ```\r\n * An error occurred\r\n * The process completed with errors\r\n * ```\r\n *\r\n * @privateRemarks\r\n * This class is experimental and marked as `@beta`. The algorithm may need some fine-tuning, or there may\r\n * be better solutions to this problem.\r\n *\r\n * @beta\r\n */\r\nexport class DiscardStdoutTransform extends TerminalTransform {\r\n private _state: State;\r\n\r\n public constructor(options: IDiscardStdoutTransformOptions) {\r\n super(options);\r\n\r\n this._state = State.Okay;\r\n }\r\n\r\n protected onWriteChunk(chunk: ITerminalChunk): void {\r\n if (chunk.text.indexOf('\\r') >= 0) {\r\n throw new Error('DiscardStdoutTransform expects chunks with normalized newlines');\r\n }\r\n\r\n if (chunk.kind === TerminalChunkKind.Stdout) {\r\n if (this._state === State.StderrFragment) {\r\n if (chunk.text.indexOf('\\n') >= 0) {\r\n this._state = State.InsertLinefeed;\r\n }\r\n }\r\n } else if (chunk.kind === TerminalChunkKind.Stderr) {\r\n let correctedText: string;\r\n if (this._state === State.InsertLinefeed) {\r\n correctedText = '\\n' + chunk.text;\r\n } else {\r\n correctedText = chunk.text;\r\n }\r\n\r\n this.destination.writeChunk({ kind: TerminalChunkKind.Stderr, text: correctedText });\r\n\r\n if (correctedText.length > 0) {\r\n if (correctedText[correctedText.length - 1] === '\\n') {\r\n this._state = State.Okay;\r\n } else {\r\n this._state = State.StderrFragment;\r\n }\r\n }\r\n } else {\r\n this.destination.writeChunk(chunk);\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ITerminalChunk.js","sourceRoot":"","sources":["../src/ITerminalChunk.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/**\n * Specifies the kind of data represented by a {@link ITerminalChunk} object.\n * @public\n */\nexport const enum TerminalChunkKind {\n /**\n * Indicates a `ITerminalChunk` object representing `stdout` console output.\n */\n Stdout = 'O',\n\n /**\n * Indicates a `ITerminalChunk` object representing `stderr` console output.\n */\n Stderr = 'E'\n}\n\n/**\n * Represents a chunk of output that will ultimately be written to a {@link TerminalWritable}.\n *\n * @remarks\n * Today `ITerminalChunk` represents the `stdout` and `stderr` text streams. In the future,\n * we plan to expand it to include other console UI elements such as instructions for displaying\n * an interactive progress bar. We may also add other metadata, for example tracking whether\n * the `text` string is known to contain color codes or not.\n *\n * The `ITerminalChunk` object should be considered to be immutable once it is created.\n * For example, {@link SplitterTransform} may pass the same chunk to multiple destinations.\n *\n * @public\n */\nexport interface ITerminalChunk {\n /**\n * Indicates the kind of information stored in this chunk.\n *\n * @remarks\n * More kinds will be introduced in the future. Implementors of\n * {@link TerminalWritable.onWriteChunk} should ignore unrecognized `TerminalChunkKind`\n * values. `TerminalTransform` implementors should pass along unrecognized chunks\n * rather than discarding them.\n */\n kind: TerminalChunkKind;\n\n /**\n * The next chunk of text from the `stderr` or `stdout` stream.\n */\n text: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ITerminalChunk.js","sourceRoot":"","sources":["../src/ITerminalChunk.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\n/**\r\n * Specifies the kind of data represented by a {@link ITerminalChunk} object.\r\n * @public\r\n */\r\nexport const enum TerminalChunkKind {\r\n /**\r\n * Indicates a `ITerminalChunk` object representing `stdout` console output.\r\n */\r\n Stdout = 'O',\r\n\r\n /**\r\n * Indicates a `ITerminalChunk` object representing `stderr` console output.\r\n */\r\n Stderr = 'E'\r\n}\r\n\r\n/**\r\n * Represents a chunk of output that will ultimately be written to a {@link TerminalWritable}.\r\n *\r\n * @remarks\r\n * Today `ITerminalChunk` represents the `stdout` and `stderr` text streams. In the future,\r\n * we plan to expand it to include other console UI elements such as instructions for displaying\r\n * an interactive progress bar. We may also add other metadata, for example tracking whether\r\n * the `text` string is known to contain color codes or not.\r\n *\r\n * The `ITerminalChunk` object should be considered to be immutable once it is created.\r\n * For example, {@link SplitterTransform} may pass the same chunk to multiple destinations.\r\n *\r\n * @public\r\n */\r\nexport interface ITerminalChunk {\r\n /**\r\n * Indicates the kind of information stored in this chunk.\r\n *\r\n * @remarks\r\n * More kinds will be introduced in the future. Implementors of\r\n * {@link TerminalWritable.onWriteChunk} should ignore unrecognized `TerminalChunkKind`\r\n * values. `TerminalTransform` implementors should pass along unrecognized chunks\r\n * rather than discarding them.\r\n */\r\n kind: TerminalChunkKind;\r\n\r\n /**\r\n * The next chunk of text from the `stderr` or `stdout` stream.\r\n */\r\n text: string;\r\n}\r\n"]}
|
package/lib/MockWritable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MockWritable.js","sourceRoot":"","sources":["../src/MockWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAG3D,yDAAsD;AACtD,oEAA0D;AAE1D;;;;GAIG;AACH,MAAa,YAAa,SAAQ,mCAAgB;IAAlD;;QACkB,WAAM,GAAqB,EAAE,CAAC;IAiBhD,CAAC;IAfW,YAAY,CAAC,KAAqB;QAC1C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAEM,YAAY;QACjB,OAAO,8BAAU,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEM,kBAAkB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,gCAAK,CAAC,KAAE,IAAI,EAAE,8BAAU,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAqB,CAAA,CAAC,CAAC;IACvG,CAAC;CACF;AAlBD,oCAkBC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { ITerminalChunk } from './ITerminalChunk';\nimport { TerminalWritable } from './TerminalWritable';\nimport { AnsiEscape } from '@rushstack/node-core-library';\n\n/**\n * A {@link TerminalWritable} subclass for use by unit tests.\n *\n * @beta\n */\nexport class MockWritable extends TerminalWritable {\n public readonly chunks: ITerminalChunk[] = [];\n\n protected onWriteChunk(chunk: ITerminalChunk): void {\n this.chunks.push(chunk);\n }\n\n public reset(): void {\n this.chunks.length = 0;\n }\n\n public getAllOutput(): string {\n return AnsiEscape.formatForTests(this.chunks.map((x) => x.text).join(''));\n }\n\n public getFormattedChunks(): ITerminalChunk[] {\n return this.chunks.map((x) => ({ ...x, text: AnsiEscape.formatForTests(x.text) } as ITerminalChunk));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MockWritable.js","sourceRoot":"","sources":["../src/MockWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAG3D,yDAAsD;AACtD,oEAA0D;AAE1D;;;;GAIG;AACH,MAAa,YAAa,SAAQ,mCAAgB;IAAlD;;QACkB,WAAM,GAAqB,EAAE,CAAC;IAiBhD,CAAC;IAfW,YAAY,CAAC,KAAqB;QAC1C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAEM,YAAY;QACjB,OAAO,8BAAU,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAEM,kBAAkB;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,gCAAK,CAAC,KAAE,IAAI,EAAE,8BAAU,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAqB,CAAA,CAAC,CAAC;IACvG,CAAC;CACF;AAlBD,oCAkBC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport type { ITerminalChunk } from './ITerminalChunk';\r\nimport { TerminalWritable } from './TerminalWritable';\r\nimport { AnsiEscape } from '@rushstack/node-core-library';\r\n\r\n/**\r\n * A {@link TerminalWritable} subclass for use by unit tests.\r\n *\r\n * @beta\r\n */\r\nexport class MockWritable extends TerminalWritable {\r\n public readonly chunks: ITerminalChunk[] = [];\r\n\r\n protected onWriteChunk(chunk: ITerminalChunk): void {\r\n this.chunks.push(chunk);\r\n }\r\n\r\n public reset(): void {\r\n this.chunks.length = 0;\r\n }\r\n\r\n public getAllOutput(): string {\r\n return AnsiEscape.formatForTests(this.chunks.map((x) => x.text).join(''));\r\n }\r\n\r\n public getFormattedChunks(): ITerminalChunk[] {\r\n return this.chunks.map((x) => ({ ...x, text: AnsiEscape.formatForTests(x.text) } as ITerminalChunk));\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NormalizeNewlinesTextRewriter.js","sourceRoot":"","sources":["../src/NormalizeNewlinesTextRewriter.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAsE;AACtE,iDAAsE;AA6BtE;;;;;GAKG;AACH,MAAa,6BAA8B,SAAQ,2BAAY;IAY7D,YAAmB,OAA8C;QAC/D,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,wBAAI,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC;IACzD,CAAC;IAEM,UAAU;QACf,OAAO;YACL,iBAAiB,EAAE,EAAE;YACrB,cAAc,EAAE,KAAK;SACiB,CAAC;IAC3C,CAAC;IAEM,OAAO,CAAC,YAA+B,EAAE,IAAY;QAC1D,MAAM,KAAK,GAAwC,YAAmD,CAAC;QAEvG,IAAI,MAAM,GAAW,EAAE,CAAC;QAExB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;YACnB,IAAI,CAAC,GAAW,CAAC,CAAC;YAElB,GAAG;gBACD,MAAM,CAAC,GAAW,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC1B,EAAE,CAAC,CAAC;gBAEJ,IAAI,CAAC,KAAK,KAAK,CAAC,iBAAiB,EAAE;oBACjC,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC;iBAC9B;qBAAM,IAAI,CAAC,KAAK,IAAI,EAAE;oBACrB,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC;oBACvB,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;oBAC/B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;iBAC9B;qBAAM,IAAI,CAAC,KAAK,IAAI,EAAE;oBACrB,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC;oBACvB,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;oBAC/B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;iBAC9B;qBAAM;oBACL,MAAM,IAAI,CAAC,CAAC;oBACZ,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC;oBAC7B,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;iBAC7B;aACF,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE;SAC3B;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEM,KAAK,CAAC,YAA+B;QAC1C,MAAM,KAAK,GAAwC,YAAmD,CAAC;QACvG,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAE7B,IAAI,KAAK,CAAC,cAAc,EAAE;YACxB,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;YAC7B,OAAO,IAAI,CAAC,OAAO,CAAC;SACrB;aAAM;YACL,OAAO,EAAE,CAAC;SACX;IACH,CAAC;CACF;AAtED,sEAsEC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { Text, type NewlineKind } from '@rushstack/node-core-library';\nimport { TextRewriter, type TextRewriterState } from './TextRewriter';\n\ninterface INormalizeNewlinesTextRewriterState extends TextRewriterState {\n characterToIgnore: string;\n incompleteLine: boolean;\n}\n\n/**\n * Constructor options for {@link NormalizeNewlinesTextRewriter}\n *\n * @public\n */\nexport interface INormalizeNewlinesTextRewriterOptions {\n /**\n * Specifies how newlines should be represented in the output stream.\n */\n newlineKind: NewlineKind;\n\n /**\n * If `true`, then `NormalizeNewlinesTextRewriter.close()` will append a newline to\n * the output if it ends with an incomplete line.\n *\n * @remarks\n * If the output is an empty string, then a newline will NOT be appended,\n * because writing an empty string does not produce an incomplete line.\n */\n ensureNewlineAtEnd?: boolean;\n}\n\n/**\n * For use with {@link TextRewriterTransform}, this rewriter converts all newlines to\n * a standard format.\n *\n * @public\n */\nexport class NormalizeNewlinesTextRewriter extends TextRewriter {\n /** {@inheritDoc INormalizeNewlinesTextRewriterOptions.newlineKind} */\n public readonly newlineKind: NewlineKind;\n\n /**\n * The specific character sequence that will be used when appending newlines.\n */\n public readonly newline: string;\n\n /** {@inheritDoc INormalizeNewlinesTextRewriterOptions.ensureNewlineAtEnd} */\n public readonly ensureNewlineAtEnd: boolean;\n\n public constructor(options: INormalizeNewlinesTextRewriterOptions) {\n super();\n this.newlineKind = options.newlineKind;\n this.newline = Text.getNewline(options.newlineKind);\n this.ensureNewlineAtEnd = !!options.ensureNewlineAtEnd;\n }\n\n public initialize(): TextRewriterState {\n return {\n characterToIgnore: '',\n incompleteLine: false\n } as INormalizeNewlinesTextRewriterState;\n }\n\n public process(unknownState: TextRewriterState, text: string): string {\n const state: INormalizeNewlinesTextRewriterState = unknownState as INormalizeNewlinesTextRewriterState;\n\n let result: string = '';\n\n if (text.length > 0) {\n let i: number = 0;\n\n do {\n const c: string = text[i];\n ++i;\n\n if (c === state.characterToIgnore) {\n state.characterToIgnore = '';\n } else if (c === '\\r') {\n result += this.newline;\n state.characterToIgnore = '\\n';\n state.incompleteLine = false;\n } else if (c === '\\n') {\n result += this.newline;\n state.characterToIgnore = '\\r';\n state.incompleteLine = false;\n } else {\n result += c;\n state.characterToIgnore = '';\n state.incompleteLine = true;\n }\n } while (i < text.length);\n }\n\n return result;\n }\n\n public close(unknownState: TextRewriterState): string {\n const state: INormalizeNewlinesTextRewriterState = unknownState as INormalizeNewlinesTextRewriterState;\n state.characterToIgnore = '';\n\n if (state.incompleteLine) {\n state.incompleteLine = false;\n return this.newline;\n } else {\n return '';\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"NormalizeNewlinesTextRewriter.js","sourceRoot":"","sources":["../src/NormalizeNewlinesTextRewriter.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAsE;AACtE,iDAAsE;AA6BtE;;;;;GAKG;AACH,MAAa,6BAA8B,SAAQ,2BAAY;IAY7D,YAAmB,OAA8C;QAC/D,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,OAAO,GAAG,wBAAI,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC;IACzD,CAAC;IAEM,UAAU;QACf,OAAO;YACL,iBAAiB,EAAE,EAAE;YACrB,cAAc,EAAE,KAAK;SACiB,CAAC;IAC3C,CAAC;IAEM,OAAO,CAAC,YAA+B,EAAE,IAAY;QAC1D,MAAM,KAAK,GAAwC,YAAmD,CAAC;QAEvG,IAAI,MAAM,GAAW,EAAE,CAAC;QAExB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;YACnB,IAAI,CAAC,GAAW,CAAC,CAAC;YAElB,GAAG;gBACD,MAAM,CAAC,GAAW,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC1B,EAAE,CAAC,CAAC;gBAEJ,IAAI,CAAC,KAAK,KAAK,CAAC,iBAAiB,EAAE;oBACjC,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC;iBAC9B;qBAAM,IAAI,CAAC,KAAK,IAAI,EAAE;oBACrB,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC;oBACvB,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;oBAC/B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;iBAC9B;qBAAM,IAAI,CAAC,KAAK,IAAI,EAAE;oBACrB,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC;oBACvB,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;oBAC/B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;iBAC9B;qBAAM;oBACL,MAAM,IAAI,CAAC,CAAC;oBACZ,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC;oBAC7B,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;iBAC7B;aACF,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE;SAC3B;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEM,KAAK,CAAC,YAA+B;QAC1C,MAAM,KAAK,GAAwC,YAAmD,CAAC;QACvG,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC;QAE7B,IAAI,KAAK,CAAC,cAAc,EAAE;YACxB,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC;YAC7B,OAAO,IAAI,CAAC,OAAO,CAAC;SACrB;aAAM;YACL,OAAO,EAAE,CAAC;SACX;IACH,CAAC;CACF;AAtED,sEAsEC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { Text, type NewlineKind } from '@rushstack/node-core-library';\r\nimport { TextRewriter, type TextRewriterState } from './TextRewriter';\r\n\r\ninterface INormalizeNewlinesTextRewriterState extends TextRewriterState {\r\n characterToIgnore: string;\r\n incompleteLine: boolean;\r\n}\r\n\r\n/**\r\n * Constructor options for {@link NormalizeNewlinesTextRewriter}\r\n *\r\n * @public\r\n */\r\nexport interface INormalizeNewlinesTextRewriterOptions {\r\n /**\r\n * Specifies how newlines should be represented in the output stream.\r\n */\r\n newlineKind: NewlineKind;\r\n\r\n /**\r\n * If `true`, then `NormalizeNewlinesTextRewriter.close()` will append a newline to\r\n * the output if it ends with an incomplete line.\r\n *\r\n * @remarks\r\n * If the output is an empty string, then a newline will NOT be appended,\r\n * because writing an empty string does not produce an incomplete line.\r\n */\r\n ensureNewlineAtEnd?: boolean;\r\n}\r\n\r\n/**\r\n * For use with {@link TextRewriterTransform}, this rewriter converts all newlines to\r\n * a standard format.\r\n *\r\n * @public\r\n */\r\nexport class NormalizeNewlinesTextRewriter extends TextRewriter {\r\n /** {@inheritDoc INormalizeNewlinesTextRewriterOptions.newlineKind} */\r\n public readonly newlineKind: NewlineKind;\r\n\r\n /**\r\n * The specific character sequence that will be used when appending newlines.\r\n */\r\n public readonly newline: string;\r\n\r\n /** {@inheritDoc INormalizeNewlinesTextRewriterOptions.ensureNewlineAtEnd} */\r\n public readonly ensureNewlineAtEnd: boolean;\r\n\r\n public constructor(options: INormalizeNewlinesTextRewriterOptions) {\r\n super();\r\n this.newlineKind = options.newlineKind;\r\n this.newline = Text.getNewline(options.newlineKind);\r\n this.ensureNewlineAtEnd = !!options.ensureNewlineAtEnd;\r\n }\r\n\r\n public initialize(): TextRewriterState {\r\n return {\r\n characterToIgnore: '',\r\n incompleteLine: false\r\n } as INormalizeNewlinesTextRewriterState;\r\n }\r\n\r\n public process(unknownState: TextRewriterState, text: string): string {\r\n const state: INormalizeNewlinesTextRewriterState = unknownState as INormalizeNewlinesTextRewriterState;\r\n\r\n let result: string = '';\r\n\r\n if (text.length > 0) {\r\n let i: number = 0;\r\n\r\n do {\r\n const c: string = text[i];\r\n ++i;\r\n\r\n if (c === state.characterToIgnore) {\r\n state.characterToIgnore = '';\r\n } else if (c === '\\r') {\r\n result += this.newline;\r\n state.characterToIgnore = '\\n';\r\n state.incompleteLine = false;\r\n } else if (c === '\\n') {\r\n result += this.newline;\r\n state.characterToIgnore = '\\r';\r\n state.incompleteLine = false;\r\n } else {\r\n result += c;\r\n state.characterToIgnore = '';\r\n state.incompleteLine = true;\r\n }\r\n } while (i < text.length);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public close(unknownState: TextRewriterState): string {\r\n const state: INormalizeNewlinesTextRewriterState = unknownState as INormalizeNewlinesTextRewriterState;\r\n state.characterToIgnore = '';\r\n\r\n if (state.incompleteLine) {\r\n state.incompleteLine = false;\r\n return this.newline;\r\n } else {\r\n return '';\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PrintUtilities.js","sourceRoot":"","sources":["../src/PrintUtilities.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { ITerminal } from '@rushstack/node-core-library';\n\n/**\n * A sensible fallback column width for consoles.\n *\n * @public\n */\nexport const DEFAULT_CONSOLE_WIDTH: number = 80;\n\n/**\n * A collection of utilities for printing messages to the console.\n *\n * @public\n */\nexport class PrintUtilities {\n /**\n * Returns the width of the console, measured in columns\n */\n public static getConsoleWidth(): number | undefined {\n return process.stdout?.columns;\n }\n\n /**\n * Applies word wrapping.\n *\n * @param text - The text to wrap\n * @param maxLineLength - The maximum length of a line, defaults to the console width\n * @param indent - The number of spaces to indent the wrapped lines, defaults to 0\n */\n public static wrapWords(text: string, maxLineLength?: number, indent?: number): string;\n /**\n * Applies word wrapping.\n *\n * @param text - The text to wrap\n * @param maxLineLength - The maximum length of a line, defaults to the console width\n * @param linePrefix - The string to prefix each line with, defaults to ''\n */\n public static wrapWords(text: string, maxLineLength?: number, linePrefix?: string): string;\n /**\n * Applies word wrapping.\n *\n * @param text - The text to wrap\n * @param maxLineLength - The maximum length of a line, defaults to the console width\n * @param indentOrLinePrefix - The number of spaces to indent the wrapped lines or the string to prefix\n * each line with, defaults to no prefix\n */\n public static wrapWords(text: string, maxLineLength?: number, indentOrLinePrefix?: number | string): string;\n public static wrapWords(\n text: string,\n maxLineLength?: number,\n indentOrLinePrefix?: number | string\n ): string {\n const wrappedLines: string[] = PrintUtilities.wrapWordsToLines(\n text,\n maxLineLength,\n indentOrLinePrefix as string | undefined // TS is confused by the overloads\n );\n return wrappedLines.join('\\n');\n }\n\n /**\n * Applies word wrapping and returns an array of lines.\n *\n * @param text - The text to wrap\n * @param maxLineLength - The maximum length of a line, defaults to the console width\n * @param indent - The number of spaces to indent the wrapped lines, defaults to 0\n */\n public static wrapWordsToLines(text: string, maxLineLength?: number, indent?: number): string[];\n /**\n * Applies word wrapping and returns an array of lines.\n *\n * @param text - The text to wrap\n * @param maxLineLength - The maximum length of a line, defaults to the console width\n * @param linePrefix - The string to prefix each line with, defaults to ''\n */\n public static wrapWordsToLines(text: string, maxLineLength?: number, linePrefix?: string): string[];\n /**\n * Applies word wrapping and returns an array of lines.\n *\n * @param text - The text to wrap\n * @param maxLineLength - The maximum length of a line, defaults to the console width\n * @param indentOrLinePrefix - The number of spaces to indent the wrapped lines or the string to prefix\n * each line with, defaults to no prefix\n */\n public static wrapWordsToLines(\n text: string,\n maxLineLength?: number,\n indentOrLinePrefix?: number | string\n ): string[];\n public static wrapWordsToLines(\n text: string,\n maxLineLength?: number,\n indentOrLinePrefix?: number | string\n ): string[] {\n let linePrefix: string;\n switch (typeof indentOrLinePrefix) {\n case 'number':\n linePrefix = ' '.repeat(indentOrLinePrefix);\n break;\n case 'string':\n linePrefix = indentOrLinePrefix;\n break;\n default:\n linePrefix = '';\n break;\n }\n\n const linePrefixLength: number = linePrefix.length;\n\n if (!maxLineLength) {\n maxLineLength = PrintUtilities.getConsoleWidth() || DEFAULT_CONSOLE_WIDTH;\n }\n\n // Apply word wrapping and the provided line prefix, while also respecting existing newlines\n // and prefix spaces that may exist in the text string already.\n const lines: string[] = text.split(/\\r?\\n/);\n\n const wrappedLines: string[] = [];\n for (const line of lines) {\n if (line.length + linePrefixLength <= maxLineLength) {\n wrappedLines.push(linePrefix + line);\n } else {\n const lineAdditionalPrefix: string = line.match(/^\\s*/)?.[0] || '';\n const whitespaceRegexp: RegExp = /\\s+/g;\n let currentWhitespaceMatch: RegExpExecArray | null = null;\n let previousWhitespaceMatch: RegExpExecArray | undefined;\n let currentLineStartIndex: number = lineAdditionalPrefix.length;\n let previousBreakRanOver: boolean = false;\n while ((currentWhitespaceMatch = whitespaceRegexp.exec(line)) !== null) {\n if (currentWhitespaceMatch.index + linePrefixLength - currentLineStartIndex > maxLineLength) {\n let whitespaceToSplitAt: RegExpExecArray | undefined;\n if (\n !previousWhitespaceMatch ||\n // Handle the case where there are two words longer than the maxLineLength in a row\n previousBreakRanOver\n ) {\n whitespaceToSplitAt = currentWhitespaceMatch;\n } else {\n whitespaceToSplitAt = previousWhitespaceMatch;\n }\n\n wrappedLines.push(\n linePrefix +\n lineAdditionalPrefix +\n line.substring(currentLineStartIndex, whitespaceToSplitAt.index)\n );\n previousBreakRanOver = whitespaceToSplitAt.index - currentLineStartIndex > maxLineLength;\n currentLineStartIndex = whitespaceToSplitAt.index + whitespaceToSplitAt[0].length;\n } else {\n previousBreakRanOver = false;\n }\n\n previousWhitespaceMatch = currentWhitespaceMatch;\n }\n\n if (currentLineStartIndex < line.length) {\n wrappedLines.push(linePrefix + lineAdditionalPrefix + line.substring(currentLineStartIndex));\n }\n }\n }\n\n return wrappedLines;\n }\n\n /**\n * Displays a message in the console wrapped in a box UI.\n *\n * @param message - The message to display.\n * @param terminal - The terminal to write the message to.\n * @param boxWidth - The width of the box, defaults to half of the console width.\n */\n public static printMessageInBox(message: string, terminal: ITerminal, boxWidth?: number): void {\n if (!boxWidth) {\n const consoleWidth: number = PrintUtilities.getConsoleWidth() || DEFAULT_CONSOLE_WIDTH;\n boxWidth = Math.floor(consoleWidth / 2);\n }\n\n const maxLineLength: number = boxWidth - 10;\n const wrappedMessageLines: string[] = PrintUtilities.wrapWordsToLines(message, maxLineLength);\n let longestLineLength: number = 0;\n const trimmedLines: string[] = [];\n for (const line of wrappedMessageLines) {\n const trimmedLine: string = line.trim();\n trimmedLines.push(trimmedLine);\n longestLineLength = Math.max(longestLineLength, trimmedLine.length);\n }\n\n if (longestLineLength > boxWidth - 2) {\n // If the longest line is longer than the box, print bars above and below the message\n // ═════════════\n // Message\n // ═════════════\n const headerAndFooter: string = ` ${'═'.repeat(boxWidth)}`;\n terminal.writeLine(headerAndFooter);\n for (const line of wrappedMessageLines) {\n terminal.writeLine(` ${line}`);\n }\n\n terminal.writeLine(headerAndFooter);\n } else {\n // ╔═══════════╗\n // ║ Message ║\n // ╚═══════════╝\n terminal.writeLine(` ╔${'═'.repeat(boxWidth - 2)}╗`);\n for (const trimmedLine of trimmedLines) {\n const padding: number = boxWidth - trimmedLine.length - 2;\n const leftPadding: number = Math.floor(padding / 2);\n const rightPadding: number = padding - leftPadding;\n terminal.writeLine(` ║${' '.repeat(leftPadding)}${trimmedLine}${' '.repeat(rightPadding)}║`);\n }\n terminal.writeLine(` ╚${'═'.repeat(boxWidth - 2)}╝`);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PrintUtilities.js","sourceRoot":"","sources":["../src/PrintUtilities.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport type { ITerminal } from '@rushstack/node-core-library';\r\n\r\n/**\r\n * A sensible fallback column width for consoles.\r\n *\r\n * @public\r\n */\r\nexport const DEFAULT_CONSOLE_WIDTH: number = 80;\r\n\r\n/**\r\n * A collection of utilities for printing messages to the console.\r\n *\r\n * @public\r\n */\r\nexport class PrintUtilities {\r\n /**\r\n * Returns the width of the console, measured in columns\r\n */\r\n public static getConsoleWidth(): number | undefined {\r\n return process.stdout?.columns;\r\n }\r\n\r\n /**\r\n * Applies word wrapping.\r\n *\r\n * @param text - The text to wrap\r\n * @param maxLineLength - The maximum length of a line, defaults to the console width\r\n * @param indent - The number of spaces to indent the wrapped lines, defaults to 0\r\n */\r\n public static wrapWords(text: string, maxLineLength?: number, indent?: number): string;\r\n /**\r\n * Applies word wrapping.\r\n *\r\n * @param text - The text to wrap\r\n * @param maxLineLength - The maximum length of a line, defaults to the console width\r\n * @param linePrefix - The string to prefix each line with, defaults to ''\r\n */\r\n public static wrapWords(text: string, maxLineLength?: number, linePrefix?: string): string;\r\n /**\r\n * Applies word wrapping.\r\n *\r\n * @param text - The text to wrap\r\n * @param maxLineLength - The maximum length of a line, defaults to the console width\r\n * @param indentOrLinePrefix - The number of spaces to indent the wrapped lines or the string to prefix\r\n * each line with, defaults to no prefix\r\n */\r\n public static wrapWords(text: string, maxLineLength?: number, indentOrLinePrefix?: number | string): string;\r\n public static wrapWords(\r\n text: string,\r\n maxLineLength?: number,\r\n indentOrLinePrefix?: number | string\r\n ): string {\r\n const wrappedLines: string[] = PrintUtilities.wrapWordsToLines(\r\n text,\r\n maxLineLength,\r\n indentOrLinePrefix as string | undefined // TS is confused by the overloads\r\n );\r\n return wrappedLines.join('\\n');\r\n }\r\n\r\n /**\r\n * Applies word wrapping and returns an array of lines.\r\n *\r\n * @param text - The text to wrap\r\n * @param maxLineLength - The maximum length of a line, defaults to the console width\r\n * @param indent - The number of spaces to indent the wrapped lines, defaults to 0\r\n */\r\n public static wrapWordsToLines(text: string, maxLineLength?: number, indent?: number): string[];\r\n /**\r\n * Applies word wrapping and returns an array of lines.\r\n *\r\n * @param text - The text to wrap\r\n * @param maxLineLength - The maximum length of a line, defaults to the console width\r\n * @param linePrefix - The string to prefix each line with, defaults to ''\r\n */\r\n public static wrapWordsToLines(text: string, maxLineLength?: number, linePrefix?: string): string[];\r\n /**\r\n * Applies word wrapping and returns an array of lines.\r\n *\r\n * @param text - The text to wrap\r\n * @param maxLineLength - The maximum length of a line, defaults to the console width\r\n * @param indentOrLinePrefix - The number of spaces to indent the wrapped lines or the string to prefix\r\n * each line with, defaults to no prefix\r\n */\r\n public static wrapWordsToLines(\r\n text: string,\r\n maxLineLength?: number,\r\n indentOrLinePrefix?: number | string\r\n ): string[];\r\n public static wrapWordsToLines(\r\n text: string,\r\n maxLineLength?: number,\r\n indentOrLinePrefix?: number | string\r\n ): string[] {\r\n let linePrefix: string;\r\n switch (typeof indentOrLinePrefix) {\r\n case 'number':\r\n linePrefix = ' '.repeat(indentOrLinePrefix);\r\n break;\r\n case 'string':\r\n linePrefix = indentOrLinePrefix;\r\n break;\r\n default:\r\n linePrefix = '';\r\n break;\r\n }\r\n\r\n const linePrefixLength: number = linePrefix.length;\r\n\r\n if (!maxLineLength) {\r\n maxLineLength = PrintUtilities.getConsoleWidth() || DEFAULT_CONSOLE_WIDTH;\r\n }\r\n\r\n // Apply word wrapping and the provided line prefix, while also respecting existing newlines\r\n // and prefix spaces that may exist in the text string already.\r\n const lines: string[] = text.split(/\\r?\\n/);\r\n\r\n const wrappedLines: string[] = [];\r\n for (const line of lines) {\r\n if (line.length + linePrefixLength <= maxLineLength) {\r\n wrappedLines.push(linePrefix + line);\r\n } else {\r\n const lineAdditionalPrefix: string = line.match(/^\\s*/)?.[0] || '';\r\n const whitespaceRegexp: RegExp = /\\s+/g;\r\n let currentWhitespaceMatch: RegExpExecArray | null = null;\r\n let previousWhitespaceMatch: RegExpExecArray | undefined;\r\n let currentLineStartIndex: number = lineAdditionalPrefix.length;\r\n let previousBreakRanOver: boolean = false;\r\n while ((currentWhitespaceMatch = whitespaceRegexp.exec(line)) !== null) {\r\n if (currentWhitespaceMatch.index + linePrefixLength - currentLineStartIndex > maxLineLength) {\r\n let whitespaceToSplitAt: RegExpExecArray | undefined;\r\n if (\r\n !previousWhitespaceMatch ||\r\n // Handle the case where there are two words longer than the maxLineLength in a row\r\n previousBreakRanOver\r\n ) {\r\n whitespaceToSplitAt = currentWhitespaceMatch;\r\n } else {\r\n whitespaceToSplitAt = previousWhitespaceMatch;\r\n }\r\n\r\n wrappedLines.push(\r\n linePrefix +\r\n lineAdditionalPrefix +\r\n line.substring(currentLineStartIndex, whitespaceToSplitAt.index)\r\n );\r\n previousBreakRanOver = whitespaceToSplitAt.index - currentLineStartIndex > maxLineLength;\r\n currentLineStartIndex = whitespaceToSplitAt.index + whitespaceToSplitAt[0].length;\r\n } else {\r\n previousBreakRanOver = false;\r\n }\r\n\r\n previousWhitespaceMatch = currentWhitespaceMatch;\r\n }\r\n\r\n if (currentLineStartIndex < line.length) {\r\n wrappedLines.push(linePrefix + lineAdditionalPrefix + line.substring(currentLineStartIndex));\r\n }\r\n }\r\n }\r\n\r\n return wrappedLines;\r\n }\r\n\r\n /**\r\n * Displays a message in the console wrapped in a box UI.\r\n *\r\n * @param message - The message to display.\r\n * @param terminal - The terminal to write the message to.\r\n * @param boxWidth - The width of the box, defaults to half of the console width.\r\n */\r\n public static printMessageInBox(message: string, terminal: ITerminal, boxWidth?: number): void {\r\n if (!boxWidth) {\r\n const consoleWidth: number = PrintUtilities.getConsoleWidth() || DEFAULT_CONSOLE_WIDTH;\r\n boxWidth = Math.floor(consoleWidth / 2);\r\n }\r\n\r\n const maxLineLength: number = boxWidth - 10;\r\n const wrappedMessageLines: string[] = PrintUtilities.wrapWordsToLines(message, maxLineLength);\r\n let longestLineLength: number = 0;\r\n const trimmedLines: string[] = [];\r\n for (const line of wrappedMessageLines) {\r\n const trimmedLine: string = line.trim();\r\n trimmedLines.push(trimmedLine);\r\n longestLineLength = Math.max(longestLineLength, trimmedLine.length);\r\n }\r\n\r\n if (longestLineLength > boxWidth - 2) {\r\n // If the longest line is longer than the box, print bars above and below the message\r\n // ═════════════\r\n // Message\r\n // ═════════════\r\n const headerAndFooter: string = ` ${'═'.repeat(boxWidth)}`;\r\n terminal.writeLine(headerAndFooter);\r\n for (const line of wrappedMessageLines) {\r\n terminal.writeLine(` ${line}`);\r\n }\r\n\r\n terminal.writeLine(headerAndFooter);\r\n } else {\r\n // ╔═══════════╗\r\n // ║ Message ║\r\n // ╚═══════════╝\r\n terminal.writeLine(` ╔${'═'.repeat(boxWidth - 2)}╗`);\r\n for (const trimmedLine of trimmedLines) {\r\n const padding: number = boxWidth - trimmedLine.length - 2;\r\n const leftPadding: number = Math.floor(padding / 2);\r\n const rightPadding: number = padding - leftPadding;\r\n terminal.writeLine(` ║${' '.repeat(leftPadding)}${trimmedLine}${' '.repeat(rightPadding)}║`);\r\n }\r\n terminal.writeLine(` ╚${'═'.repeat(boxWidth - 2)}╝`);\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoveColorsTextRewriter.js","sourceRoot":"","sources":["../src/RemoveColorsTextRewriter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { AnsiEscape } from '@rushstack/node-core-library';\nimport { TextRewriter, type TextRewriterState } from './TextRewriter';\n\nenum State {\n // Buffer is empty, and we're looking for the ESC character\n Start,\n // We're looking for the '[' character\n AwaitingBracket,\n // We're reading the codes after the '[' character\n ReadingCodes\n}\n\ninterface IRemoveColorsTextRewriterState extends TextRewriterState {\n buffer: string;\n parseState: State;\n}\n\n/**\n * For use with {@link TextRewriterTransform}, this rewriter removes ANSI escape codes\n * including colored text.\n *\n * @remarks\n * The implementation also removes other ANSI escape codes such as cursor positioning.\n * The specific set of affected codes may be adjusted in the future.\n *\n * @public\n */\nexport class RemoveColorsTextRewriter extends TextRewriter {\n public initialize(): TextRewriterState {\n return { buffer: '', parseState: State.Start } as IRemoveColorsTextRewriterState;\n }\n\n public process(unknownState: TextRewriterState, text: string): string {\n const state: IRemoveColorsTextRewriterState = unknownState as IRemoveColorsTextRewriterState;\n\n // We will be matching AnsiEscape._csiRegExp:\n //\n // /\\x1b\\[([\\x30-\\x3f]*[\\x20-\\x2f]*[\\x40-\\x7e])/gu\n //\n const ESC: string = '\\x1b';\n\n let result: string = '';\n let index: number = 0;\n\n while (index < text.length) {\n if (state.parseState === State.Start) {\n // The buffer is empty, which means we haven't found anything yet\n\n const csiIndex: number = text.indexOf(ESC, index);\n if (csiIndex < 0) {\n // We reached the end of \"text\" without finding another CSI prefix\n result += text.substring(index);\n break;\n }\n\n // Append everything up to the CSI prefix\n result += text.substring(index, csiIndex);\n\n // Save the partial match in the buffer\n state.buffer = ESC;\n index = csiIndex + 1;\n state.parseState = State.AwaitingBracket;\n } else {\n // The buffer has characters, which means we started matching a partial sequence\n\n // Read another character into the buffer\n const c: string = text[index];\n ++index;\n state.buffer += c;\n\n if (state.parseState === State.AwaitingBracket) {\n if (c === '[') {\n state.parseState = State.ReadingCodes;\n } else {\n // Failed to match, so append the buffer and start over\n result += state.buffer;\n state.buffer = '';\n state.parseState = State.Start;\n }\n } else {\n // state.state === State.ReadingCodes\n\n // Stop when we reach any character that is not [\\x30-\\x3f] or [\\x20-\\x2f]\n const code: number = c.charCodeAt(0);\n if (code < 0x20 || code > 0x3f) {\n result += AnsiEscape.removeCodes(state.buffer);\n state.buffer = '';\n state.parseState = State.Start;\n }\n }\n }\n }\n\n return result;\n }\n\n public close(unknownState: TextRewriterState): string {\n const state: IRemoveColorsTextRewriterState = unknownState as IRemoveColorsTextRewriterState;\n\n const result: string = state.buffer;\n state.buffer = '';\n return result;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"RemoveColorsTextRewriter.js","sourceRoot":"","sources":["../src/RemoveColorsTextRewriter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { AnsiEscape } from '@rushstack/node-core-library';\r\nimport { TextRewriter, type TextRewriterState } from './TextRewriter';\r\n\r\nenum State {\r\n // Buffer is empty, and we're looking for the ESC character\r\n Start,\r\n // We're looking for the '[' character\r\n AwaitingBracket,\r\n // We're reading the codes after the '[' character\r\n ReadingCodes\r\n}\r\n\r\ninterface IRemoveColorsTextRewriterState extends TextRewriterState {\r\n buffer: string;\r\n parseState: State;\r\n}\r\n\r\n/**\r\n * For use with {@link TextRewriterTransform}, this rewriter removes ANSI escape codes\r\n * including colored text.\r\n *\r\n * @remarks\r\n * The implementation also removes other ANSI escape codes such as cursor positioning.\r\n * The specific set of affected codes may be adjusted in the future.\r\n *\r\n * @public\r\n */\r\nexport class RemoveColorsTextRewriter extends TextRewriter {\r\n public initialize(): TextRewriterState {\r\n return { buffer: '', parseState: State.Start } as IRemoveColorsTextRewriterState;\r\n }\r\n\r\n public process(unknownState: TextRewriterState, text: string): string {\r\n const state: IRemoveColorsTextRewriterState = unknownState as IRemoveColorsTextRewriterState;\r\n\r\n // We will be matching AnsiEscape._csiRegExp:\r\n //\r\n // /\\x1b\\[([\\x30-\\x3f]*[\\x20-\\x2f]*[\\x40-\\x7e])/gu\r\n //\r\n const ESC: string = '\\x1b';\r\n\r\n let result: string = '';\r\n let index: number = 0;\r\n\r\n while (index < text.length) {\r\n if (state.parseState === State.Start) {\r\n // The buffer is empty, which means we haven't found anything yet\r\n\r\n const csiIndex: number = text.indexOf(ESC, index);\r\n if (csiIndex < 0) {\r\n // We reached the end of \"text\" without finding another CSI prefix\r\n result += text.substring(index);\r\n break;\r\n }\r\n\r\n // Append everything up to the CSI prefix\r\n result += text.substring(index, csiIndex);\r\n\r\n // Save the partial match in the buffer\r\n state.buffer = ESC;\r\n index = csiIndex + 1;\r\n state.parseState = State.AwaitingBracket;\r\n } else {\r\n // The buffer has characters, which means we started matching a partial sequence\r\n\r\n // Read another character into the buffer\r\n const c: string = text[index];\r\n ++index;\r\n state.buffer += c;\r\n\r\n if (state.parseState === State.AwaitingBracket) {\r\n if (c === '[') {\r\n state.parseState = State.ReadingCodes;\r\n } else {\r\n // Failed to match, so append the buffer and start over\r\n result += state.buffer;\r\n state.buffer = '';\r\n state.parseState = State.Start;\r\n }\r\n } else {\r\n // state.state === State.ReadingCodes\r\n\r\n // Stop when we reach any character that is not [\\x30-\\x3f] or [\\x20-\\x2f]\r\n const code: number = c.charCodeAt(0);\r\n if (code < 0x20 || code > 0x3f) {\r\n result += AnsiEscape.removeCodes(state.buffer);\r\n state.buffer = '';\r\n state.parseState = State.Start;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public close(unknownState: TextRewriterState): string {\r\n const state: IRemoveColorsTextRewriterState = unknownState as IRemoveColorsTextRewriterState;\r\n\r\n const result: string = state.buffer;\r\n state.buffer = '';\r\n return result;\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SplitterTransform.js","sourceRoot":"","sources":["../src/SplitterTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAqF;AAerF;;;;;;;;;;;GAWG;AACH,MAAa,iBAAkB,SAAQ,mCAAgB;IAGrD,YAAmB,OAAkC;QACnD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAChD,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE;YAC3C,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;SAC/B;IACH,CAAC;IAES,OAAO;QACf,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,2FAA2F;QAC3F,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE;YAC3C,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE;gBACjC,IAAI;oBACF,WAAW,CAAC,KAAK,EAAE,CAAC;iBACrB;gBAAC,OAAO,KAAK,EAAE;oBACd,MAAM,CAAC,IAAI,CAAC,KAAc,CAAC,CAAC;iBAC7B;aACF;SACF;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;YACrB,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC;SACjB;IACH,CAAC;CACF;AAhCD,8CAgCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { TerminalWritable, type ITerminalWritableOptions } from './TerminalWritable';\nimport type { ITerminalChunk } from './ITerminalChunk';\n\n/**\n * Constructor options for {@link SplitterTransform}.\n *\n * @public\n */\nexport interface ISplitterTransformOptions extends ITerminalWritableOptions {\n /**\n * Each input chunk will be passed to each destination in the array.\n */\n destinations: TerminalWritable[];\n}\n\n/**\n * Use this instead of {@link TerminalTransform} if you need to output `ITerminalChunk`\n * data to more than one destination.\n *\n * @remarks\n *\n * Splitting streams complicates the pipeline topology and can make debugging more difficult.\n * For this reason, it is modeled as an explicit `SplitterTransform` node, rather than\n * as a built-in feature of `TerminalTransform`.\n *\n * @public\n */\nexport class SplitterTransform extends TerminalWritable {\n public readonly destinations: ReadonlyArray<TerminalWritable>;\n\n public constructor(options: ISplitterTransformOptions) {\n super();\n this.destinations = [...options.destinations];\n }\n\n protected onWriteChunk(chunk: ITerminalChunk): void {\n for (const destination of this.destinations) {\n destination.writeChunk(chunk);\n }\n }\n\n protected onClose(): void {\n const errors: Error[] = [];\n\n // If an exception is thrown, try to ensure that the other destinations get closed properly\n for (const destination of this.destinations) {\n if (!destination.preventAutoclose) {\n try {\n destination.close();\n } catch (error) {\n errors.push(error as Error);\n }\n }\n }\n\n if (errors.length > 0) {\n throw errors[0];\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SplitterTransform.js","sourceRoot":"","sources":["../src/SplitterTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAqF;AAerF;;;;;;;;;;;GAWG;AACH,MAAa,iBAAkB,SAAQ,mCAAgB;IAGrD,YAAmB,OAAkC;QACnD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,GAAG,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAChD,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE;YAC3C,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;SAC/B;IACH,CAAC;IAES,OAAO;QACf,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,2FAA2F;QAC3F,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE;YAC3C,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE;gBACjC,IAAI;oBACF,WAAW,CAAC,KAAK,EAAE,CAAC;iBACrB;gBAAC,OAAO,KAAK,EAAE;oBACd,MAAM,CAAC,IAAI,CAAC,KAAc,CAAC,CAAC;iBAC7B;aACF;SACF;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;YACrB,MAAM,MAAM,CAAC,CAAC,CAAC,CAAC;SACjB;IACH,CAAC;CACF;AAhCD,8CAgCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { TerminalWritable, type ITerminalWritableOptions } from './TerminalWritable';\r\nimport type { ITerminalChunk } from './ITerminalChunk';\r\n\r\n/**\r\n * Constructor options for {@link SplitterTransform}.\r\n *\r\n * @public\r\n */\r\nexport interface ISplitterTransformOptions extends ITerminalWritableOptions {\r\n /**\r\n * Each input chunk will be passed to each destination in the array.\r\n */\r\n destinations: TerminalWritable[];\r\n}\r\n\r\n/**\r\n * Use this instead of {@link TerminalTransform} if you need to output `ITerminalChunk`\r\n * data to more than one destination.\r\n *\r\n * @remarks\r\n *\r\n * Splitting streams complicates the pipeline topology and can make debugging more difficult.\r\n * For this reason, it is modeled as an explicit `SplitterTransform` node, rather than\r\n * as a built-in feature of `TerminalTransform`.\r\n *\r\n * @public\r\n */\r\nexport class SplitterTransform extends TerminalWritable {\r\n public readonly destinations: ReadonlyArray<TerminalWritable>;\r\n\r\n public constructor(options: ISplitterTransformOptions) {\r\n super();\r\n this.destinations = [...options.destinations];\r\n }\r\n\r\n protected onWriteChunk(chunk: ITerminalChunk): void {\r\n for (const destination of this.destinations) {\r\n destination.writeChunk(chunk);\r\n }\r\n }\r\n\r\n protected onClose(): void {\r\n const errors: Error[] = [];\r\n\r\n // If an exception is thrown, try to ensure that the other destinations get closed properly\r\n for (const destination of this.destinations) {\r\n if (!destination.preventAutoclose) {\r\n try {\r\n destination.close();\r\n } catch (error) {\r\n errors.push(error as Error);\r\n }\r\n }\r\n }\r\n\r\n if (errors.length > 0) {\r\n throw errors[0];\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StdioLineTransform.js","sourceRoot":"","sources":["../src/StdioLineTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAiE;AAGjE,2DAAwF;AAaxF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,MAAa,mBAAoB,SAAQ,qCAAiB;IAMxD,YAAmB,OAAmC;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAEhC,IAAI,CAAC,OAAO,GAAG,wBAAI,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,IAAI,+BAAW,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;SAChF;QAED,qFAAqF;QACrF,sBAAsB;QACtB,MAAM,IAAI,GAAW,KAAK,CAAC,IAAI,CAAC;QAChC,IAAI,UAAU,GAAW,CAAC,CAAC;QAE3B,OAAO,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE;YAC/B,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;gBAC3C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;aAChC;YAED,MAAM,QAAQ,GAAW,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACxD,IAAI,QAAQ,GAAG,CAAC,EAAE;gBAChB,uCAAuC;gBACvC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;gBACpD,MAAM;aACP;YAED,6BAA6B;YAC7B,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAE9D,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAE/B,cAAc;YACd,UAAU,GAAG,QAAQ,GAAG,CAAC,CAAC;SAC3B;IACH,CAAC;IAES,OAAO;QACf,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;YACpC,IAAI,CAAC,uBAAuB,EAAE,CAAC;SAChC;QACD,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAEO,uBAAuB;QAC7B,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,OAAO,CAAC;QAEtC,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;gBAC1B,IAAI,oCAA0B;gBAC9B,IAAI,EAAE,IAAI,CAAC,gBAAgB;aAC5B,CAAC,CAAC;SACJ;aAAM;YACL,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;gBAC1B,IAAI,oCAA0B;gBAC9B,IAAI,EAAE,IAAI,CAAC,gBAAgB;aAC5B,CAAC,CAAC;SACJ;QAED,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;IAClC,CAAC;CACF;AAxED,kDAwEC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { Text, NewlineKind } from '@rushstack/node-core-library';\n\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\nimport { TerminalTransform, type ITerminalTransformOptions } from './TerminalTransform';\n\n/**\n * Constructor options for {@link StderrLineTransform}\n * @beta\n */\nexport interface IStdioLineTransformOptions extends ITerminalTransformOptions {\n /**\n * Specifies the kind of newline for the output.\n */\n newlineKind?: NewlineKind;\n}\n\n/**\n * `StderrLineTransform` normalizes lines that mix characters from `stdout` and `stderr`,\n * so that each output line is routed entirely to `stdout` or `stderr`.\n *\n * @remarks\n * IMPORTANT: This transform assumes that its input has been normalized to use `\"\\n\"` newlines.\n *\n * IMPORTANT: This transform does not produce realtime output, because lines are buffered\n * until a newline character is encountered.\n *\n * Suppose that a poorly behaved process produces output like this:\n *\n * ```ts\n * process.stderr.write('An error occurred, cleaning up');\n * process.stdout.write('.'); // (delay)\n * process.stdout.write('.'); // (delay)\n * process.stdout.write('.');\n * process.stdout.write('\\n');\n * process.stderr.write('The process completed with errors\\n');\n * ```\n *\n * When `stdout` and `stderr` are combined on the console, the mistake in the output would not be noticeable:\n * ```\n * An error occurred, cleaning up...\n * The process completed with errors\n * ```\n *\n * However, if we discard `stdout`, then `stderr` is malformed:\n * ```\n * An error occurred, cleaning upThe process completed with errors\n * ```\n *\n * Tooling scripts can introduce these sorts of problems via edge cases that are difficult to find and fix.\n *\n * `StderrLineTransform` normalizes the output so that if a combined line contains any `stderr` characters,\n * then the entire line is routed to `stderr`. Later, if we discard `stdout`, then the output will\n * preserve the appropriate context:\n *\n * ```\n * An error occurred, cleaning up...\n * The process completed with errors\n * ```\n *\n * @privateRemarks\n * This class is experimental and marked as `@beta`. The algorithm may need some fine-tuning, or there may\n * be better solutions to this problem.\n *\n * @beta\n */\nexport class StderrLineTransform extends TerminalTransform {\n private _accumulatedLine: string;\n private _accumulatedStderr: boolean;\n\n public readonly newline: string;\n\n public constructor(options: IStdioLineTransformOptions) {\n super(options);\n\n this._accumulatedLine = '';\n this._accumulatedStderr = false;\n\n this.newline = Text.getNewline(options.newlineKind || NewlineKind.Lf);\n }\n\n protected onWriteChunk(chunk: ITerminalChunk): void {\n if (chunk.text.indexOf('\\r') >= 0) {\n throw new Error('StderrLineTransform expects chunks with normalized newlines');\n }\n\n // After _newlineNormalizerTransform was applied, we can now assume that all newlines\n // use the \"\\n\" string\n const text: string = chunk.text;\n let startIndex: number = 0;\n\n while (startIndex < text.length) {\n if (chunk.kind === TerminalChunkKind.Stderr) {\n this._accumulatedStderr = true;\n }\n\n const endIndex: number = text.indexOf('\\n', startIndex);\n if (endIndex < 0) {\n // we did not find \\n, so simply append\n this._accumulatedLine += text.substring(startIndex);\n break;\n }\n\n // append everything up to \\n\n this._accumulatedLine += text.substring(startIndex, endIndex);\n\n this._processAccumulatedLine();\n\n // skip the \\n\n startIndex = endIndex + 1;\n }\n }\n\n protected onClose(): void {\n if (this._accumulatedLine.length > 0) {\n this._processAccumulatedLine();\n }\n this.autocloseDestination();\n }\n\n private _processAccumulatedLine(): void {\n this._accumulatedLine += this.newline;\n\n if (this._accumulatedStderr) {\n this.destination.writeChunk({\n kind: TerminalChunkKind.Stderr,\n text: this._accumulatedLine\n });\n } else {\n this.destination.writeChunk({\n kind: TerminalChunkKind.Stdout,\n text: this._accumulatedLine\n });\n }\n\n this._accumulatedLine = '';\n this._accumulatedStderr = false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"StdioLineTransform.js","sourceRoot":"","sources":["../src/StdioLineTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAiE;AAGjE,2DAAwF;AAaxF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,MAAa,mBAAoB,SAAQ,qCAAiB;IAMxD,YAAmB,OAAmC;QACpD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAEhC,IAAI,CAAC,OAAO,GAAG,wBAAI,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,IAAI,+BAAW,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAES,YAAY,CAAC,KAAqB;QAC1C,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;SAChF;QAED,qFAAqF;QACrF,sBAAsB;QACtB,MAAM,IAAI,GAAW,KAAK,CAAC,IAAI,CAAC;QAChC,IAAI,UAAU,GAAW,CAAC,CAAC;QAE3B,OAAO,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE;YAC/B,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;gBAC3C,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;aAChC;YAED,MAAM,QAAQ,GAAW,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACxD,IAAI,QAAQ,GAAG,CAAC,EAAE;gBAChB,uCAAuC;gBACvC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;gBACpD,MAAM;aACP;YAED,6BAA6B;YAC7B,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAE9D,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAE/B,cAAc;YACd,UAAU,GAAG,QAAQ,GAAG,CAAC,CAAC;SAC3B;IACH,CAAC;IAES,OAAO;QACf,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;YACpC,IAAI,CAAC,uBAAuB,EAAE,CAAC;SAChC;QACD,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAEO,uBAAuB;QAC7B,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,OAAO,CAAC;QAEtC,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;gBAC1B,IAAI,oCAA0B;gBAC9B,IAAI,EAAE,IAAI,CAAC,gBAAgB;aAC5B,CAAC,CAAC;SACJ;aAAM;YACL,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;gBAC1B,IAAI,oCAA0B;gBAC9B,IAAI,EAAE,IAAI,CAAC,gBAAgB;aAC5B,CAAC,CAAC;SACJ;QAED,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;IAClC,CAAC;CACF;AAxED,kDAwEC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { Text, NewlineKind } from '@rushstack/node-core-library';\r\n\r\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\r\nimport { TerminalTransform, type ITerminalTransformOptions } from './TerminalTransform';\r\n\r\n/**\r\n * Constructor options for {@link StderrLineTransform}\r\n * @beta\r\n */\r\nexport interface IStdioLineTransformOptions extends ITerminalTransformOptions {\r\n /**\r\n * Specifies the kind of newline for the output.\r\n */\r\n newlineKind?: NewlineKind;\r\n}\r\n\r\n/**\r\n * `StderrLineTransform` normalizes lines that mix characters from `stdout` and `stderr`,\r\n * so that each output line is routed entirely to `stdout` or `stderr`.\r\n *\r\n * @remarks\r\n * IMPORTANT: This transform assumes that its input has been normalized to use `\"\\n\"` newlines.\r\n *\r\n * IMPORTANT: This transform does not produce realtime output, because lines are buffered\r\n * until a newline character is encountered.\r\n *\r\n * Suppose that a poorly behaved process produces output like this:\r\n *\r\n * ```ts\r\n * process.stderr.write('An error occurred, cleaning up');\r\n * process.stdout.write('.'); // (delay)\r\n * process.stdout.write('.'); // (delay)\r\n * process.stdout.write('.');\r\n * process.stdout.write('\\n');\r\n * process.stderr.write('The process completed with errors\\n');\r\n * ```\r\n *\r\n * When `stdout` and `stderr` are combined on the console, the mistake in the output would not be noticeable:\r\n * ```\r\n * An error occurred, cleaning up...\r\n * The process completed with errors\r\n * ```\r\n *\r\n * However, if we discard `stdout`, then `stderr` is malformed:\r\n * ```\r\n * An error occurred, cleaning upThe process completed with errors\r\n * ```\r\n *\r\n * Tooling scripts can introduce these sorts of problems via edge cases that are difficult to find and fix.\r\n *\r\n * `StderrLineTransform` normalizes the output so that if a combined line contains any `stderr` characters,\r\n * then the entire line is routed to `stderr`. Later, if we discard `stdout`, then the output will\r\n * preserve the appropriate context:\r\n *\r\n * ```\r\n * An error occurred, cleaning up...\r\n * The process completed with errors\r\n * ```\r\n *\r\n * @privateRemarks\r\n * This class is experimental and marked as `@beta`. The algorithm may need some fine-tuning, or there may\r\n * be better solutions to this problem.\r\n *\r\n * @beta\r\n */\r\nexport class StderrLineTransform extends TerminalTransform {\r\n private _accumulatedLine: string;\r\n private _accumulatedStderr: boolean;\r\n\r\n public readonly newline: string;\r\n\r\n public constructor(options: IStdioLineTransformOptions) {\r\n super(options);\r\n\r\n this._accumulatedLine = '';\r\n this._accumulatedStderr = false;\r\n\r\n this.newline = Text.getNewline(options.newlineKind || NewlineKind.Lf);\r\n }\r\n\r\n protected onWriteChunk(chunk: ITerminalChunk): void {\r\n if (chunk.text.indexOf('\\r') >= 0) {\r\n throw new Error('StderrLineTransform expects chunks with normalized newlines');\r\n }\r\n\r\n // After _newlineNormalizerTransform was applied, we can now assume that all newlines\r\n // use the \"\\n\" string\r\n const text: string = chunk.text;\r\n let startIndex: number = 0;\r\n\r\n while (startIndex < text.length) {\r\n if (chunk.kind === TerminalChunkKind.Stderr) {\r\n this._accumulatedStderr = true;\r\n }\r\n\r\n const endIndex: number = text.indexOf('\\n', startIndex);\r\n if (endIndex < 0) {\r\n // we did not find \\n, so simply append\r\n this._accumulatedLine += text.substring(startIndex);\r\n break;\r\n }\r\n\r\n // append everything up to \\n\r\n this._accumulatedLine += text.substring(startIndex, endIndex);\r\n\r\n this._processAccumulatedLine();\r\n\r\n // skip the \\n\r\n startIndex = endIndex + 1;\r\n }\r\n }\r\n\r\n protected onClose(): void {\r\n if (this._accumulatedLine.length > 0) {\r\n this._processAccumulatedLine();\r\n }\r\n this.autocloseDestination();\r\n }\r\n\r\n private _processAccumulatedLine(): void {\r\n this._accumulatedLine += this.newline;\r\n\r\n if (this._accumulatedStderr) {\r\n this.destination.writeChunk({\r\n kind: TerminalChunkKind.Stderr,\r\n text: this._accumulatedLine\r\n });\r\n } else {\r\n this.destination.writeChunk({\r\n kind: TerminalChunkKind.Stdout,\r\n text: this._accumulatedLine\r\n });\r\n }\r\n\r\n this._accumulatedLine = '';\r\n this._accumulatedStderr = false;\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StdioSummarizer.js","sourceRoot":"","sources":["../src/StdioSummarizer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\nimport { TerminalWritable } from './TerminalWritable';\n\n/**\n * Constructor options for {@link StdioSummarizer}.\n * @beta\n */\nexport interface IStdioSummarizerOptions {\n /**\n * Specifies the maximum number of leading lines to include in the summary.\n * @defaultValue `10`\n */\n leadingLines?: number;\n\n /**\n * Specifies the maximum number of trailing lines to include in the summary.\n * @defaultValue `10`\n */\n trailingLines?: number;\n}\n\n/**\n * Summarizes the results of a failed build task by returning a subset of `stderr` output not to exceed\n * a specified maximum number of lines.\n *\n * @remarks\n * IMPORTANT: This transform assumes that its input was prepared by {@link StderrLineTransform}, so that each\n * {@link ITerminalChunk.text} item is a single line terminated by a `\"\\n\"` character.\n *\n * The {@link IStdioSummarizerOptions.leadingLines} and {@link IStdioSummarizerOptions.trailingLines}\n * counts specify the maximum number of lines to be returned. Any additional lines will be omitted.\n * For example, if `leadingLines` and `trailingLines` were set to `3`, then the summary of 16 `stderr` lines might\n * look like this:\n *\n * ```\n * Line 1\n * Line 2\n * Line 3\n * ...10 lines omitted...\n * Line 14\n * Line 15\n * Line 16\n * ```\n *\n * If the `stderr` output is completely empty, then the `stdout` output will be summarized instead.\n *\n * @beta\n */\nexport class StdioSummarizer extends TerminalWritable {\n // Capture up to this many leading lines\n private _leadingLines: number;\n\n // Capture up to this many trailing lines\n private _trailingLines: number;\n\n private readonly _abridgedLeading: string[];\n private readonly _abridgedTrailing: string[];\n private _abridgedOmittedLines: number = 0;\n private _abridgedStderr: boolean;\n\n public constructor(options?: IStdioSummarizerOptions) {\n super();\n\n if (!options) {\n options = {};\n }\n\n this._leadingLines = options.leadingLines !== undefined ? options.leadingLines : 10;\n this._trailingLines = options.trailingLines !== undefined ? options.trailingLines : 10;\n\n this._abridgedLeading = [];\n this._abridgedTrailing = [];\n this._abridgedStderr = false;\n }\n\n /**\n * Returns the summary report.\n *\n * @remarks\n * The `close()` method must be called before `getReport()` can be used.\n */\n public getReport(): string {\n if (this.isOpen) {\n throw new Error('The summary cannot be prepared until after close() is called.');\n }\n const report: string[] = [...this._abridgedLeading];\n if (this._abridgedOmittedLines === 1) {\n report.push(` ...${this._abridgedOmittedLines} line omitted...\\n`);\n }\n if (this._abridgedOmittedLines > 1) {\n report.push(` ...${this._abridgedOmittedLines} lines omitted...\\n`);\n }\n report.push(...this._abridgedTrailing);\n return report.join('');\n }\n\n public onWriteChunk(chunk: ITerminalChunk): void {\n if (chunk.text.length === 0 || chunk.text[chunk.text.length - 1] !== '\\n') {\n throw new Error(\n 'StdioSummarizer expects chunks that were separated parsed into lines by StderrLineTransform\\n' +\n ' Invalid input: ' +\n JSON.stringify(chunk.text)\n );\n }\n\n if (chunk.kind === TerminalChunkKind.Stderr && !this._abridgedStderr) {\n // The first time we see stderr, switch to capturing stderr\n this._abridgedStderr = true;\n this._abridgedLeading.length = 0;\n this._abridgedTrailing.length = 0;\n this._abridgedOmittedLines = 0;\n } else if (this._abridgedStderr && chunk.kind !== TerminalChunkKind.Stderr) {\n // If we're capturing stderr, then ignore non-stderr input\n return;\n }\n\n // Did we capture enough leading lines?\n if (this._abridgedLeading.length < this._leadingLines) {\n this._abridgedLeading.push(chunk.text);\n return;\n }\n\n this._abridgedTrailing.push(chunk.text);\n\n // If we captured to many trailing lines, omit the extras\n while (this._abridgedTrailing.length > this._trailingLines) {\n this._abridgedTrailing.shift();\n ++this._abridgedOmittedLines;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"StdioSummarizer.js","sourceRoot":"","sources":["../src/StdioSummarizer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\r\nimport { TerminalWritable } from './TerminalWritable';\r\n\r\n/**\r\n * Constructor options for {@link StdioSummarizer}.\r\n * @beta\r\n */\r\nexport interface IStdioSummarizerOptions {\r\n /**\r\n * Specifies the maximum number of leading lines to include in the summary.\r\n * @defaultValue `10`\r\n */\r\n leadingLines?: number;\r\n\r\n /**\r\n * Specifies the maximum number of trailing lines to include in the summary.\r\n * @defaultValue `10`\r\n */\r\n trailingLines?: number;\r\n}\r\n\r\n/**\r\n * Summarizes the results of a failed build task by returning a subset of `stderr` output not to exceed\r\n * a specified maximum number of lines.\r\n *\r\n * @remarks\r\n * IMPORTANT: This transform assumes that its input was prepared by {@link StderrLineTransform}, so that each\r\n * {@link ITerminalChunk.text} item is a single line terminated by a `\"\\n\"` character.\r\n *\r\n * The {@link IStdioSummarizerOptions.leadingLines} and {@link IStdioSummarizerOptions.trailingLines}\r\n * counts specify the maximum number of lines to be returned. Any additional lines will be omitted.\r\n * For example, if `leadingLines` and `trailingLines` were set to `3`, then the summary of 16 `stderr` lines might\r\n * look like this:\r\n *\r\n * ```\r\n * Line 1\r\n * Line 2\r\n * Line 3\r\n * ...10 lines omitted...\r\n * Line 14\r\n * Line 15\r\n * Line 16\r\n * ```\r\n *\r\n * If the `stderr` output is completely empty, then the `stdout` output will be summarized instead.\r\n *\r\n * @beta\r\n */\r\nexport class StdioSummarizer extends TerminalWritable {\r\n // Capture up to this many leading lines\r\n private _leadingLines: number;\r\n\r\n // Capture up to this many trailing lines\r\n private _trailingLines: number;\r\n\r\n private readonly _abridgedLeading: string[];\r\n private readonly _abridgedTrailing: string[];\r\n private _abridgedOmittedLines: number = 0;\r\n private _abridgedStderr: boolean;\r\n\r\n public constructor(options?: IStdioSummarizerOptions) {\r\n super();\r\n\r\n if (!options) {\r\n options = {};\r\n }\r\n\r\n this._leadingLines = options.leadingLines !== undefined ? options.leadingLines : 10;\r\n this._trailingLines = options.trailingLines !== undefined ? options.trailingLines : 10;\r\n\r\n this._abridgedLeading = [];\r\n this._abridgedTrailing = [];\r\n this._abridgedStderr = false;\r\n }\r\n\r\n /**\r\n * Returns the summary report.\r\n *\r\n * @remarks\r\n * The `close()` method must be called before `getReport()` can be used.\r\n */\r\n public getReport(): string {\r\n if (this.isOpen) {\r\n throw new Error('The summary cannot be prepared until after close() is called.');\r\n }\r\n const report: string[] = [...this._abridgedLeading];\r\n if (this._abridgedOmittedLines === 1) {\r\n report.push(` ...${this._abridgedOmittedLines} line omitted...\\n`);\r\n }\r\n if (this._abridgedOmittedLines > 1) {\r\n report.push(` ...${this._abridgedOmittedLines} lines omitted...\\n`);\r\n }\r\n report.push(...this._abridgedTrailing);\r\n return report.join('');\r\n }\r\n\r\n public onWriteChunk(chunk: ITerminalChunk): void {\r\n if (chunk.text.length === 0 || chunk.text[chunk.text.length - 1] !== '\\n') {\r\n throw new Error(\r\n 'StdioSummarizer expects chunks that were separated parsed into lines by StderrLineTransform\\n' +\r\n ' Invalid input: ' +\r\n JSON.stringify(chunk.text)\r\n );\r\n }\r\n\r\n if (chunk.kind === TerminalChunkKind.Stderr && !this._abridgedStderr) {\r\n // The first time we see stderr, switch to capturing stderr\r\n this._abridgedStderr = true;\r\n this._abridgedLeading.length = 0;\r\n this._abridgedTrailing.length = 0;\r\n this._abridgedOmittedLines = 0;\r\n } else if (this._abridgedStderr && chunk.kind !== TerminalChunkKind.Stderr) {\r\n // If we're capturing stderr, then ignore non-stderr input\r\n return;\r\n }\r\n\r\n // Did we capture enough leading lines?\r\n if (this._abridgedLeading.length < this._leadingLines) {\r\n this._abridgedLeading.push(chunk.text);\r\n return;\r\n }\r\n\r\n this._abridgedTrailing.push(chunk.text);\r\n\r\n // If we captured to many trailing lines, omit the extras\r\n while (this._abridgedTrailing.length > this._trailingLines) {\r\n this._abridgedTrailing.shift();\r\n ++this._abridgedOmittedLines;\r\n }\r\n }\r\n}\r\n"]}
|
package/lib/StdioWritable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StdioWritable.js","sourceRoot":"","sources":["../src/StdioWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;AAE3D,sDAA8B;AAE9B,yDAAsD;AAEtD;;;;;;;;;GASG;AACH,MAAa,aAAc,SAAQ,mCAAgB;IAGvC,YAAY,CAAC,KAAqB;QAC1C,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAC3C,iBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC;aAAM,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAClD,iBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC;IACH,CAAC;;AARa,sBAAQ,GAAkB,IAAI,aAAa,EAAE,CAAC;AADjD,sCAAa","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport process from 'process';\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\nimport { TerminalWritable } from './TerminalWritable';\n\n/**\n * A {@link TerminalWritable} subclass that writes its output directly to the process `stdout` and `stderr`\n * streams.\n *\n * @remarks\n * This is the standard output target for a process. You normally do not need to construct\n * this class; the {@link StdioWritable.\"instance\"} singleton can be used instead.\n *\n * @public\n */\nexport class StdioWritable extends TerminalWritable {\n public static instance: StdioWritable = new StdioWritable();\n\n protected onWriteChunk(chunk: ITerminalChunk): void {\n if (chunk.kind === TerminalChunkKind.Stdout) {\n process.stdout.write(chunk.text);\n } else if (chunk.kind === TerminalChunkKind.Stderr) {\n process.stderr.write(chunk.text);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"StdioWritable.js","sourceRoot":"","sources":["../src/StdioWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;AAE3D,sDAA8B;AAE9B,yDAAsD;AAEtD;;;;;;;;;GASG;AACH,MAAa,aAAc,SAAQ,mCAAgB;IAGvC,YAAY,CAAC,KAAqB;QAC1C,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAC3C,iBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC;aAAM,IAAI,KAAK,CAAC,IAAI,uCAA6B,EAAE;YAClD,iBAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC;IACH,CAAC;;AARa,sBAAQ,GAAkB,IAAI,aAAa,EAAE,CAAC;AADjD,sCAAa","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport process from 'process';\r\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\r\nimport { TerminalWritable } from './TerminalWritable';\r\n\r\n/**\r\n * A {@link TerminalWritable} subclass that writes its output directly to the process `stdout` and `stderr`\r\n * streams.\r\n *\r\n * @remarks\r\n * This is the standard output target for a process. You normally do not need to construct\r\n * this class; the {@link StdioWritable.\"instance\"} singleton can be used instead.\r\n *\r\n * @public\r\n */\r\nexport class StdioWritable extends TerminalWritable {\r\n public static instance: StdioWritable = new StdioWritable();\r\n\r\n protected onWriteChunk(chunk: ITerminalChunk): void {\r\n if (chunk.kind === TerminalChunkKind.Stdout) {\r\n process.stdout.write(chunk.text);\r\n } else if (chunk.kind === TerminalChunkKind.Stderr) {\r\n process.stderr.write(chunk.text);\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalTransform.js","sourceRoot":"","sources":["../src/TerminalTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAqF;AA2BrF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAsB,iBAAkB,SAAQ,mCAAgB;IAO9D,YAAmB,OAAkC;QACnD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,2BAA2B,GAAG,CAAC,CAAC,OAAO,CAAC,2BAA2B,CAAC;IAC3E,CAAC;IAED,gBAAgB;IACN,OAAO;QACf,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;OAWG;IACO,oBAAoB;QAC5B,IAAI,CAAC,IAAI,CAAC,2BAA2B,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE;YAC3E,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;SAC1B;IACH,CAAC;CACF;AAnCD,8CAmCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { TerminalWritable, type ITerminalWritableOptions } from './TerminalWritable';\n\n/**\n * Constructor options for {@link TerminalTransform}.\n *\n * @public\n */\nexport interface ITerminalTransformOptions extends ITerminalWritableOptions {\n /**\n * The target `TerminalWritable` that the `TerminalTransform` will write its\n * output to.\n */\n destination: TerminalWritable;\n\n /**\n * Prevents the {@link TerminalTransform.destination} object from being\n * closed automatically when the transform is closed.\n *\n * @remarks\n * When a transform is closed, normally it will automatically close its destination\n * `TerminalWritable` object. There are two ways to prevent that: either by setting\n * `preventDestinationAutoclose` to `true` for the transform, or by setting\n * {@link TerminalWritable.preventAutoclose} to `true` for the `destination` object.\n */\n preventDestinationAutoclose?: boolean;\n}\n\n/**\n * The abstract base class for {@link TerminalWritable} objects that receive an input,\n * transform it somehow, and then write the output to another `TerminalWritable`.\n *\n * @remarks\n *\n * The `TerminalTransform` and {@link SplitterTransform} base classes formalize the idea\n * of modeling data flow as a directed acyclic graph of reusable transforms, whose\n * final outputs are `TerminalWritable` objects.\n *\n * The design is based loosely on the `WritableStream` and `TransformStream` classes from\n * the system {@link https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Concepts\n * | Streams API}, except that instead of asynchronous byte streams, the `TerminalWritable`\n * system synchronously transmits human readable messages intended to be rendered on a\n * text console or log file.\n *\n * The main feature of the `TerminalTransform` class is its {@link TerminalTransform.destination}\n * property, which tracks the next link in the graph.\n *\n * @public\n */\nexport abstract class TerminalTransform extends TerminalWritable {\n /** {@inheritDoc ITerminalTransformOptions.destination} */\n public readonly destination: TerminalWritable;\n\n /** {@inheritDoc ITerminalTransformOptions.preventDestinationAutoclose} */\n public readonly preventDestinationAutoclose: boolean;\n\n public constructor(options: ITerminalTransformOptions) {\n super();\n this.destination = options.destination;\n this.preventDestinationAutoclose = !!options.preventDestinationAutoclose;\n }\n\n /** @override */\n protected onClose(): void {\n this.autocloseDestination();\n }\n\n /**\n * The default implementation of {@link TerminalTransform.onClose} calls this\n * method, which closes the {@link TerminalTransform.destination} if appropriate.\n *\n * @remarks\n * The destination will not be closed if its {@link TerminalWritable.preventAutoclose}\n * property is `true`. The destination will not be closed if\n * {@link ITerminalTransformOptions.preventDestinationAutoclose}\n * is `true`.\n *\n * @sealed\n */\n protected autocloseDestination(): void {\n if (!this.preventDestinationAutoclose && !this.destination.preventAutoclose) {\n this.destination.close();\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TerminalTransform.js","sourceRoot":"","sources":["../src/TerminalTransform.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,yDAAqF;AA2BrF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAsB,iBAAkB,SAAQ,mCAAgB;IAO9D,YAAmB,OAAkC;QACnD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,2BAA2B,GAAG,CAAC,CAAC,OAAO,CAAC,2BAA2B,CAAC;IAC3E,CAAC;IAED,gBAAgB;IACN,OAAO;QACf,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;OAWG;IACO,oBAAoB;QAC5B,IAAI,CAAC,IAAI,CAAC,2BAA2B,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,EAAE;YAC3E,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;SAC1B;IACH,CAAC;CACF;AAnCD,8CAmCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { TerminalWritable, type ITerminalWritableOptions } from './TerminalWritable';\r\n\r\n/**\r\n * Constructor options for {@link TerminalTransform}.\r\n *\r\n * @public\r\n */\r\nexport interface ITerminalTransformOptions extends ITerminalWritableOptions {\r\n /**\r\n * The target `TerminalWritable` that the `TerminalTransform` will write its\r\n * output to.\r\n */\r\n destination: TerminalWritable;\r\n\r\n /**\r\n * Prevents the {@link TerminalTransform.destination} object from being\r\n * closed automatically when the transform is closed.\r\n *\r\n * @remarks\r\n * When a transform is closed, normally it will automatically close its destination\r\n * `TerminalWritable` object. There are two ways to prevent that: either by setting\r\n * `preventDestinationAutoclose` to `true` for the transform, or by setting\r\n * {@link TerminalWritable.preventAutoclose} to `true` for the `destination` object.\r\n */\r\n preventDestinationAutoclose?: boolean;\r\n}\r\n\r\n/**\r\n * The abstract base class for {@link TerminalWritable} objects that receive an input,\r\n * transform it somehow, and then write the output to another `TerminalWritable`.\r\n *\r\n * @remarks\r\n *\r\n * The `TerminalTransform` and {@link SplitterTransform} base classes formalize the idea\r\n * of modeling data flow as a directed acyclic graph of reusable transforms, whose\r\n * final outputs are `TerminalWritable` objects.\r\n *\r\n * The design is based loosely on the `WritableStream` and `TransformStream` classes from\r\n * the system {@link https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Concepts\r\n * | Streams API}, except that instead of asynchronous byte streams, the `TerminalWritable`\r\n * system synchronously transmits human readable messages intended to be rendered on a\r\n * text console or log file.\r\n *\r\n * The main feature of the `TerminalTransform` class is its {@link TerminalTransform.destination}\r\n * property, which tracks the next link in the graph.\r\n *\r\n * @public\r\n */\r\nexport abstract class TerminalTransform extends TerminalWritable {\r\n /** {@inheritDoc ITerminalTransformOptions.destination} */\r\n public readonly destination: TerminalWritable;\r\n\r\n /** {@inheritDoc ITerminalTransformOptions.preventDestinationAutoclose} */\r\n public readonly preventDestinationAutoclose: boolean;\r\n\r\n public constructor(options: ITerminalTransformOptions) {\r\n super();\r\n this.destination = options.destination;\r\n this.preventDestinationAutoclose = !!options.preventDestinationAutoclose;\r\n }\r\n\r\n /** @override */\r\n protected onClose(): void {\r\n this.autocloseDestination();\r\n }\r\n\r\n /**\r\n * The default implementation of {@link TerminalTransform.onClose} calls this\r\n * method, which closes the {@link TerminalTransform.destination} if appropriate.\r\n *\r\n * @remarks\r\n * The destination will not be closed if its {@link TerminalWritable.preventAutoclose}\r\n * property is `true`. The destination will not be closed if\r\n * {@link ITerminalTransformOptions.preventDestinationAutoclose}\r\n * is `true`.\r\n *\r\n * @sealed\r\n */\r\n protected autocloseDestination(): void {\r\n if (!this.preventDestinationAutoclose && !this.destination.preventAutoclose) {\r\n this.destination.close();\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalWritable.js","sourceRoot":"","sources":["../src/TerminalWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAwB3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,MAAsB,gBAAgB;IAKpC,YAAmB,OAAkC;QACnD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,GAAG,EAAE,CAAC;SACd;QAED,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC;IACrD,CAAC;IAED;;;;OAIG;IACH,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,UAAU,CAAC,KAAqB;QACrC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;SAC9C;QACD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAOD;;;;;;;;;;;;OAYG;IACI,KAAK;QACV,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;SACtB;IACH,CAAC;IAED;;;;;;;;;OASG;IACO,OAAO,KAAU,CAAC;CAC7B;AAhFD,4CAgFC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { ITerminalChunk } from './ITerminalChunk';\n\n/**\n * Constructor options for {@link TerminalWritable}\n *\n * @public\n */\nexport interface ITerminalWritableOptions {\n /**\n * When this object is the {@link TerminalTransform.destination} for a transform,\n * the transform will automatically close this object. Set `preventAutoclose` to `true`\n * to prevent that behavior.\n *\n * @remarks\n * When a transform is closed, normally it will automatically close its destination\n * `TerminalWritable` object. There are two ways to prevent that: either by setting\n * `preventDestinationAutoclose` to `true` for the transform, or by setting\n * {@link TerminalWritable.preventAutoclose} to `true` for the `destination` object.\n */\n preventAutoclose?: boolean;\n}\n\n/**\n * The abstract base class for objects that can present, route, or process text output for\n * a console application. This output is typically prepared using\n * the {@link @rushstack/node-core-library#Terminal} API.\n *\n * @remarks\n *\n * The design is based loosely on the `WritableStream` and `TransformStream` classes from\n * the system {@link https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Concepts\n * | Streams API}, except that instead of asynchronous byte streams, the `TerminalWritable`\n * system synchronously transmits human readable messages intended to be rendered on a text\n * console or log file.\n *\n * Consider a console application whose output may need to be processed in different ways\n * before finally being output. The conceptual block diagram might look like this:\n *\n * ```\n * [Terminal API]\n * |\n * V\n * [normalize newlines]\n * |\n * V\n * +----[splitter]-------+\n * | |\n * V V\n * [shell console] [remove ANSI colors]\n * |\n * V\n * [write to build.log]\n * ```\n *\n * The application uses the `Terminal` API to print `stdout` and `stderr` messages, for example with standardized\n * formatting for errors and warnings, and ANSI escapes to make nice colors. Maybe it also includes text\n * received from external processes, whose newlines may be inconsistent. Ultimately we want to write the\n * output to the shell console and a `build.log` file, but we don't want to put ANSI colors in the build log.\n *\n * For the above example, `[shell console]` and `[write to build.log]` would be modeled as subclasses of\n * `TerminalWritable`. The `[normalize newlines]` and `[remove ANSI colors]` steps are modeled as subclasses\n * of {@link TerminalTransform}, because they output to a \"destination\" object. The `[splitter]` would be\n * implemented using {@link SplitterTransform}.\n *\n * The stream of messages are {@link ITerminalChunk} objects, which can represent both `stdout` and `stderr`\n * channels. The pipeline operates synchronously on each chunk, but by processing one chunk at a time,\n * it avoids storing the entire output in memory. This means that operations like `[remove ANSI colors]`\n * cannot be simple regular expressions -- they must be implemented as state machines ({@link TextRewriter}\n * subclasses) capable of matching substrings that span multiple chunks.\n *\n * @public\n */\nexport abstract class TerminalWritable {\n private _isOpen: boolean;\n\n public readonly preventAutoclose: boolean;\n\n public constructor(options?: ITerminalWritableOptions) {\n this._isOpen = true;\n\n if (!options) {\n options = {};\n }\n\n this.preventAutoclose = !!options.preventAutoclose;\n }\n\n /**\n * This property is initially `true` when the object is constructed, and becomes `false`\n * when `close()` is called.\n * @sealed\n */\n public get isOpen(): boolean {\n return this._isOpen;\n }\n\n /**\n * Upstream objects call this method to provide inputs to this object.\n *\n * @remarks\n * The subclass provides its implementation via the the {@link TerminalWritable.onWriteChunk}\n * method, which is called by `writeChunk()`.\n *\n * The object that calls `writeChunk()` must call `close()` when it is finished;\n * failing to do so may introduce a resource leak, or may prevent some buffered data from\n * being written.\n *\n * @sealed\n */\n public writeChunk(chunk: ITerminalChunk): void {\n if (!this._isOpen) {\n throw new Error('Writer was already closed');\n }\n this.onWriteChunk(chunk);\n }\n\n /**\n * Subclasses should implement this `abstract` method to process the chunk.\n */\n protected abstract onWriteChunk(chunk: ITerminalChunk): void;\n\n /**\n * Calling this method flushes any remaining outputs and permanently transitions the\n * `TerminalWritable` to a \"closed\" state, where no further chunks can be written.\n *\n * @remarks\n * The subclass provides its implementation via the the {@link TerminalWritable.onClose}\n * method, which is called by `close()`.\n *\n * If this method is called more than once, the additional calls are ignored;\n * `TerminalWritable.onClose` will be called at most once.\n *\n * @sealed\n */\n public close(): void {\n if (this._isOpen) {\n this.onClose();\n this._isOpen = false;\n }\n }\n\n /**\n * Subclasses can override this empty method to perform additional operations\n * such as closing a file handle.\n *\n * @remarks\n * It is guaranteed that this method will be called at most once during the lifetime\n * of a `TerminalWritable` object.\n *\n * @virtual\n */\n protected onClose(): void {}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TerminalWritable.js","sourceRoot":"","sources":["../src/TerminalWritable.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAwB3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,MAAsB,gBAAgB;IAKpC,YAAmB,OAAkC;QACnD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,GAAG,EAAE,CAAC;SACd;QAED,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC;IACrD,CAAC;IAED;;;;OAIG;IACH,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,UAAU,CAAC,KAAqB;QACrC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;SAC9C;QACD,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAOD;;;;;;;;;;;;OAYG;IACI,KAAK;QACV,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;SACtB;IACH,CAAC;IAED;;;;;;;;;OASG;IACO,OAAO,KAAU,CAAC;CAC7B;AAhFD,4CAgFC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport type { ITerminalChunk } from './ITerminalChunk';\r\n\r\n/**\r\n * Constructor options for {@link TerminalWritable}\r\n *\r\n * @public\r\n */\r\nexport interface ITerminalWritableOptions {\r\n /**\r\n * When this object is the {@link TerminalTransform.destination} for a transform,\r\n * the transform will automatically close this object. Set `preventAutoclose` to `true`\r\n * to prevent that behavior.\r\n *\r\n * @remarks\r\n * When a transform is closed, normally it will automatically close its destination\r\n * `TerminalWritable` object. There are two ways to prevent that: either by setting\r\n * `preventDestinationAutoclose` to `true` for the transform, or by setting\r\n * {@link TerminalWritable.preventAutoclose} to `true` for the `destination` object.\r\n */\r\n preventAutoclose?: boolean;\r\n}\r\n\r\n/**\r\n * The abstract base class for objects that can present, route, or process text output for\r\n * a console application. This output is typically prepared using\r\n * the {@link @rushstack/node-core-library#Terminal} API.\r\n *\r\n * @remarks\r\n *\r\n * The design is based loosely on the `WritableStream` and `TransformStream` classes from\r\n * the system {@link https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Concepts\r\n * | Streams API}, except that instead of asynchronous byte streams, the `TerminalWritable`\r\n * system synchronously transmits human readable messages intended to be rendered on a text\r\n * console or log file.\r\n *\r\n * Consider a console application whose output may need to be processed in different ways\r\n * before finally being output. The conceptual block diagram might look like this:\r\n *\r\n * ```\r\n * [Terminal API]\r\n * |\r\n * V\r\n * [normalize newlines]\r\n * |\r\n * V\r\n * +----[splitter]-------+\r\n * | |\r\n * V V\r\n * [shell console] [remove ANSI colors]\r\n * |\r\n * V\r\n * [write to build.log]\r\n * ```\r\n *\r\n * The application uses the `Terminal` API to print `stdout` and `stderr` messages, for example with standardized\r\n * formatting for errors and warnings, and ANSI escapes to make nice colors. Maybe it also includes text\r\n * received from external processes, whose newlines may be inconsistent. Ultimately we want to write the\r\n * output to the shell console and a `build.log` file, but we don't want to put ANSI colors in the build log.\r\n *\r\n * For the above example, `[shell console]` and `[write to build.log]` would be modeled as subclasses of\r\n * `TerminalWritable`. The `[normalize newlines]` and `[remove ANSI colors]` steps are modeled as subclasses\r\n * of {@link TerminalTransform}, because they output to a \"destination\" object. The `[splitter]` would be\r\n * implemented using {@link SplitterTransform}.\r\n *\r\n * The stream of messages are {@link ITerminalChunk} objects, which can represent both `stdout` and `stderr`\r\n * channels. The pipeline operates synchronously on each chunk, but by processing one chunk at a time,\r\n * it avoids storing the entire output in memory. This means that operations like `[remove ANSI colors]`\r\n * cannot be simple regular expressions -- they must be implemented as state machines ({@link TextRewriter}\r\n * subclasses) capable of matching substrings that span multiple chunks.\r\n *\r\n * @public\r\n */\r\nexport abstract class TerminalWritable {\r\n private _isOpen: boolean;\r\n\r\n public readonly preventAutoclose: boolean;\r\n\r\n public constructor(options?: ITerminalWritableOptions) {\r\n this._isOpen = true;\r\n\r\n if (!options) {\r\n options = {};\r\n }\r\n\r\n this.preventAutoclose = !!options.preventAutoclose;\r\n }\r\n\r\n /**\r\n * This property is initially `true` when the object is constructed, and becomes `false`\r\n * when `close()` is called.\r\n * @sealed\r\n */\r\n public get isOpen(): boolean {\r\n return this._isOpen;\r\n }\r\n\r\n /**\r\n * Upstream objects call this method to provide inputs to this object.\r\n *\r\n * @remarks\r\n * The subclass provides its implementation via the the {@link TerminalWritable.onWriteChunk}\r\n * method, which is called by `writeChunk()`.\r\n *\r\n * The object that calls `writeChunk()` must call `close()` when it is finished;\r\n * failing to do so may introduce a resource leak, or may prevent some buffered data from\r\n * being written.\r\n *\r\n * @sealed\r\n */\r\n public writeChunk(chunk: ITerminalChunk): void {\r\n if (!this._isOpen) {\r\n throw new Error('Writer was already closed');\r\n }\r\n this.onWriteChunk(chunk);\r\n }\r\n\r\n /**\r\n * Subclasses should implement this `abstract` method to process the chunk.\r\n */\r\n protected abstract onWriteChunk(chunk: ITerminalChunk): void;\r\n\r\n /**\r\n * Calling this method flushes any remaining outputs and permanently transitions the\r\n * `TerminalWritable` to a \"closed\" state, where no further chunks can be written.\r\n *\r\n * @remarks\r\n * The subclass provides its implementation via the the {@link TerminalWritable.onClose}\r\n * method, which is called by `close()`.\r\n *\r\n * If this method is called more than once, the additional calls are ignored;\r\n * `TerminalWritable.onClose` will be called at most once.\r\n *\r\n * @sealed\r\n */\r\n public close(): void {\r\n if (this._isOpen) {\r\n this.onClose();\r\n this._isOpen = false;\r\n }\r\n }\r\n\r\n /**\r\n * Subclasses can override this empty method to perform additional operations\r\n * such as closing a file handle.\r\n *\r\n * @remarks\r\n * It is guaranteed that this method will be called at most once during the lifetime\r\n * of a `TerminalWritable` object.\r\n *\r\n * @virtual\r\n */\r\n protected onClose(): void {}\r\n}\r\n"]}
|
package/lib/TextRewriter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextRewriter.js","sourceRoot":"","sources":["../src/TextRewriter.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AA6B3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAsB,YAAY;CAejC;AAfD,oCAeC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { Brand } from '@rushstack/node-core-library';\n\n/**\n * Represents the internal state of a {@link TextRewriter} subclass.\n *\n * @remarks\n * For example, suppose that {@link NormalizeNewlinesTextRewriter} will be used to rewrite\n * the input `\"line 1\\r\\nline 2\\r\\n\"` to become `\"line 1\\nline 2\\n\"`. But suppose that the `\"\\r\\n\"`\n * pair is split across two chunks:\n *\n * ```ts\n * const rewriter: NormalizeNewlinesTextRewriter = new NormalizeNewlinesTextRewriter(NewlineKind.Lf);\n * const state: TextRewriterState = rewriter.initialize();\n * let output: string = rewriter.process(state, 'line 1\\r');\n * output += rewriter.process(state, '\\nline 2\\r\\n');\n * output += rewriter.close(state);\n *\n * // The final \"output\" value is: \"line 1\\nline 2\\n\"\n * ```\n *\n * The `TextRewriterState` keeps track of this context, so that split `\"\\r\"` and `\"\\n\"` are\n * interpreted as a single newline.\n *\n * @public\n */\nexport type TextRewriterState = Brand<unknown, 'TextRewriterState'>;\n\n/**\n * The abstract base class for operations that can be applied by {@link TextRewriterTransform}.\n *\n * @remarks\n * The {@link TextRewriterTransform} applies one or more character rewriting operations to its\n * chunk stream. Since these operations are applied separately to `stderr` and `stdout`, the\n * state is stored in an opaque `TextRewriterState` object.\n *\n * Conceptually, a `TextRewriter` subclass is very similar to a regular expression, with the difference\n * that `RegExp` operates on a text string, whereas `TextRewriter` operates on a stream of characters.\n *\n * The two most common subclasses are {@link NormalizeNewlinesTextRewriter} and {@link RemoveColorsTextRewriter}.\n *\n * A rewriting operation starts with `initialize()`, followed by any number of `process()` calls, and\n * then finishes with `close()`. For example:\n *\n * ```ts\n * const rewriter: NormalizeNewlinesTextRewriter = new NormalizeNewlinesTextRewriter(NewlineKind.Lf);\n * const state: TextRewriterState = rewriter.initialize();\n * let output: string = rewriter.process(state, 'line 1\\r');\n * output += rewriter.process(state, '\\nline 2\\r\\n');\n * output += rewriter.close(state);\n *\n * // The final \"output\" value is: \"line 1\\nline 2\\n\"\n * ```\n *\n * After `close()` has been called, the `TextRewriterState` state should not be reused.\n *\n * @public\n */\nexport abstract class TextRewriter {\n /**\n * Create a new `TextRewriterState` object that can be used to process a stream of characters.\n */\n public abstract initialize(): TextRewriterState;\n\n /**\n * Rewrite the next sequence of characters from the input stream, returning the modified output.\n */\n public abstract process(state: TextRewriterState, input: string): string;\n\n /**\n * Close the `TextRewriterState` object and return any buffered output.\n */\n public abstract close(state: TextRewriterState): string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TextRewriter.js","sourceRoot":"","sources":["../src/TextRewriter.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AA6B3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAsB,YAAY;CAejC;AAfD,oCAeC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport type { Brand } from '@rushstack/node-core-library';\r\n\r\n/**\r\n * Represents the internal state of a {@link TextRewriter} subclass.\r\n *\r\n * @remarks\r\n * For example, suppose that {@link NormalizeNewlinesTextRewriter} will be used to rewrite\r\n * the input `\"line 1\\r\\nline 2\\r\\n\"` to become `\"line 1\\nline 2\\n\"`. But suppose that the `\"\\r\\n\"`\r\n * pair is split across two chunks:\r\n *\r\n * ```ts\r\n * const rewriter: NormalizeNewlinesTextRewriter = new NormalizeNewlinesTextRewriter(NewlineKind.Lf);\r\n * const state: TextRewriterState = rewriter.initialize();\r\n * let output: string = rewriter.process(state, 'line 1\\r');\r\n * output += rewriter.process(state, '\\nline 2\\r\\n');\r\n * output += rewriter.close(state);\r\n *\r\n * // The final \"output\" value is: \"line 1\\nline 2\\n\"\r\n * ```\r\n *\r\n * The `TextRewriterState` keeps track of this context, so that split `\"\\r\"` and `\"\\n\"` are\r\n * interpreted as a single newline.\r\n *\r\n * @public\r\n */\r\nexport type TextRewriterState = Brand<unknown, 'TextRewriterState'>;\r\n\r\n/**\r\n * The abstract base class for operations that can be applied by {@link TextRewriterTransform}.\r\n *\r\n * @remarks\r\n * The {@link TextRewriterTransform} applies one or more character rewriting operations to its\r\n * chunk stream. Since these operations are applied separately to `stderr` and `stdout`, the\r\n * state is stored in an opaque `TextRewriterState` object.\r\n *\r\n * Conceptually, a `TextRewriter` subclass is very similar to a regular expression, with the difference\r\n * that `RegExp` operates on a text string, whereas `TextRewriter` operates on a stream of characters.\r\n *\r\n * The two most common subclasses are {@link NormalizeNewlinesTextRewriter} and {@link RemoveColorsTextRewriter}.\r\n *\r\n * A rewriting operation starts with `initialize()`, followed by any number of `process()` calls, and\r\n * then finishes with `close()`. For example:\r\n *\r\n * ```ts\r\n * const rewriter: NormalizeNewlinesTextRewriter = new NormalizeNewlinesTextRewriter(NewlineKind.Lf);\r\n * const state: TextRewriterState = rewriter.initialize();\r\n * let output: string = rewriter.process(state, 'line 1\\r');\r\n * output += rewriter.process(state, '\\nline 2\\r\\n');\r\n * output += rewriter.close(state);\r\n *\r\n * // The final \"output\" value is: \"line 1\\nline 2\\n\"\r\n * ```\r\n *\r\n * After `close()` has been called, the `TextRewriterState` state should not be reused.\r\n *\r\n * @public\r\n */\r\nexport abstract class TextRewriter {\r\n /**\r\n * Create a new `TextRewriterState` object that can be used to process a stream of characters.\r\n */\r\n public abstract initialize(): TextRewriterState;\r\n\r\n /**\r\n * Rewrite the next sequence of characters from the input stream, returning the modified output.\r\n */\r\n public abstract process(state: TextRewriterState, input: string): string;\r\n\r\n /**\r\n * Close the `TextRewriterState` object and return any buffered output.\r\n */\r\n public abstract close(state: TextRewriterState): string;\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextRewriterTransform.js","sourceRoot":"","sources":["../src/TextRewriterTransform.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { NewlineKind } from '@rushstack/node-core-library';\n\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\nimport { TerminalTransform, type ITerminalTransformOptions } from './TerminalTransform';\nimport type { TextRewriter, TextRewriterState } from './TextRewriter';\nimport { RemoveColorsTextRewriter } from './RemoveColorsTextRewriter';\nimport { NormalizeNewlinesTextRewriter } from './NormalizeNewlinesTextRewriter';\n\n/**\n * Constructor options for {@link TextRewriterTransform}.\n *\n * @public\n */\nexport interface ITextRewriterTransformOptions extends ITerminalTransformOptions {\n /**\n * A list of rewriters to be applied. More items may be appended to the list, for example\n * if {@link ITextRewriterTransformOptions.removeColors} is specified.\n *\n * @remarks\n * The final list must contain at least one item.\n */\n textRewriters?: TextRewriter[];\n\n /**\n * If specified, a {@link RemoveColorsTextRewriter} will be appended to the list of rewriters.\n */\n removeColors?: boolean;\n\n /**\n * If `normalizeNewlines` or `ensureNewlineAtEnd` is specified, a {@link NormalizeNewlinesTextRewriter}\n * will be appended to the list of rewriters with the specified settings.\n *\n * @remarks\n * See {@link INormalizeNewlinesTextRewriterOptions} for details.\n */\n normalizeNewlines?: NewlineKind;\n\n /**\n * If `normalizeNewlines` or `ensureNewlineAtEnd` is specified, a {@link NormalizeNewlinesTextRewriter}\n * will be appended to the list of rewriters with the specified settings.\n *\n * @remarks\n * See {@link INormalizeNewlinesTextRewriterOptions} for details.\n */\n ensureNewlineAtEnd?: boolean;\n}\n\n/**\n * A {@link TerminalTransform} subclass that performs one or more {@link TextRewriter} operations.\n * The most common operations are {@link NormalizeNewlinesTextRewriter} and {@link RemoveColorsTextRewriter}.\n *\n * @remarks\n * The `TextRewriter` operations are applied separately to the `stderr` and `stdout` streams.\n * If multiple {@link ITextRewriterTransformOptions.textRewriters} are configured, they are applied\n * in the order that they appear in the array.\n *\n * @public\n */\nexport class TextRewriterTransform extends TerminalTransform {\n private readonly _stderrStates: TextRewriterState[];\n private readonly _stdoutStates: TextRewriterState[];\n\n public readonly textRewriters: ReadonlyArray<TextRewriter>;\n\n public constructor(options: ITextRewriterTransformOptions) {\n super(options);\n\n const textRewriters: TextRewriter[] = options.textRewriters || [];\n\n if (options.removeColors) {\n textRewriters.push(new RemoveColorsTextRewriter());\n }\n if (options.normalizeNewlines) {\n textRewriters.push(\n new NormalizeNewlinesTextRewriter({\n newlineKind: options.normalizeNewlines,\n ensureNewlineAtEnd: options.ensureNewlineAtEnd\n })\n );\n }\n\n if (textRewriters.length === 0) {\n throw new Error('TextRewriterTransform requires at least one matcher');\n }\n\n this.textRewriters = textRewriters;\n\n this._stderrStates = this.textRewriters.map((x) => x.initialize());\n this._stdoutStates = this.textRewriters.map((x) => x.initialize());\n }\n\n protected onWriteChunk(chunk: ITerminalChunk): void {\n if (chunk.kind === TerminalChunkKind.Stderr) {\n this._processText(chunk, this._stderrStates);\n } else if (chunk.kind === TerminalChunkKind.Stdout) {\n this._processText(chunk, this._stdoutStates);\n } else {\n this.destination.writeChunk(chunk);\n }\n }\n\n private _processText(chunk: ITerminalChunk, states: TextRewriterState[]): void {\n let text: string = chunk.text;\n for (let i: number = 0; i < states.length; ++i) {\n if (text.length > 0) {\n text = this.textRewriters[i].process(states[i], text);\n }\n }\n if (text.length > 0) {\n // If possible, avoid allocating a new chunk\n if (text === chunk.text) {\n this.destination.writeChunk(chunk);\n } else {\n this.destination.writeChunk({\n text: text,\n kind: chunk.kind\n });\n }\n }\n }\n\n private _closeRewriters(states: TextRewriterState[], chunkKind: TerminalChunkKind): void {\n let text: string = '';\n for (let i: number = 0; i < states.length; ++i) {\n if (text.length > 0) {\n text = this.textRewriters[i].process(states[i], text);\n }\n text += this.textRewriters[i].close(states[i]);\n }\n if (text.length > 0) {\n this.destination.writeChunk({\n text: text,\n kind: chunkKind\n });\n }\n }\n\n protected onClose(): void {\n this._closeRewriters(this._stderrStates, TerminalChunkKind.Stderr);\n this._closeRewriters(this._stdoutStates, TerminalChunkKind.Stdout);\n\n this.autocloseDestination();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TextRewriterTransform.js","sourceRoot":"","sources":["../src/TextRewriterTransform.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport type { NewlineKind } from '@rushstack/node-core-library';\r\n\r\nimport { type ITerminalChunk, TerminalChunkKind } from './ITerminalChunk';\r\nimport { TerminalTransform, type ITerminalTransformOptions } from './TerminalTransform';\r\nimport type { TextRewriter, TextRewriterState } from './TextRewriter';\r\nimport { RemoveColorsTextRewriter } from './RemoveColorsTextRewriter';\r\nimport { NormalizeNewlinesTextRewriter } from './NormalizeNewlinesTextRewriter';\r\n\r\n/**\r\n * Constructor options for {@link TextRewriterTransform}.\r\n *\r\n * @public\r\n */\r\nexport interface ITextRewriterTransformOptions extends ITerminalTransformOptions {\r\n /**\r\n * A list of rewriters to be applied. More items may be appended to the list, for example\r\n * if {@link ITextRewriterTransformOptions.removeColors} is specified.\r\n *\r\n * @remarks\r\n * The final list must contain at least one item.\r\n */\r\n textRewriters?: TextRewriter[];\r\n\r\n /**\r\n * If specified, a {@link RemoveColorsTextRewriter} will be appended to the list of rewriters.\r\n */\r\n removeColors?: boolean;\r\n\r\n /**\r\n * If `normalizeNewlines` or `ensureNewlineAtEnd` is specified, a {@link NormalizeNewlinesTextRewriter}\r\n * will be appended to the list of rewriters with the specified settings.\r\n *\r\n * @remarks\r\n * See {@link INormalizeNewlinesTextRewriterOptions} for details.\r\n */\r\n normalizeNewlines?: NewlineKind;\r\n\r\n /**\r\n * If `normalizeNewlines` or `ensureNewlineAtEnd` is specified, a {@link NormalizeNewlinesTextRewriter}\r\n * will be appended to the list of rewriters with the specified settings.\r\n *\r\n * @remarks\r\n * See {@link INormalizeNewlinesTextRewriterOptions} for details.\r\n */\r\n ensureNewlineAtEnd?: boolean;\r\n}\r\n\r\n/**\r\n * A {@link TerminalTransform} subclass that performs one or more {@link TextRewriter} operations.\r\n * The most common operations are {@link NormalizeNewlinesTextRewriter} and {@link RemoveColorsTextRewriter}.\r\n *\r\n * @remarks\r\n * The `TextRewriter` operations are applied separately to the `stderr` and `stdout` streams.\r\n * If multiple {@link ITextRewriterTransformOptions.textRewriters} are configured, they are applied\r\n * in the order that they appear in the array.\r\n *\r\n * @public\r\n */\r\nexport class TextRewriterTransform extends TerminalTransform {\r\n private readonly _stderrStates: TextRewriterState[];\r\n private readonly _stdoutStates: TextRewriterState[];\r\n\r\n public readonly textRewriters: ReadonlyArray<TextRewriter>;\r\n\r\n public constructor(options: ITextRewriterTransformOptions) {\r\n super(options);\r\n\r\n const textRewriters: TextRewriter[] = options.textRewriters || [];\r\n\r\n if (options.removeColors) {\r\n textRewriters.push(new RemoveColorsTextRewriter());\r\n }\r\n if (options.normalizeNewlines) {\r\n textRewriters.push(\r\n new NormalizeNewlinesTextRewriter({\r\n newlineKind: options.normalizeNewlines,\r\n ensureNewlineAtEnd: options.ensureNewlineAtEnd\r\n })\r\n );\r\n }\r\n\r\n if (textRewriters.length === 0) {\r\n throw new Error('TextRewriterTransform requires at least one matcher');\r\n }\r\n\r\n this.textRewriters = textRewriters;\r\n\r\n this._stderrStates = this.textRewriters.map((x) => x.initialize());\r\n this._stdoutStates = this.textRewriters.map((x) => x.initialize());\r\n }\r\n\r\n protected onWriteChunk(chunk: ITerminalChunk): void {\r\n if (chunk.kind === TerminalChunkKind.Stderr) {\r\n this._processText(chunk, this._stderrStates);\r\n } else if (chunk.kind === TerminalChunkKind.Stdout) {\r\n this._processText(chunk, this._stdoutStates);\r\n } else {\r\n this.destination.writeChunk(chunk);\r\n }\r\n }\r\n\r\n private _processText(chunk: ITerminalChunk, states: TextRewriterState[]): void {\r\n let text: string = chunk.text;\r\n for (let i: number = 0; i < states.length; ++i) {\r\n if (text.length > 0) {\r\n text = this.textRewriters[i].process(states[i], text);\r\n }\r\n }\r\n if (text.length > 0) {\r\n // If possible, avoid allocating a new chunk\r\n if (text === chunk.text) {\r\n this.destination.writeChunk(chunk);\r\n } else {\r\n this.destination.writeChunk({\r\n text: text,\r\n kind: chunk.kind\r\n });\r\n }\r\n }\r\n }\r\n\r\n private _closeRewriters(states: TextRewriterState[], chunkKind: TerminalChunkKind): void {\r\n let text: string = '';\r\n for (let i: number = 0; i < states.length; ++i) {\r\n if (text.length > 0) {\r\n text = this.textRewriters[i].process(states[i], text);\r\n }\r\n text += this.textRewriters[i].close(states[i]);\r\n }\r\n if (text.length > 0) {\r\n this.destination.writeChunk({\r\n text: text,\r\n kind: chunkKind\r\n });\r\n }\r\n }\r\n\r\n protected onClose(): void {\r\n this._closeRewriters(this._stderrStates, TerminalChunkKind.Stderr);\r\n this._closeRewriters(this._stdoutStates, TerminalChunkKind.Stdout);\r\n\r\n this.autocloseDestination();\r\n }\r\n}\r\n"]}
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;AAE3D;;;;;;;;GAQG;AAEH,qDAAmC;AACnC,2DAAyC;AACzC,mDAAiC;AACjC,iDAA+B;AAC/B,kEAAgD;AAChD,mDAAiC;AACjC,6DAA2C;AAC3C,sDAAoC;AACpC,uDAAqC;AACrC,oDAAkC;AAClC,kDAAgC;AAChC,sDAAoC;AACpC,qDAAmC;AACnC,iDAA+B;AAC/B,0DAAwC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\n/**\n * This library implements a system for processing human readable text that\n * will be output by console applications.\n *\n * @remarks\n * See the {@link TerminalWritable} documentation for an overview of the major concepts.\n *\n * @packageDocumentation\n */\n\nexport * from './CallbackWritable';\nexport * from './DiscardStdoutTransform';\nexport * from './ITerminalChunk';\nexport * from './MockWritable';\nexport * from './NormalizeNewlinesTextRewriter';\nexport * from './PrintUtilities';\nexport * from './RemoveColorsTextRewriter';\nexport * from './SplitterTransform';\nexport * from './StdioLineTransform';\nexport * from './StdioSummarizer';\nexport * from './StdioWritable';\nexport * from './TerminalTransform';\nexport * from './TerminalWritable';\nexport * from './TextRewriter';\nexport * from './TextRewriterTransform';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;;;;;;;;;;;;AAE3D;;;;;;;;GAQG;AAEH,qDAAmC;AACnC,2DAAyC;AACzC,mDAAiC;AACjC,iDAA+B;AAC/B,kEAAgD;AAChD,mDAAiC;AACjC,6DAA2C;AAC3C,sDAAoC;AACpC,uDAAqC;AACrC,oDAAkC;AAClC,kDAAgC;AAChC,sDAAoC;AACpC,qDAAmC;AACnC,iDAA+B;AAC/B,0DAAwC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\n/**\r\n * This library implements a system for processing human readable text that\r\n * will be output by console applications.\r\n *\r\n * @remarks\r\n * See the {@link TerminalWritable} documentation for an overview of the major concepts.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nexport * from './CallbackWritable';\r\nexport * from './DiscardStdoutTransform';\r\nexport * from './ITerminalChunk';\r\nexport * from './MockWritable';\r\nexport * from './NormalizeNewlinesTextRewriter';\r\nexport * from './PrintUtilities';\r\nexport * from './RemoveColorsTextRewriter';\r\nexport * from './SplitterTransform';\r\nexport * from './StdioLineTransform';\r\nexport * from './StdioSummarizer';\r\nexport * from './StdioWritable';\r\nexport * from './TerminalTransform';\r\nexport * from './TerminalWritable';\r\nexport * from './TextRewriter';\r\nexport * from './TextRewriterTransform';\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rushstack/terminal",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.10",
|
|
4
4
|
"description": "User interface primitives for console applications",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "dist/terminal.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"colors": "~1.2.1",
|
|
18
|
-
"@rushstack/heft": "0.
|
|
18
|
+
"@rushstack/heft": "0.63.0",
|
|
19
19
|
"local-node-rig": "1.0.0"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|