Comparing version 3.4.0 to 4.0.0
@@ -28,3 +28,3 @@ /// <reference types="node"/> | ||
/** | ||
Text to display before the spinner. | ||
Text to display before the spinner. No prefix text will be displayed if set to an empty string. | ||
*/ | ||
@@ -74,3 +74,5 @@ readonly prefixText?: string; | ||
Spinners provide their own recommended interval, so you don't really need to specify this. Default value: Provided by the spinner or `100`. | ||
Spinners provide their own recommended interval, so you don't really need to specify this. | ||
Default: Provided by the spinner or `100`. | ||
*/ | ||
@@ -94,2 +96,9 @@ readonly interval?: number; | ||
readonly isEnabled?: boolean; | ||
/** | ||
Discard stdin input (except Ctrl+C) while running if it's TTY. This prevents the spinner from twitching on input, outputting broken lines on `Enter` key presses, and prevents buffering of input while the spinner is running. | ||
@default true | ||
*/ | ||
readonly discardStdin?: boolean; | ||
} | ||
@@ -106,3 +115,5 @@ | ||
/** | ||
Text to be persisted after the symbol. Default: Current `text`. | ||
Text to be persisted after the symbol. | ||
Default: Current `text`. | ||
*/ | ||
@@ -112,3 +123,5 @@ readonly text?: string; | ||
/** | ||
Text to be persisted before the symbol. Default: Current `prefixText`. | ||
Text to be persisted before the symbol. No prefix text will be displayed if set to an empty string. | ||
Default: Current `prefixText`. | ||
*/ | ||
@@ -130,3 +143,3 @@ readonly prefixText?: string; | ||
/** | ||
Change the text before the spinner. | ||
Change the text before the spinner. No prefix text will be displayed if set to an empty string. | ||
*/ | ||
@@ -221,5 +234,5 @@ prefixText: string; | ||
@returns The spinner instance. | ||
@returns The spinner instance text. | ||
*/ | ||
frame(): Ora; | ||
frame(): string; | ||
} | ||
@@ -259,7 +272,4 @@ } | ||
): ora.Ora; | ||
// TODO: Remove this for the next major release | ||
default: typeof ora; | ||
}; | ||
export = ora; |
97
index.js
@@ -8,2 +8,3 @@ 'use strict'; | ||
const wcwidth = require('wcwidth'); | ||
const isInteractive = require('is-interactive'); | ||
@@ -13,2 +14,6 @@ const TEXT = Symbol('text'); | ||
const noop = () => {}; | ||
const ASCII_ETX_CODE = 0x03; // Ctrl+C emits this code | ||
class Ora { | ||
@@ -22,7 +27,9 @@ constructor(options) { | ||
this.options = Object.assign({ | ||
this.options = { | ||
text: '', | ||
color: 'cyan', | ||
stream: process.stderr | ||
}, options); | ||
stream: process.stderr, | ||
discardStdin: true, | ||
...options | ||
}; | ||
@@ -35,4 +42,4 @@ this.spinner = this.options.spinner; | ||
this.stream = this.options.stream; | ||
this.id = null; | ||
this.isEnabled = typeof this.options.isEnabled === 'boolean' ? this.options.isEnabled : ((this.stream && this.stream.isTTY) && !process.env.CI); | ||
this.id = undefined; | ||
this.isEnabled = typeof this.options.isEnabled === 'boolean' ? this.options.isEnabled : isInteractive({stream: this.stream}); | ||
@@ -44,2 +51,3 @@ // Set *after* `this.stream` | ||
this.indent = this.options.indent; | ||
this.discardStdin = this.options.discardStdin; | ||
} | ||
@@ -71,2 +79,6 @@ | ||
if (spinner.interval !== undefined) { | ||
this.interval = spinner.interval; | ||
} | ||
this._spinner = spinner; | ||
@@ -94,3 +106,3 @@ } else if (process.platform === 'win32') { | ||
get isSpinning() { | ||
return this.id !== null; | ||
return this.id !== undefined; | ||
} | ||
@@ -125,3 +137,3 @@ | ||
this.frameIndex = ++this.frameIndex % frames.length; | ||
const fullPrefixText = typeof this.prefixText === 'string' ? this.prefixText + ' ' : ''; | ||
const fullPrefixText = (typeof this.prefixText === 'string' && this.prefixText !== '') ? this.prefixText + ' ' : ''; | ||
const fullText = typeof this.text === 'string' ? ' ' + this.text : ''; | ||
@@ -177,2 +189,6 @@ | ||
if (this.discardStdin && process.stdin.isTTY) { | ||
this.startDiscardingStdin(); | ||
} | ||
this.render(); | ||
@@ -190,3 +206,3 @@ this.id = setInterval(this.render.bind(this), this.interval); | ||
clearInterval(this.id); | ||
this.id = null; | ||
this.id = undefined; | ||
this.frameIndex = 0; | ||
@@ -198,5 +214,51 @@ this.clear(); | ||
if (this.discardStdin && process.stdin.isTTY) { | ||
this.stopDiscardingStdin(); | ||
} | ||
return this; | ||
} | ||
startDiscardingStdin() { | ||
const {stdin} = process; | ||
this._stdinOldRawMode = stdin.isRaw; | ||
this._stdinOldEmit = stdin.emit; | ||
this._stdinOldEmitOwnProperty = Object.prototype.hasOwnProperty.call(stdin, 'emit'); | ||
stdin.setRawMode(true); | ||
stdin.on('data', noop); | ||
const self = this; | ||
stdin.emit = function (event, data, ...args) { | ||
if (event === 'data' && data.includes(ASCII_ETX_CODE)) { | ||
process.emit('SIGINT'); | ||
} | ||
self._stdinOldEmit.apply(this, [event, data, ...args]); | ||
}; | ||
} | ||
stopDiscardingStdin() { | ||
if (this._stdinOldEmit !== undefined) { | ||
const {stdin} = process; | ||
stdin.setRawMode(this._stdinOldRawMode); | ||
stdin.removeListener('data', noop); | ||
if (stdin.listenerCount('data') === 0) { | ||
stdin.pause(); | ||
} | ||
if (this._stdinOldEmitOwnProperty) { | ||
stdin.emit = this._stdinOldEmit; | ||
} else { | ||
delete stdin.emit; | ||
} | ||
this._stdinOldRawMode = undefined; | ||
this._stdinOldEmit = undefined; | ||
this._stdinOldEmitOwnProperty = undefined; | ||
} | ||
} | ||
succeed(text) { | ||
@@ -220,3 +282,3 @@ return this.stopAndPersist({symbol: logSymbols.success, text}); | ||
const prefixText = options.prefixText || this.prefixText; | ||
const fullPrefixText = (typeof prefixText === 'string') ? prefixText + ' ' : ''; | ||
const fullPrefixText = (typeof prefixText === 'string' && prefixText !== '') ? prefixText + ' ' : ''; | ||
const text = options.text || this.text; | ||
@@ -232,11 +294,10 @@ const fullText = (typeof text === 'string') ? ' ' + text : ''; | ||
const oraFactory = function (opts) { | ||
return new Ora(opts); | ||
const oraFactory = function (options) { | ||
return new Ora(options); | ||
}; | ||
module.exports = oraFactory; | ||
// TODO: Remove this for the next major release | ||
module.exports.default = oraFactory; | ||
module.exports.promise = (action, options) => { | ||
// eslint-disable-next-line promise/prefer-await-to-then | ||
if (typeof action.then !== 'function') { | ||
@@ -249,12 +310,12 @@ throw new TypeError('Parameter `action` must be a Promise'); | ||
action.then( | ||
() => { | ||
(async () => { | ||
try { | ||
await action; | ||
spinner.succeed(); | ||
}, | ||
() => { | ||
} catch (_) { | ||
spinner.fail(); | ||
} | ||
); | ||
})(); | ||
return spinner; | ||
}; |
{ | ||
"name": "ora", | ||
"version": "3.4.0", | ||
"version": "4.0.0", | ||
"description": "Elegant terminal spinner", | ||
@@ -13,3 +13,3 @@ "license": "MIT", | ||
"engines": { | ||
"node": ">=6" | ||
"node": ">=8" | ||
}, | ||
@@ -41,5 +41,6 @@ "scripts": { | ||
"chalk": "^2.4.2", | ||
"cli-cursor": "^2.1.0", | ||
"cli-spinners": "^2.0.0", | ||
"log-symbols": "^2.2.0", | ||
"cli-cursor": "^3.1.0", | ||
"cli-spinners": "^2.2.0", | ||
"is-interactive": "^1.0.0", | ||
"log-symbols": "^3.0.0", | ||
"strip-ansi": "^5.2.0", | ||
@@ -49,8 +50,8 @@ "wcwidth": "^1.0.1" | ||
"devDependencies": { | ||
"@types/node": "^11.13.0", | ||
"ava": "^1.4.1", | ||
"get-stream": "^4.1.0", | ||
"tsd": "^0.7.2", | ||
"@types/node": "^12.7.5", | ||
"ava": "^2.4.0", | ||
"get-stream": "^5.1.0", | ||
"tsd": "^0.8.0", | ||
"xo": "^0.24.0" | ||
} | ||
} |
@@ -18,7 +18,3 @@ # ora [![Build Status](https://travis-ci.org/sindresorhus/ora.svg?branch=master)](https://travis-ci.org/sindresorhus/ora) | ||
<a href="https://www.patreon.com/sindresorhus"> | ||
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160"> | ||
</a> | ||
## Usage | ||
@@ -40,3 +36,4 @@ | ||
### ora([options|text]) | ||
### ora(text) | ||
### ora(options) | ||
@@ -47,3 +44,3 @@ If a string is provided, it is treated as a shortcut for [`options.text`](#text). | ||
Type: `Object` | ||
Type: `object` | ||
@@ -60,8 +57,8 @@ ##### text | ||
Text to display before the spinner. | ||
Text to display before the spinner. No prefix text will be displayed if set to an empty string. | ||
##### spinner | ||
Type: `string` `Object`<br> | ||
Default: `dots` <img src="screenshot-spinner.gif" width="14"> | ||
Type: `string | object`<br> | ||
Default: `'dots'` <img src="screenshot-spinner.gif" width="14"> | ||
@@ -82,4 +79,4 @@ Name of one of the [provided spinners](https://github.com/sindresorhus/cli-spinners/blob/master/spinners.json). See `example.js` in this repo if you want to test out different spinners. On Windows, it will always use the `line` spinner as the Windows command-line doesn't have proper Unicode support. | ||
Type: `string`<br> | ||
Default: `cyan`<br> | ||
Values: `black` `red` `green` `yellow` `blue` `magenta` `cyan` `white` `gray` | ||
Default: `'cyan'`<br> | ||
Values: `'black'` `'red'` `'green'` `'yellow'` `'blue'` `'magenta'` `'cyan'` `'white'` `'gray'` | ||
@@ -128,5 +125,12 @@ Color of the spinner. | ||
##### discardStdin | ||
Type: `boolean`<br> | ||
Default: `true` | ||
Discard stdin input (except Ctrl+C) while running if it's TTY. This prevents the spinner from twitching on input, outputting broken lines on <kbd>Enter</kbd> key presses, and prevents buffering of input while the spinner is running. | ||
### Instance | ||
#### .start([text]) | ||
#### .start(text?) | ||
@@ -139,15 +143,15 @@ Start the spinner. Returns the instance. Set the current text if `text` is provided. | ||
#### .succeed([text]) | ||
#### .succeed(text?) | ||
Stop the spinner, change it to a green `✔` and persist the current text, or `text` if provided. Returns the instance. See the GIF below. | ||
#### .fail([text]) | ||
#### .fail(text?) | ||
Stop the spinner, change it to a red `✖` and persist the current text, or `text` if provided. Returns the instance. See the GIF below. | ||
#### .warn([text]) | ||
#### .warn(text?) | ||
Stop the spinner, change it to a yellow `⚠` and persist the current text, or `text` if provided. Returns the instance. | ||
#### .info([text]) | ||
#### .info(text?) | ||
@@ -160,3 +164,3 @@ Stop the spinner, change it to a blue `ℹ` and persist the current text, or `text` if provided. Returns the instance. | ||
#### .stopAndPersist([options]) | ||
#### .stopAndPersist(options?) | ||
@@ -167,3 +171,3 @@ Stop the spinner and change the symbol or text. Returns the instance. See the GIF below. | ||
Type: `Object` | ||
Type: `object` | ||
@@ -180,3 +184,3 @@ ###### symbol | ||
Type: `string`<br> | ||
Default: Current `text` | ||
Default: Current `'text'` | ||
@@ -190,3 +194,3 @@ Text to be persisted after the symbol | ||
Text to be persisted before the symbol. | ||
Text to be persisted before the symbol. No prefix text will be displayed if set to an empty string. | ||
@@ -213,3 +217,3 @@ <img src="screenshot-2.gif" width="480"> | ||
Change the text before the spinner. | ||
Change the text before the spinner. No prefix text will be displayed if set to an empty string. | ||
@@ -228,3 +232,4 @@ #### .color | ||
### ora.promise(action, [options|text]) | ||
### ora.promise(action, text) | ||
### ora.promise(action, options) | ||
@@ -238,2 +243,20 @@ Starts a spinner for a promise. The spinner is stopped with `.succeed()` if the promise fulfills or with `.fail()` if it rejects. Returns the spinner instance. | ||
## FAQ | ||
### How do I change the color of the text? | ||
Use [Chalk](https://github.com/chalk/chalk): | ||
```js | ||
const ora = require('ora'); | ||
const chalk = require('chalk'); | ||
const spinner = ora(`Loading ${chalk.red('unicorns')}`).start(); | ||
``` | ||
### Why does the spinner freeze? | ||
JavaScript is single-threaded, so synchronous operations blocks the thread, including the spinner animation. Prefer asynchronous operations whenever possible. | ||
## Related | ||
@@ -249,6 +272,2 @@ | ||
- [tj/go-spin](https://github.com/tj/go-spin) - Terminal spinner package for Go | ||
## License | ||
MIT © [Sindre Sorhus](https://sindresorhus.com) | ||
- [observablehq.com/@victordidenko/ora](https://observablehq.com/@victordidenko/ora) - Ora port to Observable notebooks |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
20609
444
259
1
7
+ Addedis-interactive@^1.0.0
+ Addedcli-cursor@3.1.0(transitive)
+ Addedis-interactive@1.0.0(transitive)
+ Addedlog-symbols@3.0.0(transitive)
+ Addedmimic-fn@2.1.0(transitive)
+ Addedonetime@5.1.2(transitive)
+ Addedrestore-cursor@3.1.0(transitive)
- Removedcli-cursor@2.1.0(transitive)
- Removedlog-symbols@2.2.0(transitive)
- Removedmimic-fn@1.2.0(transitive)
- Removedonetime@2.0.1(transitive)
- Removedrestore-cursor@2.0.0(transitive)
Updatedcli-cursor@^3.1.0
Updatedcli-spinners@^2.2.0
Updatedlog-symbols@^3.0.0