Socket
Socket
Sign inDemoInstall

enquirer

Package Overview
Dependencies
1
Maintainers
2
Versions
37
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.3.0 to 2.3.1

8

CHANGELOG.md

@@ -35,2 +35,10 @@ # Release history

## 2.3.1 - 2019-07-12
### Fixed
- Several examples were updated to align with latest code changes and to fix small bugs found in the implementation of the example.
- Some bugs found from updating examples were fixed.
- Updates to documentation to provide more information on how to use prompts and the options available.
## 2.1.0 - 2018-11-29

@@ -37,0 +45,0 @@

6

index.js

@@ -35,3 +35,3 @@ 'use strict';

* ```
* @name register
* @name register()
* @param {String} `type`

@@ -73,3 +73,3 @@ * @param {Function|Prompt} `fn` `Prompt` class, or a function that returns a `Prompt` class.

* ```
* @name prompt
* @name prompt()
* @param {Array|Object} `questions` Options objects for one or more prompts to run.

@@ -156,3 +156,3 @@ * @return {Promise} Promise that returns an "answers" object with the user's responses.

* ```
* @name use
* @name use()
* @param {Function} `plugin` Plugin function that takes an instance of Enquirer.

@@ -159,0 +159,0 @@ * @return {Object} Returns the Enquirer instance.

@@ -9,3 +9,95 @@ 'use strict';

const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
const keyName = {
/* xterm/gnome ESC O letter */
'OP': 'f1',
'OQ': 'f2',
'OR': 'f3',
'OS': 'f4',
/* xterm/rxvt ESC [ number ~ */
'[11~': 'f1',
'[12~': 'f2',
'[13~': 'f3',
'[14~': 'f4',
/* from Cygwin and used in libuv */
'[[A': 'f1',
'[[B': 'f2',
'[[C': 'f3',
'[[D': 'f4',
'[[E': 'f5',
/* common */
'[15~': 'f5',
'[17~': 'f6',
'[18~': 'f7',
'[19~': 'f8',
'[20~': 'f9',
'[21~': 'f10',
'[23~': 'f11',
'[24~': 'f12',
/* xterm ESC [ letter */
'[A': 'up',
'[B': 'down',
'[C': 'right',
'[D': 'left',
'[E': 'clear',
'[F': 'end',
'[H': 'home',
/* xterm/gnome ESC O letter */
'OA': 'up',
'OB': 'down',
'OC': 'right',
'OD': 'left',
'OE': 'clear',
'OF': 'end',
'OH': 'home',
/* xterm/rxvt ESC [ number ~ */
'[1~': 'home',
'[2~': 'insert',
'[3~': 'delete',
'[4~': 'end',
'[5~': 'pageup',
'[6~': 'pagedown',
/* putty */
'[[5~': 'pageup',
'[[6~': 'pagedown',
/* rxvt */
'[7~': 'home',
'[8~': 'end',
/* rxvt keys with modifiers */
'[a': 'up',
'[b': 'down',
'[c': 'right',
'[d': 'left',
'[e': 'clear',
'[2$': 'insert',
'[3$': 'delete',
'[5$': 'pageup',
'[6$': 'pagedown',
'[7$': 'home',
'[8$': 'end',
'Oa': 'up',
'Ob': 'down',
'Oc': 'right',
'Od': 'left',
'Oe': 'clear',
'[2^': 'insert',
'[3^': 'delete',
'[5^': 'pageup',
'[6^': 'pagedown',
'[7^': 'home',
'[8^': 'end',
/* misc. */
'[Z': 'tab',
}
function isShiftKey(code) {
return ['[a', '[b', '[c', '[d', '[e', '[2$', '[3$', '[5$', '[6$', '[7$', '[8$', '[Z'].includes(code)
}
function isCtrlKey(code) {
return [ 'Oa', 'Ob', 'Oc', 'Od', 'Oe', '[2^', '[3^', '[5^', '[6^', '[7^', '[8^'].includes(code)
}
const keypress = (s = '', event = {}) => {

@@ -97,91 +189,5 @@ let parts;

// Parse the key itself
switch (code) {
/* xterm/gnome ESC O letter */
case 'OP': key.name = 'f1'; break;
case 'OQ': key.name = 'f2'; break;
case 'OR': key.name = 'f3'; break;
case 'OS': key.name = 'f4'; break;
/* xterm/rxvt ESC [ number ~ */
case '[11~': key.name = 'f1'; break;
case '[12~': key.name = 'f2'; break;
case '[13~': key.name = 'f3'; break;
case '[14~': key.name = 'f4'; break;
/* from Cygwin and used in libuv */
case '[[A': key.name = 'f1'; break;
case '[[B': key.name = 'f2'; break;
case '[[C': key.name = 'f3'; break;
case '[[D': key.name = 'f4'; break;
case '[[E': key.name = 'f5'; break;
/* common */
case '[15~': key.name = 'f5'; break;
case '[17~': key.name = 'f6'; break;
case '[18~': key.name = 'f7'; break;
case '[19~': key.name = 'f8'; break;
case '[20~': key.name = 'f9'; break;
case '[21~': key.name = 'f10'; break;
case '[23~': key.name = 'f11'; break;
case '[24~': key.name = 'f12'; break;
/* xterm ESC [ letter */
case '[A': key.name = 'up'; break;
case '[B': key.name = 'down'; break;
case '[C': key.name = 'right'; break;
case '[D': key.name = 'left'; break;
case '[E': key.name = 'clear'; break;
case '[F': key.name = 'end'; break;
case '[H': key.name = 'home'; break;
/* xterm/gnome ESC O letter */
case 'OA': key.name = 'up'; break;
case 'OB': key.name = 'down'; break;
case 'OC': key.name = 'right'; break;
case 'OD': key.name = 'left'; break;
case 'OE': key.name = 'clear'; break;
case 'OF': key.name = 'end'; break;
case 'OH': key.name = 'home'; break;
/* xterm/rxvt ESC [ number ~ */
case '[1~': key.name = 'home'; break;
case '[2~': key.name = 'insert'; break;
case '[3~': key.name = 'delete'; break;
case '[4~': key.name = 'end'; break;
case '[5~': key.name = 'pageup'; break;
case '[6~': key.name = 'pagedown'; break;
/* putty */
case '[[5~': key.name = 'pageup'; break;
case '[[6~': key.name = 'pagedown'; break;
/* rxvt */
case '[7~': key.name = 'home'; break;
case '[8~': key.name = 'end'; break;
/* rxvt keys with modifiers */
case '[a': key.name = 'up'; key.shift = true; break;
case '[b': key.name = 'down'; key.shift = true; break;
case '[c': key.name = 'right'; key.shift = true; break;
case '[d': key.name = 'left'; key.shift = true; break;
case '[e': key.name = 'clear'; key.shift = true; break;
case '[2$': key.name = 'insert'; key.shift = true; break;
case '[3$': key.name = 'delete'; key.shift = true; break;
case '[5$': key.name = 'pageup'; key.shift = true; break;
case '[6$': key.name = 'pagedown'; key.shift = true; break;
case '[7$': key.name = 'home'; key.shift = true; break;
case '[8$': key.name = 'end'; key.shift = true; break;
case 'Oa': key.name = 'up'; key.ctrl = true; break;
case 'Ob': key.name = 'down'; key.ctrl = true; break;
case 'Oc': key.name = 'right'; key.ctrl = true; break;
case 'Od': key.name = 'left'; key.ctrl = true; break;
case 'Oe': key.name = 'clear'; key.ctrl = true; break;
case '[2^': key.name = 'insert'; key.ctrl = true; break;
case '[3^': key.name = 'delete'; key.ctrl = true; break;
case '[5^': key.name = 'pageup'; key.ctrl = true; break;
case '[6^': key.name = 'pagedown'; key.ctrl = true; break;
case '[7^': key.name = 'home'; key.ctrl = true; break;
case '[8^': key.name = 'end'; key.ctrl = true; break;
/* misc. */
case '[Z': key.name = 'tab'; key.shift = true; break;
default: {
key.name = 'undefined';
break;
}
}
key.name = keyName[code];
key.shift = isShiftKey(code) || key.shift;
key.ctrl = isCtrlKey(code) || key.ctrl;
}

@@ -188,0 +194,0 @@ return key;

@@ -36,2 +36,6 @@ 'use strict';

number(char) {
return this.focused.editable ? this.append(char) : super.number(char);
}
next() {

@@ -38,0 +42,0 @@ return this.focused.editable ? form.next.call(this) : super.next();

@@ -61,2 +61,9 @@ 'use strict';

set heading(custom) {
this._heading = custom;
},
get heading() {
return this._heading || this.muted.underline;
},
/**

@@ -63,0 +70,0 @@ * Statuses

@@ -508,3 +508,4 @@ 'use strict';

let fn = typeof value === 'function' ? value : isChoice;
let result = this.choices.filter(fn);
let choices = this.options.multiple ? this.state._choices : this.choices;
let result = choices.filter(fn);
if (prop) {

@@ -511,0 +512,0 @@ return result.map(ch => ch[prop]);

@@ -16,3 +16,3 @@ 'use strict';

this.initial = options.initial != null ? options.initial : '';
this.value = this.input = String(this.initial);
this.input = String(this.initial);
this.cursor = this.input.length;

@@ -77,3 +77,3 @@ this.cursorShow();

isValue(value) {
return /^[-+]?[0-9]+(\.[0-9]+)?$/.test(value);
return /^[-+]?[0-9]+((\.)|(\.[0-9]+))?$/.test(value);
}

@@ -80,0 +80,0 @@

{
"name": "enquirer",
"description": "Stylish, intuitive and user-friendly prompt system. Fast and lightweight enough for small projects, powerful and extensible enough for the most advanced use cases.",
"version": "2.3.0",
"version": "2.3.1",
"homepage": "https://github.com/enquirer/enquirer",

@@ -6,0 +6,0 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)",

@@ -48,3 +48,3 @@ <h1 align="center">Enquirer</h1>

* **Well tested** - All prompts are well-tested, and tests are easy to create without having to use brittle, hacky solutions to spy on prompts or "inject" values.
* **Examples** - There are numerous [examples](examples) and [examples](examples) available to help you get started.
* **Examples** - There are numerous [examples](examples) available to help you get started.

@@ -88,3 +88,8 @@ If you like Enquirer, please consider starring or tweeting about this project to show your support. Thanks!

```
Install with [yarn](https://yarnpkg.com/en/):
```sh
$ yarn add enquirer
```
<p align="center">

@@ -113,4 +118,3 @@ <img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/npm-install.gif" alt="Install Enquirer with NPM" width="750">

console.log(response);
//=> { username: 'jonschlinkert' }
console.log(response); // { username: 'jonschlinkert' }
```

@@ -138,26 +142,36 @@

console.log(response);
//=> { name: 'Edward Chan', username: 'edwardmchan' }
console.log(response); // { name: 'Edward Chan', username: 'edwardmchan' }
```
**Jump to**: [Getting Started](#-getting-started) · [Prompts](#-prompts) · [Options](#-options) · [Key Bindings](#-key-bindings)
### Different ways to run enquirer
<br>
#### 1. By importing the specific `built-in prompt`
## Todo
```js
const { Confirm } = require('enquirer');
We're currently working on documentation for the following items. Please star and watch the repository for updates!
const prompt = new Confirm({
name: 'question',
message: 'Did you like enquirer?'
});
* [ ] Customizing symbols
* [ ] Customizing styles (palette)
* [ ] Customizing rendered input
* [ ] Customizing returned values
* [ ] Customizing key bindings
* [ ] Question validation
* [ ] Choice validation
* [ ] Skipping questions
* [ ] Async choices
* [ ] Async timers: loaders, spinners and other animations
* [ ] Links to examples
prompt.run()
.then(answer => console.log('Answer:', answer));
```
#### 2. By passing the options to `prompt`
```js
const { prompt } = require('enquirer');
prompt({
type: 'confirm',
name: 'question',
message: 'Did you like enquirer?'
})
.then(answer => console.log('Answer:', answer));
```
**Jump to**: [Getting Started](#-getting-started) · [Prompts](#-prompts) · [Options](#-options) · [Key Bindings](#-key-bindings)
<br>

@@ -167,2 +181,4 @@

**Enquirer is a prompt runner**
Add Enquirer to your JavaScript project with following line of code.

@@ -174,6 +190,2 @@

### How does Enquirer work?
**Enquirer is a prompt runner**
The main export of this library is the `Enquirer` class, which has methods and features designed to simplify running prompts.

@@ -208,3 +220,3 @@

All of the individual [prompt classes](#built-in-prompts) in this library are exposed as static properties on Enquirer. This allows them to be used directly (without using `enquirer.prompt()`.
All of the individual [prompt classes](#built-in-prompts) in this library are exposed as static properties on Enquirer. This allows them to be used directly without using `enquirer.prompt()`.

@@ -243,3 +255,3 @@ Use this approach if you need to modify a prompt instance, or listen for events on the prompt.

### [register](index.js#L42)
### [register()](index.js#L42)

@@ -262,3 +274,3 @@ Register a custom prompt type.

### [prompt](index.js#L78)
### [prompt()](index.js#L78)

@@ -286,3 +298,3 @@ Prompt function that takes a "question" object or array of question objects, and returns an object with responses from the user.

### [use](index.js#L160)
### [use()](index.js#L160)

@@ -332,3 +344,3 @@ Use an enquirer plugin.

In this document you'll learn about Enquirer's prompts: what they look like, how they work, how to run them, available options, and how to customize the prompts or create your own prompt concept.
This section is about Enquirer's prompts: what they look like, how they work, how to run them, available options, and how to customize the prompts or create your own prompt concept.

@@ -339,4 +351,5 @@ **Getting started with Enquirer's prompts**

- [Prompt Options](#prompt-options)
- [Prompt Types](#prompt-types) - The base `Prompt` class used by other prompts
* [Built-in prompts](#built-in-prompts)
* [Prompt Types](#prompt-types) - The base `Prompt` class used by other prompts
* [Custom prompts](#%E2%9D%AF-custom-prompts) - Enquirer 2.0 introduced the concept of prompt "types", with the goal of making custom prompts easier than ever to create and use.

@@ -354,3 +367,3 @@ ### Prompt

### Prompt Options
#### Prompt Options

@@ -367,25 +380,22 @@ Each prompt takes an options object (aka "question" object), that implements the following interface:

// optional
skip: boolean | function | async function
initial: string | function | async function
skip: boolean | function | async function,
initial: string | function | async function,
format: function | async function,
result: function | async function,
validate: function | async function
validate: function | async function,
}
```
Each property of the options object is described below:
### General options
| **Property** | **Required?** | **Type** | **Description** |
| ------------ | ------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | yes | `string\|function` | Enquirer uses this value to determine the type of prompt to run, but it's optional when prompts are run directly. |
| `name` | yes | `string\|function` | Used as the key for the answer on the returned values (answers) object. |
| `message` | yes | `string\|function` | The message to display when the prompt is rendered in the terminal. |
| `skip` | no | `boolean\|function` | If `true` it will not ask that prompt. |
| `initial` | no | `string\|function` | The default value to return if the user does not supply a value. |
| `format` | no | `function` | Function to format user input in the terminal. |
| `result` | no | `function` | Function to format the final submitted value before it's returned. |
| `validate` | no | `function` | Function to validate the submitted value before it's returned. This function may return a boolean or a string. If a string is returned it will be used as the validation error message. |
All prompts take the following options.
| **Property** | **Required?** | **Type** | **Description** |
| --- | --- | --- | --- |
| `type` | Yes | `string\|function` | Enquirer uses this value to determine the type of prompt to run, but it's optional when prompts are run directly. |
| `name` | Yes | `string\|function` | Used as the key for the answer on the returned values (answers) object. |
| `message` | Yes | `string\|function` | The message to display when the prompt is rendered in the terminal. |
| `skip` | no | `boolean\|function` | If `true` it will not ask that prompt. |
| `initial` | no | `string\|function` | The default value to return if the user does not supply a value. |
| `format` | no | `function` | Function to format user input in the terminal. |
| `result` | no | `function` | Function to format the final submitted value before it's returned. |
| `validate` | no | `function` | Function to validate the submitted value before it's returned. This function may return a boolean or a string. If a string is returned it will be used as the validation error message. |
**Example usage**

@@ -411,18 +421,17 @@

* [AutoComplete](#autocomplete-prompt)
* [Confirm](#confirm-prompt)
* [Form](#form-prompt)
* [Input](#input-prompt)
* [Invisible](#invisible-prompt)
* [List](#list-prompt)
* [MultiSelect](#multiselect-prompt)
* [Number](#number-prompt)
* [Password](#password-prompt)
* [Scale](#scale-prompt)
* [Select](#select-prompt)
* [Snippet](#snippet-prompt)
* [Sort](#sort-prompt)
* [Survey](#survey-prompt)
* [Text](#input-prompt) (alias for the [Input prompt](#input-prompt))
* [Toggle](#toggle-prompt)
* [AutoComplete Prompt](#autocomplete-prompt)
* [Confirm Prompt](#confirm-prompt)
* [Form Prompt](#form-prompt)
* [Input Prompt](#input-prompt)
* [Invisible Prompt](#invisible-prompt)
* [List Prompt](#list-prompt)
* [MultiSelect Prompt](#multiselect-prompt)
* [Numeral Prompt](#numeral-prompt)
* [Password Prompt](#password-prompt)
* [Survey Prompt](#survey-prompt)
* [Scale Prompt](#scale-prompt)
* [Select Prompt](#select-prompt)
* [Sort Prompt](#sort-prompt)
* [Snippet Prompt](#snippet-prompt)
* [Toggle Prompt](#toggle-prompt)

@@ -437,28 +446,38 @@ ### AutoComplete Prompt

**Related prompts**
* [Select](#select-prompt)
* [MultiSelect](#multiselect-prompt)
* [Survey](#survey-prompt)
**Example Usage**
```js
const question = {
type: 'autocomplete',
name: 'country',
message: 'Where to?',
limit: 5,
suggest(input, choices) {
return choices.filter(choice => choice.message.startsWith(input));
},
const { AutoComplete } = require('enquirer');
const prompt = new AutoComplete({
name: 'flavor',
message: 'Pick your favorite flavor',
limit: 10,
choices: [
'Afghanistan',
'Albania',
'Algeria',
'Andorra',
'Angola',
...
'Almond',
'Apple',
'Banana',
'Blackberry',
'Blueberry',
'Cherry',
'Chocolate',
'Cinnamon',
'Coconut',
'Cranberry',
'Grape',
'Nougat',
'Orange',
'Pear',
'Pineapple',
'Raspberry',
'Strawberry',
'Vanilla',
'Watermelon',
'Wintergreen'
]
};
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```

@@ -468,12 +487,17 @@

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `highlight` | `function` | `dim` version of primary style | The color to use when "highlighting" characters in the list that match user input. |
| `multiple` | `boolean` | `false` | Allow multiple choices to be selected. |
| Option | Type | Default | Description |
| ----------- | ---------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `highlight` | `function` | `dim` version of primary style | The color to use when "highlighting" characters in the list that match user input. |
| `multiple` | `boolean` | `false` | Allow multiple choices to be selected. |
| `suggest` | `function` | Greedy match, returns true if choice message contains input string. | Function that filters choices. Takes user input and a choices array, and returns a list of matching choices. |
**Related prompts**
* [Select](#select-prompt)
* [MultiSelect](#multiselect-prompt)
* [Survey](#survey-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
<br>
<br>
***

@@ -488,2 +512,17 @@ ### Confirm Prompt

**Example Usage**
```js
const { Confirm } = require('enquirer');
const prompt = new Confirm({
name: 'question',
message: 'Want to answer?'
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**Related prompts**

@@ -497,4 +536,3 @@

<br>
<br>
***

@@ -509,2 +547,22 @@ ### Form Prompt

**Example Usage**
```js
const { Form } = require('enquirer');
const prompt = new Form({
name: 'user',
message: 'Please provide the following information:',
choices: [
{ name: 'firstname', message: 'First Name', initial: 'Jon' },
{ name: 'lastname', message: 'Last Name', initial: 'Schlinkert' },
{ name: 'username', message: 'GitHub username', initial: 'jonschlinkert' }
]
});
prompt.run()
.then(value => console.log('Answer:', value))
.catch(console.error);
```
**Related prompts**

@@ -517,4 +575,3 @@

<br>
<br>
***

@@ -529,10 +586,14 @@ ### Input Prompt

**Usage**
**Example Usage**
```js
const question = {
type: 'input',
name: 'username',
message: 'What is your username?'
};
const { Input } = require('enquirer');
const prompt = new Input({
message: 'What is your username?',
initial: 'jonschlinkert'
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.log);
```

@@ -548,4 +609,3 @@

<br>
<br>
***

@@ -560,2 +620,16 @@ ### Invisible Prompt

**Example Usage**
```js
const { Invisible } = require('enquirer');
const prompt = new Invisible({
name: 'secret',
message: 'What is your secret?'
});
prompt.run()
.then(answer => console.log('Answer:', { secret: answer }))
.catch(console.error);
```
**Related prompts**

@@ -568,4 +642,3 @@

<br>
<br>
***

@@ -580,2 +653,16 @@ ### List Prompt

**Example Usage**
```js
const { List } = require('enquirer');
const prompt = new List({
name: 'keywords',
message: 'Type comma-separated keywords'
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**Related prompts**

@@ -588,4 +675,3 @@

<br>
<br>
***

@@ -600,2 +686,36 @@ ### MultiSelect Prompt

**Example Usage**
```js
const { MultiSelect } = require('enquirer');
const prompt = new MultiSelect({
name: 'value',
message: 'Pick your favorite colors',
limit: 7,
choices: [
{ name: 'aqua', value: '#00ffff' },
{ name: 'black', value: '#000000' },
{ name: 'blue', value: '#0000ff' },
{ name: 'fuchsia', value: '#ff00ff' },
{ name: 'gray', value: '#808080' },
{ name: 'green', value: '#008000' },
{ name: 'lime', value: '#00ff00' },
{ name: 'maroon', value: '#800000' },
{ name: 'navy', value: '#000080' },
{ name: 'olive', value: '#808000' },
{ name: 'purple', value: '#800080' },
{ name: 'red', value: '#ff0000' },
{ name: 'silver', value: '#c0c0c0' },
{ name: 'teal', value: '#008080' },
{ name: 'white', value: '#ffffff' },
{ name: 'yellow', value: '#ffff00' }
]
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**Related prompts**

@@ -609,4 +729,3 @@

<br>
<br>
***

@@ -621,2 +740,17 @@ ### Numeral Prompt

**Example Usage**
```js
const { NumberPrompt } = require('enquirer');
const prompt = new NumberPrompt({
name: 'number',
message: 'Please enter a number'
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**Related prompts**

@@ -629,4 +763,3 @@

<br>
<br>
***

@@ -641,2 +774,17 @@ ### Password Prompt

**Example Usage**
```js
const { Password } = require('enquirer');
const prompt = new Password({
name: 'password',
message: 'What is your password?'
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**Related prompts**

@@ -649,5 +797,65 @@

<br>
<br>
***
### Survey Prompt
Prompt that allows the user to provide feedback for a list of questions.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/survey-prompt.gif" alt="Enquirer Survey Prompt" width="750">
</p>
**Example Usage**
```js
const { Survey } = require('enquirer');
const prompt = new Survey({
name: 'experience',
message: 'Please rate your experience',
scale: [
{ name: '1', message: 'Strongly Disagree' },
{ name: '2', message: 'Disagree' },
{ name: '3', message: 'Neutral' },
{ name: '4', message: 'Agree' },
{ name: '5', message: 'Strongly Agree' }
],
margin: [0, 0, 2, 1],
choices: [
{
name: 'interface',
message: 'The website has a friendly interface.'
},
{
name: 'navigation',
message: 'The website is easy to navigate.'
},
{
name: 'images',
message: 'The website usually has good images.'
},
{
name: 'upload',
message: 'The website makes it easy to upload images.'
},
{
name: 'colors',
message: 'The website has a pleasing color palette.'
}
]
});
prompt.run()
.then(value => console.log('ANSWERS:', value))
.catch(console.error);
```
**Related prompts**
* [Scale](#scale-prompt)
* [Snippet](#snippet-prompt)
* [Select](#select-prompt)
***
### Scale Prompt

@@ -661,2 +869,51 @@

**Example Usage**
```js
const { Scale } = require('enquirer');
const prompt = new Scale({
name: 'experience',
message: 'Please rate your experience',
scale: [
{ name: '1', message: 'Strongly Disagree' },
{ name: '2', message: 'Disagree' },
{ name: '3', message: 'Neutral' },
{ name: '4', message: 'Agree' },
{ name: '5', message: 'Strongly Agree' }
],
margin: [0, 0, 2, 1],
choices: [
{
name: 'interface',
message: 'The website has a friendly interface.',
initial: 2
},
{
name: 'navigation',
message: 'The website is easy to navigate.',
initial: 2
},
{
name: 'images',
message: 'The website usually has good images.',
initial: 2
},
{
name: 'upload',
message: 'The website makes it easy to upload images.',
initial: 2
},
{
name: 'colors',
message: 'The website has a pleasing color palette.',
initial: 2
}
]
});
prompt.run()
.then(value => console.log('ANSWERS:', value))
.catch(console.error);
```
**Related prompts**

@@ -670,4 +927,3 @@

<br>
<br>
***

@@ -682,2 +938,18 @@ ### Select Prompt

**Example Usage**
```js
const { Select } = require('enquirer');
const prompt = new Select({
name: 'color',
message: 'Pick a flavor',
choices: ['apple', 'grape', 'watermelon', 'cherry', 'orange']
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**Related prompts**

@@ -690,4 +962,3 @@

<br>
<br>
***

@@ -706,2 +977,27 @@ ### Sort Prompt

**Example Usage**
```js
const colors = require('ansi-colors');
const { Sort } = require('enquirer');
const prompt = new Sort({
name: 'colors',
message: 'Sort the colors in order of preference',
hint: 'Top is best, bottom is worst',
numbered: true,
choices: ['red', 'white', 'green', 'cyan', 'yellow'].map(n => ({
name: n,
message: colors[n](n)
}))
});
prompt.run()
.then(function(answer = []) {
console.log(answer);
console.log('Your preferred order of colors is:');
console.log(answer.map(key => colors[key](key)).join('\n'));
})
.catch(console.error);
```
**Related prompts**

@@ -714,4 +1010,3 @@

<br>
<br>
***

@@ -726,2 +1021,43 @@ ### Snippet Prompt

**Example Usage**
```js
const semver = require('semver');
const { Snippet } = require('enquirer');
const prompt = new Snippet({
name: 'username',
message: 'Fill out the fields in package.json',
required: true,
fields: [
{
name: 'author_name',
message: 'Author Name'
},
{
name: 'version',
validate(value, state, item, index) {
if (item && item.name === 'version' && !semver.valid(value)) {
return prompt.styles.danger('version should be a valid semver value');
}
return true;
}
}
],
template: `{
"name": "\${name}",
"description": "\${description}",
"version": "\${version}",
"homepage": "https://github.com/\${username}/\${name}",
"author": "\${author_name} (https://github.com/\${username})",
"repository": "\${username}/\${name}",
"license": "\${license:ISC}"
}
`
});
prompt.run()
.then(answer => console.log('Answer:', answer.result))
.catch(console.error);
```
**Related prompts**

@@ -734,32 +1070,28 @@

<br>
<br>
***
### Survey Prompt
### Toggle Prompt
Prompt that allows the user to provide feedback for a list of questions.
Prompt that allows the user to toggle between two values then returns `true` or `false`.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/survey-prompt.gif" alt="Enquirer Survey Prompt" width="750">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/toggle-prompt.gif" alt="Enquirer Toggle Prompt" width="750">
</p>
**Related prompts**
**Example Usage**
* [Scale](#scale-prompt)
* [Snippet](#snippet-prompt)
* [Select](#select-prompt)
```js
const { Toggle } = require('enquirer');
<br>
<br>
const prompt = new Toggle({
message: 'Want to answer?',
enabled: 'Yep',
disabled: 'Nope'
});
### Toggle Prompt
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
Prompt that allows the user to toggle between two values then returns `true` or `false`.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/toggle-prompt.gif" alt="Enquirer Toggle Prompt" width="750">
</p>
As with the other prompts, all parts of this prompt are customizable.
**Related prompts**

@@ -773,10 +1105,16 @@

<br>
<br>
***
## ❯ Prompt Types
### Prompt Types
Enquirer 2.0 introduced the concept of prompt "types", with the goal of making custom prompts easier than ever to create and use. There are 4 (soon to be 5!) type classes:
There are 4 (soon to be 5!) type classes:
* [ArrayPrompt](#arrayprompt)
- [Options](#options)
- [Properties](#properties)
- [Methods](#methods)
- [Choices](#choices)
- [Defining choices](#defining-choices)
- [Choice properties](#choice-properties)
- [Related prompts](#related-prompts)
* [BooleanPrompt](#booleanprompt)

@@ -797,14 +1135,8 @@ * DatePrompt (Coming Soon!)

| **Option** | **Required?** | **Type** | **Description** |
| --- | --- | --- | --- |
| `type` | `Yes` | `string\|function` | Enquirer uses this value to determine the type of prompt to run, but it's optional when prompts are run directly. |
| `name` | `Yes` | `string\|function` | Used as the key for the answer on the returned values (answers) object. |
| `message` | `Yes` | `string\|function` | The message to display when the prompt is rendered in the terminal. |
| `autofocus` | `no` | `string\|number` | The index or name of the choice that should have focus when the prompt loads. Only one choice may have focus at a time. |
| `initial` | `no` | `string\|function` | The default value to return when the user does not supply a value. |
| `format` | `no` | `function` | Function to format user input in the terminal. |
| `result` | `no` | `function` | Function to format the final submitted value before it's returned. |
| `stdin` | `no` | `stream` | The input stream to use for emitting keypress events. Defaults to `process.stdin`. |
| `stdout` | `no` | `stream` | The output stream to use for writing the prompt to the terminal. Defaults to `process.stdout`. |
| `validate` | `no` | `function` | Function to validate the submitted value before it's returned. This function may return a boolean or a string. If a string is returned it will be used as the validation error message. |
| **Option** | **Required?** | **Type** | **Description** |
| ----------- | ------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `autofocus` | `no` | `string\|number` | The index or name of the choice that should have focus when the prompt loads. Only one choice may have focus at a time. | |
| `stdin` | `no` | `stream` | The input stream to use for emitting keypress events. Defaults to `process.stdin`. |
| `stdout` | `no` | `stream` | The output stream to use for writing the prompt to the terminal. Defaults to `process.stdout`. |
| |

@@ -815,21 +1147,21 @@ #### Properties

| **Property name** | **Type** | **Description** |
| --- | --- | --- |
| `choices` | `array` | Array of choices that have been normalized from choices passed on the prompt options. |
| `cursor` | `number` | Position of the cursor relative to the _user input (string)_. |
| `enabled` | `array` | Returns an array of enabled choices. |
| `focused` | `array` | Returns the currently selected choice in the visible list of choices. This is similar to the concept of focus in HTML and CSS. Focused choices are always visible (on-screen). When a list of choices is longer than the list of visible choices, and an off-screen choice is _focused_, the list will scroll to the focused choice and re-render. |
| `focused` | Gets the currently selected choice. Equivalent to `prompt.choices[prompt.index]`. |
| `index` | `number` | Position of the pointer in the _visible list (array) of choices_. |
| `limit` | `number` | The number of choices to display on-screen. |
| `selected` | `array` | Either a list of enabled choices (when `options.multiple` is true) or the currently focused choice. |
| `visible` | `string` | |
| **Property name** | **Type** | **Description** |
| ----------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `choices` | `array` | Array of choices that have been normalized from choices passed on the prompt options. |
| `cursor` | `number` | Position of the cursor relative to the _user input (string)_. |
| `enabled` | `array` | Returns an array of enabled choices. |
| `focused` | `array` | Returns the currently selected choice in the visible list of choices. This is similar to the concept of focus in HTML and CSS. Focused choices are always visible (on-screen). When a list of choices is longer than the list of visible choices, and an off-screen choice is _focused_, the list will scroll to the focused choice and re-render. |
| `focused` | Gets the currently selected choice. Equivalent to `prompt.choices[prompt.index]`. |
| `index` | `number` | Position of the pointer in the _visible list (array) of choices_. |
| `limit` | `number` | The number of choices to display on-screen. |
| `selected` | `array` | Either a list of enabled choices (when `options.multiple` is true) or the currently focused choice. |
| `visible` | `string` | |
#### Methods
| **Method** | **Description** |
| --- | --- |
| **Method** | **Description** |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pointer()` | Returns the visual symbol to use to identify the choice that currently has focus. The `❯` symbol is often used for this. The pointer is not always visible, as with the `autocomplete` prompt. |
| `indicator()` | Returns the visual symbol that indicates whether or not a choice is checked/enabled. |
| `focus()` | Sets focus on a choice, if it can be focused. |
| `indicator()` | Returns the visual symbol that indicates whether or not a choice is checked/enabled. |
| `focus()` | Sets focus on a choice, if it can be focused. |

@@ -905,13 +1237,13 @@ #### Choices

| **Option** | **Type** | **Description** |
| --- | --- | --- |
| `name` | `string` | The unique key to identify a choice |
| `message` | `string` | The message to display in the terminal. `name` is used when this is undefined. |
| `value` | `string` | Value to associate with the choice. Useful for creating key-value pairs from user choices. `name` is used when this is undefined. |
| `choices` | `array` | Array of "child" choices. |
| `hint` | `string` | Help message to display next to a choice. |
| `role` | `string` | Determines how the choice will be displayed. Currently the only role supported is `separator`. Additional roles may be added in the future (like `heading`, etc). Please create a [feature request] |
| `enabled` | `boolean` | Enabled a choice by default. This is only supported when `options.multiple` is true or on prompts that support multiple choices, like [MultiSelect](#-multiselect). |
| `disabled` | `boolean\|string` | Disable a choice so that it cannot be selected. This value may either be `true`, `false`, or a message to display. |
| `indicator` | `string\|function` | Custom indicator to render for a choice (like a check or radio button). |
| **Option** | **Type** | **Description** |
| ----------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | The unique key to identify a choice |
| `message` | `string` | The message to display in the terminal. `name` is used when this is undefined. |
| `value` | `string` | Value to associate with the choice. Useful for creating key-value pairs from user choices. `name` is used when this is undefined. |
| `choices` | `array` | Array of "child" choices. |
| `hint` | `string` | Help message to display next to a choice. |
| `role` | `string` | Determines how the choice will be displayed. Currently the only role supported is `separator`. Additional roles may be added in the future (like `heading`, etc). Please create a [feature request] |
| `enabled` | `boolean` | Enabled a choice by default. This is only supported when `options.multiple` is true or on prompts that support multiple choices, like [MultiSelect](#-multiselect). |
| `disabled` | `boolean\|string` | Disable a choice so that it cannot be selected. This value may either be `true`, `false`, or a message to display. |
| `indicator` | `string\|function` | Custom indicator to render for a choice (like a check or radio button). |

@@ -926,2 +1258,4 @@ #### Related prompts

***
### BooleanPrompt

@@ -933,2 +1267,4 @@

***
### NumberPrompt

@@ -940,2 +1276,4 @@

***
### StringPrompt

@@ -953,4 +1291,8 @@

Custom prompts are created by extending Enquirer's `Prompt` class, or one of the built-in [prompts](#-prompts) or low-level [types](#-types).
Custom prompts are created by extending either:
* Enquirer's `Prompt` class
* one of the built-in [prompts](#-prompts), or
* low-level [types](#-types).
<!-- Example: HaiKarate Custom Prompt -->

@@ -1031,6 +1373,6 @@

| **command** | **description** |
| --- | --- |
| <kbd>ctrl</kbd>+<kbd>c</kbd> | Cancel the prompt. |
| <kbd>ctrl</kbd>+<kbd>g</kdb> | Reset the prompt to its initial state. |
| **command** | **description** |
| -------------------------------- | -------------------------------------- |
| <kbd>ctrl</kbd> + <kbd>c</kbd> | Cancel the prompt. |
| <kbd>ctrl</kbd> + <kbd>g</kbd> | Reset the prompt to its initial state. |

@@ -1041,13 +1383,13 @@ <br>

These combinations may be used on prompts that support user input, such as the [input prompt](#input-prompt), [password prompt](#password-prompt), and [invisible prompt](#invisible-prompt)).
These combinations may be used on prompts that support user input (eg. [input prompt](#input-prompt), [password prompt](#password-prompt), and [invisible prompt](#invisible-prompt)).
| **command** | **description** |
| --- | --- |
| <kbd>left</kbd> | Move the cursor forward one character. |
| <kbd>right</kbd> | Move the cursor back one character. |
| <kbd>ctrl</kbd>+<kbd>a</kbd> | Move cursor to the start of the line |
| <kbd>ctrl</kbd>+<kbd>e</kbd> | Move cursor to the end of the line |
| <kbd>ctrl</kbd>+<kbd>b</kbd> | Move cursor back one character |
| <kbd>ctrl</kbd>+<kbd>f</kbd> | Move cursor forward one character |
| <kbd>ctrl</kbd>+<kbd>x</kbd> | Toggle between first and cursor position |
| **command** | **description** |
| ------------------------------ | ---------------------------------------- |
| <kbd>left</kbd> | Move the cursor back one character. |
| <kbd>right</kbd> | Move the cursor forward one character. |
| <kbd>ctrl</kbd> + <kbd>a</kbd> | Move cursor to the start of the line |
| <kbd>ctrl</kbd> + <kbd>e</kbd> | Move cursor to the end of the line |
| <kbd>ctrl</kbd> + <kbd>b</kbd> | Move cursor back one character |
| <kbd>ctrl</kbd> + <kbd>f</kbd> | Move cursor forward one character |
| <kbd>ctrl</kbd> + <kbd>x</kbd> | Toggle between first and cursor position |

@@ -1058,32 +1400,21 @@ <br>

These key combinations may be used on prompts that support user input, such as the [input prompt](#input-prompt), [password prompt](#password-prompt), and [invisible prompt](#invisible-prompt)).
These key combinations may be used on prompts that support user input (eg. [input prompt](#input-prompt), [password prompt](#password-prompt), and [invisible prompt](#invisible-prompt)).
| **command** | **description** |
| --- | --- |
| <kbd>ctrl</kbd>+<kbd>a</kbd> | Move cursor to the start of the line |
| <kbd>ctrl</kbd>+<kbd>e</kbd> | Move cursor to the end of the line |
| <kbd>ctrl</kbd>+<kbd>b</kbd> | Move cursor back one character |
| <kbd>ctrl</kbd>+<kbd>f</kbd> | Move cursor forward one character |
| <kbd>ctrl</kbd>+<kbd>x</kbd> | Toggle between first and cursor position |
| **command** | **description** |
| ------------------------------ | ---------------------------------------- |
| <kbd>ctrl</kbd> + <kbd>a</kbd> | Move cursor to the start of the line |
| <kbd>ctrl</kbd> + <kbd>e</kbd> | Move cursor to the end of the line |
| <kbd>ctrl</kbd> + <kbd>b</kbd> | Move cursor back one character |
| <kbd>ctrl</kbd> + <kbd>f</kbd> | Move cursor forward one character |
| <kbd>ctrl</kbd> + <kbd>x</kbd> | Toggle between first and cursor position |
#### Mac
<br>
| **command** | **description** |
| --- | --- |
| <kbd>delete</kbd> | Delete one character to the left. |
| <kbd>fn</kbd>+<kbd>delete</kbd> | Delete one character to the right. |
| <kbd>option</kbd>+<kbd>up</kbd> | Scroll to the previous item in history ([Input prompt](#input-prompt) only, when [history is enabled](examples/input/option-history.js)). |
| <kbd>option</kbd>+<kbd>down</kbd> | Scroll to the next item in history ([Input prompt](#input-prompt) only, when [history is enabled](examples/input/option-history.js)). |
| **command (Mac)** | **command (Windows)** | **description** |
| ----------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| <kbd>delete</kbd> | <kbd>backspace</kbd> | Delete one character to the left. |
| <kbd>fn</kbd> + <kbd>delete</kbd> | <kbd>delete</kbd> | Delete one character to the right. |
| <kbd>option</kbd> + <kbd>up</kbd> | <kbd>alt</kbd> + <kbd>up</kbd> | Scroll to the previous item in history ([Input prompt](#input-prompt) only, when [history is enabled](examples/input/option-history.js)). |
| <kbd>option</kbd> + <kbd>down</kbd> | <kbd>alt</kbd> + <kbd>down</kbd> | Scroll to the next item in history ([Input prompt](#input-prompt) only, when [history is enabled](examples/input/option-history.js)). |
#### Windows
| **command** | **description** |
| --- | --- |
| <kbd>backspace</kbd> | Delete one character to the left. |
| <kbd>delete</kbd> | Delete one character to the right (forward). |
| <kbd>alt</kbd>+<kbd>up</kbd> | Scroll to the previous item in history ([Input prompt](#input-prompt) only, when [history is enabled](examples/input/option-history.js)). |
| <kbd>alt</kbd>+<kbd>down</kbd> | Scroll to the next item in history ([Input prompt](#input-prompt) only, when [history is enabled](examples/input/option-history.js)). |
<br>
### Select choices

@@ -1093,9 +1424,9 @@

| **command** | **description** |
| --- | --- |
| <kbd>space</kbd> | Toggle the currently selected choice when `options.multiple` is true. |
| **command** | **description** |
| ----------------- | -------------------------------------------------------------------------------------------------------------------- |
| <kbd>space</kbd> | Toggle the currently selected choice when `options.multiple` is true. |
| <kbd>number</kbd> | Move the pointer to the choice at the given index. Also toggles the selected choice when `options.multiple` is true. |
| <kbd>a</kbd> | Toggle all choices to be enabled or disabled. |
| <kbd>i</kbd> | Invert the current selection of choices. |
| <kbd>g</kbd> | Toggle the current choice group. |
| <kbd>a</kbd> | Toggle all choices to be enabled or disabled. |
| <kbd>i</kbd> | Invert the current selection of choices. |
| <kbd>g</kbd> | Toggle the current choice group. |

@@ -1106,6 +1437,6 @@ <br>

| **command** | **description** |
| --- | --- |
| <kbd>fn</kbd>+<kbd>up</kbd> | Decrease the number of visible choices by one. |
| <kbd>fn</kbd>+<kbd>down</kbd> | Increase the number of visible choices by one. |
| **command** | **description** |
| ------------------------------- | ---------------------------------------------- |
| <kbd>fn</kbd> + <kbd>up</kbd> | Decrease the number of visible choices by one. |
| <kbd>fn</kbd> + <kbd>down</kbd> | Increase the number of visible choices by one. |

@@ -1116,26 +1447,19 @@ <br>

| **command** | **description** |
| --- | --- |
| <kbd>number</kbd> | Move the pointer to the choice at the given index. Also toggles the selected choice when `options.multiple` is true. |
| <kbd>up</kbd> | Move the pointer up. |
| <kbd>down</kbd> | Move the pointer down. |
| <kbd>ctrl</kbd>+<kbd>a</kbd> | Move the pointer to the first _visible_ choice. |
| <kbd>ctrl</kbd>+<kbd>e</kbd> | Move the pointer to the last _visible_ choice. |
| <kbd>shift</kbd>+<kbd>up</kbd> | Scroll up one choice without changing pointer position (locks the pointer while scrolling). |
| <kbd>shift</kbd>+<kbd>down</kbd> | Scroll down one choice without changing pointer position (locks the pointer while scrolling). |
| **command** | **description** |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| <kbd>number</kbd> | Move the pointer to the choice at the given index. Also toggles the selected choice when `options.multiple` is true. |
| <kbd>up</kbd> | Move the pointer up. |
| <kbd>down</kbd> | Move the pointer down. |
| <kbd>ctrl</kbd> + <kbd>a</kbd> | Move the pointer to the first _visible_ choice. |
| <kbd>ctrl</kbd> + <kbd>e</kbd> | Move the pointer to the last _visible_ choice. |
| <kbd>shift</kbd> + <kbd>up</kbd> | Scroll up one choice without changing pointer position (locks the pointer while scrolling). |
| <kbd>shift</kbd> + <kbd>down</kbd> | Scroll down one choice without changing pointer position (locks the pointer while scrolling). |
#### Mac
<br>
| **command** | **description** |
| --- | --- |
| <kbd>fn</kbd>+<kbd>left</kbd> | Move the pointer to the first choice in the choices array. |
| <kbd>fn</kbd>+<kbd>right</kbd> | Move the pointer to the last choice in the choices array. |
| **command (Mac)** | **command (Windows)** | **description** |
| -------------------------------- | --------------------- | ---------------------------------------------------------- |
| <kbd>fn</kbd> + <kbd>left</kbd> | <kbd>home</kbd> | Move the pointer to the first choice in the choices array. |
| <kbd>fn</kbd> + <kbd>right</kbd> | <kbd>end</kbd> | Move the pointer to the last choice in the choices array. |
#### Windows
| **command** | **description** |
| --- | --- |
| <kbd>home</kbd> | Move the pointer to the first choice in the choices array. |
| <kbd>end</kbd> | Move the pointer to the last choice in the choices array. |
<br>

@@ -1149,2 +1473,4 @@

### System specs
MacBook Pro, Intel Core i7, 2.5 GHz, 16 GB.

@@ -1170,2 +1496,17 @@

### Todo
We're currently working on documentation for the following items. Please star and watch the repository for updates!
* [ ] Customizing symbols
* [ ] Customizing styles (palette)
* [ ] Customizing rendered input
* [ ] Customizing returned values
* [ ] Customizing key bindings
* [ ] Question validation
* [ ] Choice validation
* [ ] Skipping questions
* [ ] Async choices
* [ ] Async timers: loaders, spinners and other animations
* [ ] Links to examples
</details>

@@ -1181,2 +1522,5 @@

```
```sh
$ yarn && yarn test
```

@@ -1198,13 +1542,15 @@ </details>

### Contributors
#### Contributors
| **Commits** | **Contributor** |
| --- | --- |
| 271 | [jonschlinkert](https://github.com/jonschlinkert) |
| 25 | [doowb](https://github.com/doowb) |
| 281 | [jonschlinkert](https://github.com/jonschlinkert) |
| 43 | [doowb](https://github.com/doowb) |
| 20 | [318097](https://github.com/318097) |
| 15 | [g-plane](https://github.com/g-plane) |
| 13 | [rajat-sr](https://github.com/rajat-sr) |
| 12 | [pixelass](https://github.com/pixelass) |
| 3 | [tunnckoCore](https://github.com/tunnckoCore) |
| 2 | [DanielRuf](https://github.com/DanielRuf) |
| 1 | [gabel0287](https://github.com/gabel0287) |
| 2 | [gabel0287](https://github.com/gabel0287) |
| 1 | [ImgBotApp](https://github.com/ImgBotApp) |

@@ -1220,3 +1566,3 @@ | 1 | [jsonkao](https://github.com/jsonkao) |

### Author
#### Author

@@ -1229,9 +1575,9 @@ **Jon Schlinkert**

### Credit
#### Credit
Thanks to [derhuerst](https://github.com/derhuerst), creator of prompt libraries such as [prompt-skeleton](https://github.com/derhuerst/prompt-skeleton), which influenced some of the concepts we used in our prompts.
### License
#### License
Copyright © 2018-present, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc