Commit 24e3ee4b authored by Rosanny Sihombing's avatar Rosanny Sihombing
Browse files

MLAB-677: Update modules

parent 60ea96ad
Showing with 0 additions and 5038 deletions
+0 -5038
/*
* @fileoverview Main Doctrine object
* @author Yusuke Suzuki <utatane.tea@gmail.com>
* @author Dan Tao <daniel.tao@gmail.com>
* @author Andrew Eisenberg <andrew@eisenberg.as>
*/
(function () {
'use strict';
var typed,
utility,
jsdoc,
esutils,
hasOwnProperty;
esutils = require('esutils');
typed = require('./typed');
utility = require('./utility');
function sliceSource(source, index, last) {
return source.slice(index, last);
}
hasOwnProperty = (function () {
var func = Object.prototype.hasOwnProperty;
return function hasOwnProperty(obj, name) {
return func.call(obj, name);
};
}());
function shallowCopy(obj) {
var ret = {}, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
ret[key] = obj[key];
}
}
return ret;
}
function isASCIIAlphanumeric(ch) {
return (ch >= 0x61 /* 'a' */ && ch <= 0x7A /* 'z' */) ||
(ch >= 0x41 /* 'A' */ && ch <= 0x5A /* 'Z' */) ||
(ch >= 0x30 /* '0' */ && ch <= 0x39 /* '9' */);
}
function isParamTitle(title) {
return title === 'param' || title === 'argument' || title === 'arg';
}
function isReturnTitle(title) {
return title === 'return' || title === 'returns';
}
function isProperty(title) {
return title === 'property' || title === 'prop';
}
function isNameParameterRequired(title) {
return isParamTitle(title) || isProperty(title) ||
title === 'alias' || title === 'this' || title === 'mixes' || title === 'requires';
}
function isAllowedName(title) {
return isNameParameterRequired(title) || title === 'const' || title === 'constant';
}
function isAllowedNested(title) {
return isProperty(title) || isParamTitle(title);
}
function isAllowedOptional(title) {
return isProperty(title) || isParamTitle(title);
}
function isTypeParameterRequired(title) {
return isParamTitle(title) || isReturnTitle(title) ||
title === 'define' || title === 'enum' ||
title === 'implements' || title === 'this' ||
title === 'type' || title === 'typedef' || isProperty(title);
}
// Consider deprecation instead using 'isTypeParameterRequired' and 'Rules' declaration to pick when a type is optional/required
// This would require changes to 'parseType'
function isAllowedType(title) {
return isTypeParameterRequired(title) || title === 'throws' || title === 'const' || title === 'constant' ||
title === 'namespace' || title === 'member' || title === 'var' || title === 'module' ||
title === 'constructor' || title === 'class' || title === 'extends' || title === 'augments' ||
title === 'public' || title === 'private' || title === 'protected';
}
// A regex character class that contains all whitespace except linebreak characters (\r, \n, \u2028, \u2029)
var WHITESPACE = '[ \\f\\t\\v\\u00a0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]';
var STAR_MATCHER = '(' + WHITESPACE + '*(?:\\*' + WHITESPACE + '?)?)(.+|[\r\n\u2028\u2029])';
function unwrapComment(doc) {
// JSDoc comment is following form
// /**
// * .......
// */
return doc.
// remove /**
replace(/^\/\*\*?/, '').
// remove */
replace(/\*\/$/, '').
// remove ' * ' at the beginning of a line
replace(new RegExp(STAR_MATCHER, 'g'), '$2').
// remove trailing whitespace
replace(/\s*$/, '');
}
/**
* Converts an index in an "unwrapped" JSDoc comment to the corresponding index in the original "wrapped" version
* @param {string} originalSource The original wrapped comment
* @param {number} unwrappedIndex The index of a character in the unwrapped string
* @returns {number} The index of the corresponding character in the original wrapped string
*/
function convertUnwrappedCommentIndex(originalSource, unwrappedIndex) {
var replacedSource = originalSource.replace(/^\/\*\*?/, '');
var numSkippedChars = 0;
var matcher = new RegExp(STAR_MATCHER, 'g');
var match;
while ((match = matcher.exec(replacedSource))) {
numSkippedChars += match[1].length;
if (match.index + match[0].length > unwrappedIndex + numSkippedChars) {
return unwrappedIndex + numSkippedChars + originalSource.length - replacedSource.length;
}
}
return originalSource.replace(/\*\/$/, '').replace(/\s*$/, '').length;
}
// JSDoc Tag Parser
(function (exports) {
var Rules,
index,
lineNumber,
length,
source,
originalSource,
recoverable,
sloppy,
strict;
function advance() {
var ch = source.charCodeAt(index);
index += 1;
if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D /* '\r' */ && source.charCodeAt(index) === 0x0A /* '\n' */)) {
lineNumber += 1;
}
return String.fromCharCode(ch);
}
function scanTitle() {
var title = '';
// waste '@'
advance();
while (index < length && isASCIIAlphanumeric(source.charCodeAt(index))) {
title += advance();
}
return title;
}
function seekContent() {
var ch, waiting, last = index;
waiting = false;
while (last < length) {
ch = source.charCodeAt(last);
if (esutils.code.isLineTerminator(ch) && !(ch === 0x0D /* '\r' */ && source.charCodeAt(last + 1) === 0x0A /* '\n' */)) {
waiting = true;
} else if (waiting) {
if (ch === 0x40 /* '@' */) {
break;
}
if (!esutils.code.isWhiteSpace(ch)) {
waiting = false;
}
}
last += 1;
}
return last;
}
// type expression may have nest brace, such as,
// { { ok: string } }
//
// therefore, scanning type expression with balancing braces.
function parseType(title, last, addRange) {
var ch, brace, type, startIndex, direct = false;
// search '{'
while (index < last) {
ch = source.charCodeAt(index);
if (esutils.code.isWhiteSpace(ch)) {
advance();
} else if (ch === 0x7B /* '{' */) {
advance();
break;
} else {
// this is direct pattern
direct = true;
break;
}
}
if (direct) {
return null;
}
// type expression { is found
brace = 1;
type = '';
while (index < last) {
ch = source.charCodeAt(index);
if (esutils.code.isLineTerminator(ch)) {
advance();
} else {
if (ch === 0x7D /* '}' */) {
brace -= 1;
if (brace === 0) {
advance();
break;
}
} else if (ch === 0x7B /* '{' */) {
brace += 1;
}
if (type === '') {
startIndex = index;
}
type += advance();
}
}
if (brace !== 0) {
// braces is not balanced
return utility.throwError('Braces are not balanced');
}
if (isAllowedOptional(title)) {
return typed.parseParamType(type, {startIndex: convertIndex(startIndex), range: addRange});
}
return typed.parseType(type, {startIndex: convertIndex(startIndex), range: addRange});
}
function scanIdentifier(last) {
var identifier;
if (!esutils.code.isIdentifierStartES5(source.charCodeAt(index)) && !source[index].match(/[0-9]/)) {
return null;
}
identifier = advance();
while (index < last && esutils.code.isIdentifierPartES5(source.charCodeAt(index))) {
identifier += advance();
}
return identifier;
}
function skipWhiteSpace(last) {
while (index < last && (esutils.code.isWhiteSpace(source.charCodeAt(index)) || esutils.code.isLineTerminator(source.charCodeAt(index)))) {
advance();
}
}
function parseName(last, allowBrackets, allowNestedParams) {
var name = '',
useBrackets,
insideString;
skipWhiteSpace(last);
if (index >= last) {
return null;
}
if (source.charCodeAt(index) === 0x5B /* '[' */) {
if (allowBrackets) {
useBrackets = true;
name = advance();
} else {
return null;
}
}
name += scanIdentifier(last);
if (allowNestedParams) {
if (source.charCodeAt(index) === 0x3A /* ':' */ && (
name === 'module' ||
name === 'external' ||
name === 'event')) {
name += advance();
name += scanIdentifier(last);
}
if(source.charCodeAt(index) === 0x5B /* '[' */ && source.charCodeAt(index + 1) === 0x5D /* ']' */){
name += advance();
name += advance();
}
while (source.charCodeAt(index) === 0x2E /* '.' */ ||
source.charCodeAt(index) === 0x2F /* '/' */ ||
source.charCodeAt(index) === 0x23 /* '#' */ ||
source.charCodeAt(index) === 0x2D /* '-' */ ||
source.charCodeAt(index) === 0x7E /* '~' */) {
name += advance();
name += scanIdentifier(last);
}
}
if (useBrackets) {
skipWhiteSpace(last);
// do we have a default value for this?
if (source.charCodeAt(index) === 0x3D /* '=' */) {
// consume the '='' symbol
name += advance();
skipWhiteSpace(last);
var ch;
var bracketDepth = 1;
// scan in the default value
while (index < last) {
ch = source.charCodeAt(index);
if (esutils.code.isWhiteSpace(ch)) {
if (!insideString) {
skipWhiteSpace(last);
ch = source.charCodeAt(index);
}
}
if (ch === 0x27 /* ''' */) {
if (!insideString) {
insideString = '\'';
} else {
if (insideString === '\'') {
insideString = '';
}
}
}
if (ch === 0x22 /* '"' */) {
if (!insideString) {
insideString = '"';
} else {
if (insideString === '"') {
insideString = '';
}
}
}
if (ch === 0x5B /* '[' */) {
bracketDepth++;
} else if (ch === 0x5D /* ']' */ &&
--bracketDepth === 0) {
break;
}
name += advance();
}
}
skipWhiteSpace(last);
if (index >= last || source.charCodeAt(index) !== 0x5D /* ']' */) {
// we never found a closing ']'
return null;
}
// collect the last ']'
name += advance();
}
return name;
}
function skipToTag() {
while (index < length && source.charCodeAt(index) !== 0x40 /* '@' */) {
advance();
}
if (index >= length) {
return false;
}
utility.assert(source.charCodeAt(index) === 0x40 /* '@' */);
return true;
}
function convertIndex(rangeIndex) {
if (source === originalSource) {
return rangeIndex;
}
return convertUnwrappedCommentIndex(originalSource, rangeIndex);
}
function TagParser(options, title) {
this._options = options;
this._title = title.toLowerCase();
this._tag = {
title: title,
description: null
};
if (this._options.lineNumbers) {
this._tag.lineNumber = lineNumber;
}
this._first = index - title.length - 1;
this._last = 0;
// space to save special information for title parsers.
this._extra = { };
}
// addError(err, ...)
TagParser.prototype.addError = function addError(errorText) {
var args = Array.prototype.slice.call(arguments, 1),
msg = errorText.replace(
/%(\d)/g,
function (whole, index) {
utility.assert(index < args.length, 'Message reference must be in range');
return args[index];
}
);
if (!this._tag.errors) {
this._tag.errors = [];
}
if (strict) {
utility.throwError(msg);
}
this._tag.errors.push(msg);
return recoverable;
};
TagParser.prototype.parseType = function () {
// type required titles
if (isTypeParameterRequired(this._title)) {
try {
this._tag.type = parseType(this._title, this._last, this._options.range);
if (!this._tag.type) {
if (!isParamTitle(this._title) && !isReturnTitle(this._title)) {
if (!this.addError('Missing or invalid tag type')) {
return false;
}
}
}
} catch (error) {
this._tag.type = null;
if (!this.addError(error.message)) {
return false;
}
}
} else if (isAllowedType(this._title)) {
// optional types
try {
this._tag.type = parseType(this._title, this._last, this._options.range);
} catch (e) {
//For optional types, lets drop the thrown error when we hit the end of the file
}
}
return true;
};
TagParser.prototype._parseNamePath = function (optional) {
var name;
name = parseName(this._last, sloppy && isAllowedOptional(this._title), true);
if (!name) {
if (!optional) {
if (!this.addError('Missing or invalid tag name')) {
return false;
}
}
}
this._tag.name = name;
return true;
};
TagParser.prototype.parseNamePath = function () {
return this._parseNamePath(false);
};
TagParser.prototype.parseNamePathOptional = function () {
return this._parseNamePath(true);
};
TagParser.prototype.parseName = function () {
var assign, name;
// param, property requires name
if (isAllowedName(this._title)) {
this._tag.name = parseName(this._last, sloppy && isAllowedOptional(this._title), isAllowedNested(this._title));
if (!this._tag.name) {
if (!isNameParameterRequired(this._title)) {
return true;
}
// it's possible the name has already been parsed but interpreted as a type
// it's also possible this is a sloppy declaration, in which case it will be
// fixed at the end
if (isParamTitle(this._title) && this._tag.type && this._tag.type.name) {
this._extra.name = this._tag.type;
this._tag.name = this._tag.type.name;
this._tag.type = null;
} else {
if (!this.addError('Missing or invalid tag name')) {
return false;
}
}
} else {
name = this._tag.name;
if (name.charAt(0) === '[' && name.charAt(name.length - 1) === ']') {
// extract the default value if there is one
// example: @param {string} [somebody=John Doe] description
assign = name.substring(1, name.length - 1).split('=');
if (assign.length > 1) {
this._tag['default'] = assign.slice(1).join('=');
}
this._tag.name = assign[0];
// convert to an optional type
if (this._tag.type && this._tag.type.type !== 'OptionalType') {
this._tag.type = {
type: 'OptionalType',
expression: this._tag.type
};
}
}
}
}
return true;
};
TagParser.prototype.parseDescription = function parseDescription() {
var description = sliceSource(source, index, this._last).trim();
if (description) {
if ((/^-\s+/).test(description)) {
description = description.substring(2);
}
this._tag.description = description;
}
return true;
};
TagParser.prototype.parseCaption = function parseDescription() {
var description = sliceSource(source, index, this._last).trim();
var captionStartTag = '<caption>';
var captionEndTag = '</caption>';
var captionStart = description.indexOf(captionStartTag);
var captionEnd = description.indexOf(captionEndTag);
if (captionStart >= 0 && captionEnd >= 0) {
this._tag.caption = description.substring(
captionStart + captionStartTag.length, captionEnd).trim();
this._tag.description = description.substring(captionEnd + captionEndTag.length).trim();
} else {
this._tag.description = description;
}
return true;
};
TagParser.prototype.parseKind = function parseKind() {
var kind, kinds;
kinds = {
'class': true,
'constant': true,
'event': true,
'external': true,
'file': true,
'function': true,
'member': true,
'mixin': true,
'module': true,
'namespace': true,
'typedef': true
};
kind = sliceSource(source, index, this._last).trim();
this._tag.kind = kind;
if (!hasOwnProperty(kinds, kind)) {
if (!this.addError('Invalid kind name \'%0\'', kind)) {
return false;
}
}
return true;
};
TagParser.prototype.parseAccess = function parseAccess() {
var access;
access = sliceSource(source, index, this._last).trim();
this._tag.access = access;
if (access !== 'private' && access !== 'protected' && access !== 'public') {
if (!this.addError('Invalid access name \'%0\'', access)) {
return false;
}
}
return true;
};
TagParser.prototype.parseThis = function parseThis() {
// this name may be a name expression (e.g. {foo.bar}),
// an union (e.g. {foo.bar|foo.baz}) or a name path (e.g. foo.bar)
var value = sliceSource(source, index, this._last).trim();
if (value && value.charAt(0) === '{') {
var gotType = this.parseType();
if (gotType && this._tag.type.type === 'NameExpression' || this._tag.type.type === 'UnionType') {
this._tag.name = this._tag.type.name;
return true;
} else {
return this.addError('Invalid name for this');
}
} else {
return this.parseNamePath();
}
};
TagParser.prototype.parseVariation = function parseVariation() {
var variation, text;
text = sliceSource(source, index, this._last).trim();
variation = parseFloat(text, 10);
this._tag.variation = variation;
if (isNaN(variation)) {
if (!this.addError('Invalid variation \'%0\'', text)) {
return false;
}
}
return true;
};
TagParser.prototype.ensureEnd = function () {
var shouldBeEmpty = sliceSource(source, index, this._last).trim();
if (shouldBeEmpty) {
if (!this.addError('Unknown content \'%0\'', shouldBeEmpty)) {
return false;
}
}
return true;
};
TagParser.prototype.epilogue = function epilogue() {
var description;
description = this._tag.description;
// un-fix potentially sloppy declaration
if (isAllowedOptional(this._title) && !this._tag.type && description && description.charAt(0) === '[') {
this._tag.type = this._extra.name;
if (!this._tag.name) {
this._tag.name = undefined;
}
if (!sloppy) {
if (!this.addError('Missing or invalid tag name')) {
return false;
}
}
}
return true;
};
Rules = {
// http://usejsdoc.org/tags-access.html
'access': ['parseAccess'],
// http://usejsdoc.org/tags-alias.html
'alias': ['parseNamePath', 'ensureEnd'],
// http://usejsdoc.org/tags-augments.html
'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// http://usejsdoc.org/tags-constructor.html
'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// Synonym: http://usejsdoc.org/tags-constructor.html
'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// Synonym: http://usejsdoc.org/tags-extends.html
'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// http://usejsdoc.org/tags-example.html
'example': ['parseCaption'],
// http://usejsdoc.org/tags-deprecated.html
'deprecated': ['parseDescription'],
// http://usejsdoc.org/tags-global.html
'global': ['ensureEnd'],
// http://usejsdoc.org/tags-inner.html
'inner': ['ensureEnd'],
// http://usejsdoc.org/tags-instance.html
'instance': ['ensureEnd'],
// http://usejsdoc.org/tags-kind.html
'kind': ['parseKind'],
// http://usejsdoc.org/tags-mixes.html
'mixes': ['parseNamePath', 'ensureEnd'],
// http://usejsdoc.org/tags-mixin.html
'mixin': ['parseNamePathOptional', 'ensureEnd'],
// http://usejsdoc.org/tags-member.html
'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// http://usejsdoc.org/tags-method.html
'method': ['parseNamePathOptional', 'ensureEnd'],
// http://usejsdoc.org/tags-module.html
'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// Synonym: http://usejsdoc.org/tags-method.html
'func': ['parseNamePathOptional', 'ensureEnd'],
// Synonym: http://usejsdoc.org/tags-method.html
'function': ['parseNamePathOptional', 'ensureEnd'],
// Synonym: http://usejsdoc.org/tags-member.html
'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// http://usejsdoc.org/tags-name.html
'name': ['parseNamePath', 'ensureEnd'],
// http://usejsdoc.org/tags-namespace.html
'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
// http://usejsdoc.org/tags-private.html
'private': ['parseType', 'parseDescription'],
// http://usejsdoc.org/tags-protected.html
'protected': ['parseType', 'parseDescription'],
// http://usejsdoc.org/tags-public.html
'public': ['parseType', 'parseDescription'],
// http://usejsdoc.org/tags-readonly.html
'readonly': ['ensureEnd'],
// http://usejsdoc.org/tags-requires.html
'requires': ['parseNamePath', 'ensureEnd'],
// http://usejsdoc.org/tags-since.html
'since': ['parseDescription'],
// http://usejsdoc.org/tags-static.html
'static': ['ensureEnd'],
// http://usejsdoc.org/tags-summary.html
'summary': ['parseDescription'],
// http://usejsdoc.org/tags-this.html
'this': ['parseThis', 'ensureEnd'],
// http://usejsdoc.org/tags-todo.html
'todo': ['parseDescription'],
// http://usejsdoc.org/tags-typedef.html
'typedef': ['parseType', 'parseNamePathOptional'],
// http://usejsdoc.org/tags-variation.html
'variation': ['parseVariation'],
// http://usejsdoc.org/tags-version.html
'version': ['parseDescription']
};
TagParser.prototype.parse = function parse() {
var i, iz, sequences, method;
// empty title
if (!this._title) {
if (!this.addError('Missing or invalid title')) {
return null;
}
}
// Seek to content last index.
this._last = seekContent(this._title);
if (this._options.range) {
this._tag.range = [this._first, source.slice(0, this._last).replace(/\s*$/, '').length].map(convertIndex);
}
if (hasOwnProperty(Rules, this._title)) {
sequences = Rules[this._title];
} else {
// default sequences
sequences = ['parseType', 'parseName', 'parseDescription', 'epilogue'];
}
for (i = 0, iz = sequences.length; i < iz; ++i) {
method = sequences[i];
if (!this[method]()) {
return null;
}
}
return this._tag;
};
function parseTag(options) {
var title, parser, tag;
// skip to tag
if (!skipToTag()) {
return null;
}
// scan title
title = scanTitle();
// construct tag parser
parser = new TagParser(options, title);
tag = parser.parse();
// Seek global index to end of this tag.
while (index < parser._last) {
advance();
}
return tag;
}
//
// Parse JSDoc
//
function scanJSDocDescription(preserveWhitespace) {
var description = '', ch, atAllowed;
atAllowed = true;
while (index < length) {
ch = source.charCodeAt(index);
if (atAllowed && ch === 0x40 /* '@' */) {
break;
}
if (esutils.code.isLineTerminator(ch)) {
atAllowed = true;
} else if (atAllowed && !esutils.code.isWhiteSpace(ch)) {
atAllowed = false;
}
description += advance();
}
return preserveWhitespace ? description : description.trim();
}
function parse(comment, options) {
var tags = [], tag, description, interestingTags, i, iz;
if (options === undefined) {
options = {};
}
if (typeof options.unwrap === 'boolean' && options.unwrap) {
source = unwrapComment(comment);
} else {
source = comment;
}
originalSource = comment;
// array of relevant tags
if (options.tags) {
if (Array.isArray(options.tags)) {
interestingTags = { };
for (i = 0, iz = options.tags.length; i < iz; i++) {
if (typeof options.tags[i] === 'string') {
interestingTags[options.tags[i]] = true;
} else {
utility.throwError('Invalid "tags" parameter: ' + options.tags);
}
}
} else {
utility.throwError('Invalid "tags" parameter: ' + options.tags);
}
}
length = source.length;
index = 0;
lineNumber = 0;
recoverable = options.recoverable;
sloppy = options.sloppy;
strict = options.strict;
description = scanJSDocDescription(options.preserveWhitespace);
while (true) {
tag = parseTag(options);
if (!tag) {
break;
}
if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) {
tags.push(tag);
}
}
return {
description: description,
tags: tags
};
}
exports.parse = parse;
}(jsdoc = {}));
exports.version = utility.VERSION;
exports.parse = jsdoc.parse;
exports.parseType = typed.parseType;
exports.parseParamType = typed.parseParamType;
exports.unwrapComment = unwrapComment;
exports.Syntax = shallowCopy(typed.Syntax);
exports.Error = utility.DoctrineError;
exports.type = {
Syntax: exports.Syntax,
parseType: typed.parseType,
parseParamType: typed.parseParamType,
stringify: typed.stringify
};
}());
/* vim: set sw=4 ts=4 et tw=80 : */
/*
* @fileoverview Type expression parser.
* @author Yusuke Suzuki <utatane.tea@gmail.com>
* @author Dan Tao <daniel.tao@gmail.com>
* @author Andrew Eisenberg <andrew@eisenberg.as>
*/
// "typed", the Type Expression Parser for doctrine.
(function () {
'use strict';
var Syntax,
Token,
source,
length,
index,
previous,
token,
value,
esutils,
utility,
rangeOffset,
addRange;
esutils = require('esutils');
utility = require('./utility');
Syntax = {
NullableLiteral: 'NullableLiteral',
AllLiteral: 'AllLiteral',
NullLiteral: 'NullLiteral',
UndefinedLiteral: 'UndefinedLiteral',
VoidLiteral: 'VoidLiteral',
UnionType: 'UnionType',
ArrayType: 'ArrayType',
RecordType: 'RecordType',
FieldType: 'FieldType',
FunctionType: 'FunctionType',
ParameterType: 'ParameterType',
RestType: 'RestType',
NonNullableType: 'NonNullableType',
OptionalType: 'OptionalType',
NullableType: 'NullableType',
NameExpression: 'NameExpression',
TypeApplication: 'TypeApplication',
StringLiteralType: 'StringLiteralType',
NumericLiteralType: 'NumericLiteralType',
BooleanLiteralType: 'BooleanLiteralType'
};
Token = {
ILLEGAL: 0, // ILLEGAL
DOT_LT: 1, // .<
REST: 2, // ...
LT: 3, // <
GT: 4, // >
LPAREN: 5, // (
RPAREN: 6, // )
LBRACE: 7, // {
RBRACE: 8, // }
LBRACK: 9, // [
RBRACK: 10, // ]
COMMA: 11, // ,
COLON: 12, // :
STAR: 13, // *
PIPE: 14, // |
QUESTION: 15, // ?
BANG: 16, // !
EQUAL: 17, // =
NAME: 18, // name token
STRING: 19, // string
NUMBER: 20, // number
EOF: 21
};
function isTypeName(ch) {
return '><(){}[],:*|?!='.indexOf(String.fromCharCode(ch)) === -1 && !esutils.code.isWhiteSpace(ch) && !esutils.code.isLineTerminator(ch);
}
function Context(previous, index, token, value) {
this._previous = previous;
this._index = index;
this._token = token;
this._value = value;
}
Context.prototype.restore = function () {
previous = this._previous;
index = this._index;
token = this._token;
value = this._value;
};
Context.save = function () {
return new Context(previous, index, token, value);
};
function maybeAddRange(node, range) {
if (addRange) {
node.range = [range[0] + rangeOffset, range[1] + rangeOffset];
}
return node;
}
function advance() {
var ch = source.charAt(index);
index += 1;
return ch;
}
function scanHexEscape(prefix) {
var i, len, ch, code = 0;
len = (prefix === 'u') ? 4 : 2;
for (i = 0; i < len; ++i) {
if (index < length && esutils.code.isHexDigit(source.charCodeAt(index))) {
ch = advance();
code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
} else {
return '';
}
}
return String.fromCharCode(code);
}
function scanString() {
var str = '', quote, ch, code, unescaped, restore; //TODO review removal octal = false
quote = source.charAt(index);
++index;
while (index < length) {
ch = advance();
if (ch === quote) {
quote = '';
break;
} else if (ch === '\\') {
ch = advance();
if (!esutils.code.isLineTerminator(ch.charCodeAt(0))) {
switch (ch) {
case 'n':
str += '\n';
break;
case 'r':
str += '\r';
break;
case 't':
str += '\t';
break;
case 'u':
case 'x':
restore = index;
unescaped = scanHexEscape(ch);
if (unescaped) {
str += unescaped;
} else {
index = restore;
str += ch;
}
break;
case 'b':
str += '\b';
break;
case 'f':
str += '\f';
break;
case 'v':
str += '\v';
break;
default:
if (esutils.code.isOctalDigit(ch.charCodeAt(0))) {
code = '01234567'.indexOf(ch);
// \0 is not octal escape sequence
// Deprecating unused code. TODO review removal
//if (code !== 0) {
// octal = true;
//}
if (index < length && esutils.code.isOctalDigit(source.charCodeAt(index))) {
//TODO Review Removal octal = true;
code = code * 8 + '01234567'.indexOf(advance());
// 3 digits are only allowed when string starts
// with 0, 1, 2, 3
if ('0123'.indexOf(ch) >= 0 &&
index < length &&
esutils.code.isOctalDigit(source.charCodeAt(index))) {
code = code * 8 + '01234567'.indexOf(advance());
}
}
str += String.fromCharCode(code);
} else {
str += ch;
}
break;
}
} else {
if (ch === '\r' && source.charCodeAt(index) === 0x0A /* '\n' */) {
++index;
}
}
} else if (esutils.code.isLineTerminator(ch.charCodeAt(0))) {
break;
} else {
str += ch;
}
}
if (quote !== '') {
utility.throwError('unexpected quote');
}
value = str;
return Token.STRING;
}
function scanNumber() {
var number, ch;
number = '';
ch = source.charCodeAt(index);
if (ch !== 0x2E /* '.' */) {
number = advance();
ch = source.charCodeAt(index);
if (number === '0') {
if (ch === 0x78 /* 'x' */ || ch === 0x58 /* 'X' */) {
number += advance();
while (index < length) {
ch = source.charCodeAt(index);
if (!esutils.code.isHexDigit(ch)) {
break;
}
number += advance();
}
if (number.length <= 2) {
// only 0x
utility.throwError('unexpected token');
}
if (index < length) {
ch = source.charCodeAt(index);
if (esutils.code.isIdentifierStartES5(ch)) {
utility.throwError('unexpected token');
}
}
value = parseInt(number, 16);
return Token.NUMBER;
}
if (esutils.code.isOctalDigit(ch)) {
number += advance();
while (index < length) {
ch = source.charCodeAt(index);
if (!esutils.code.isOctalDigit(ch)) {
break;
}
number += advance();
}
if (index < length) {
ch = source.charCodeAt(index);
if (esutils.code.isIdentifierStartES5(ch) || esutils.code.isDecimalDigit(ch)) {
utility.throwError('unexpected token');
}
}
value = parseInt(number, 8);
return Token.NUMBER;
}
if (esutils.code.isDecimalDigit(ch)) {
utility.throwError('unexpected token');
}
}
while (index < length) {
ch = source.charCodeAt(index);
if (!esutils.code.isDecimalDigit(ch)) {
break;
}
number += advance();
}
}
if (ch === 0x2E /* '.' */) {
number += advance();
while (index < length) {
ch = source.charCodeAt(index);
if (!esutils.code.isDecimalDigit(ch)) {
break;
}
number += advance();
}
}
if (ch === 0x65 /* 'e' */ || ch === 0x45 /* 'E' */) {
number += advance();
ch = source.charCodeAt(index);
if (ch === 0x2B /* '+' */ || ch === 0x2D /* '-' */) {
number += advance();
}
ch = source.charCodeAt(index);
if (esutils.code.isDecimalDigit(ch)) {
number += advance();
while (index < length) {
ch = source.charCodeAt(index);
if (!esutils.code.isDecimalDigit(ch)) {
break;
}
number += advance();
}
} else {
utility.throwError('unexpected token');
}
}
if (index < length) {
ch = source.charCodeAt(index);
if (esutils.code.isIdentifierStartES5(ch)) {
utility.throwError('unexpected token');
}
}
value = parseFloat(number);
return Token.NUMBER;
}
function scanTypeName() {
var ch, ch2;
value = advance();
while (index < length && isTypeName(source.charCodeAt(index))) {
ch = source.charCodeAt(index);
if (ch === 0x2E /* '.' */) {
if ((index + 1) >= length) {
return Token.ILLEGAL;
}
ch2 = source.charCodeAt(index + 1);
if (ch2 === 0x3C /* '<' */) {
break;
}
}
value += advance();
}
return Token.NAME;
}
function next() {
var ch;
previous = index;
while (index < length && esutils.code.isWhiteSpace(source.charCodeAt(index))) {
advance();
}
if (index >= length) {
token = Token.EOF;
return token;
}
ch = source.charCodeAt(index);
switch (ch) {
case 0x27: /* ''' */
case 0x22: /* '"' */
token = scanString();
return token;
case 0x3A: /* ':' */
advance();
token = Token.COLON;
return token;
case 0x2C: /* ',' */
advance();
token = Token.COMMA;
return token;
case 0x28: /* '(' */
advance();
token = Token.LPAREN;
return token;
case 0x29: /* ')' */
advance();
token = Token.RPAREN;
return token;
case 0x5B: /* '[' */
advance();
token = Token.LBRACK;
return token;
case 0x5D: /* ']' */
advance();
token = Token.RBRACK;
return token;
case 0x7B: /* '{' */
advance();
token = Token.LBRACE;
return token;
case 0x7D: /* '}' */
advance();
token = Token.RBRACE;
return token;
case 0x2E: /* '.' */
if (index + 1 < length) {
ch = source.charCodeAt(index + 1);
if (ch === 0x3C /* '<' */) {
advance(); // '.'
advance(); // '<'
token = Token.DOT_LT;
return token;
}
if (ch === 0x2E /* '.' */ && index + 2 < length && source.charCodeAt(index + 2) === 0x2E /* '.' */) {
advance(); // '.'
advance(); // '.'
advance(); // '.'
token = Token.REST;
return token;
}
if (esutils.code.isDecimalDigit(ch)) {
token = scanNumber();
return token;
}
}
token = Token.ILLEGAL;
return token;
case 0x3C: /* '<' */
advance();
token = Token.LT;
return token;
case 0x3E: /* '>' */
advance();
token = Token.GT;
return token;
case 0x2A: /* '*' */
advance();
token = Token.STAR;
return token;
case 0x7C: /* '|' */
advance();
token = Token.PIPE;
return token;
case 0x3F: /* '?' */
advance();
token = Token.QUESTION;
return token;
case 0x21: /* '!' */
advance();
token = Token.BANG;
return token;
case 0x3D: /* '=' */
advance();
token = Token.EQUAL;
return token;
case 0x2D: /* '-' */
token = scanNumber();
return token;
default:
if (esutils.code.isDecimalDigit(ch)) {
token = scanNumber();
return token;
}
// type string permits following case,
//
// namespace.module.MyClass
//
// this reduced 1 token TK_NAME
utility.assert(isTypeName(ch));
token = scanTypeName();
return token;
}
}
function consume(target, text) {
utility.assert(token === target, text || 'consumed token not matched');
next();
}
function expect(target, message) {
if (token !== target) {
utility.throwError(message || 'unexpected token');
}
next();
}
// UnionType := '(' TypeUnionList ')'
//
// TypeUnionList :=
// <<empty>>
// | NonemptyTypeUnionList
//
// NonemptyTypeUnionList :=
// TypeExpression
// | TypeExpression '|' NonemptyTypeUnionList
function parseUnionType() {
var elements, startIndex = index - 1;
consume(Token.LPAREN, 'UnionType should start with (');
elements = [];
if (token !== Token.RPAREN) {
while (true) {
elements.push(parseTypeExpression());
if (token === Token.RPAREN) {
break;
}
expect(Token.PIPE);
}
}
consume(Token.RPAREN, 'UnionType should end with )');
return maybeAddRange({
type: Syntax.UnionType,
elements: elements
}, [startIndex, previous]);
}
// ArrayType := '[' ElementTypeList ']'
//
// ElementTypeList :=
// <<empty>>
// | TypeExpression
// | '...' TypeExpression
// | TypeExpression ',' ElementTypeList
function parseArrayType() {
var elements, startIndex = index - 1, restStartIndex;
consume(Token.LBRACK, 'ArrayType should start with [');
elements = [];
while (token !== Token.RBRACK) {
if (token === Token.REST) {
restStartIndex = index - 3;
consume(Token.REST);
elements.push(maybeAddRange({
type: Syntax.RestType,
expression: parseTypeExpression()
}, [restStartIndex, previous]));
break;
} else {
elements.push(parseTypeExpression());
}
if (token !== Token.RBRACK) {
expect(Token.COMMA);
}
}
expect(Token.RBRACK);
return maybeAddRange({
type: Syntax.ArrayType,
elements: elements
}, [startIndex, previous]);
}
function parseFieldName() {
var v = value;
if (token === Token.NAME || token === Token.STRING) {
next();
return v;
}
if (token === Token.NUMBER) {
consume(Token.NUMBER);
return String(v);
}
utility.throwError('unexpected token');
}
// FieldType :=
// FieldName
// | FieldName ':' TypeExpression
//
// FieldName :=
// NameExpression
// | StringLiteral
// | NumberLiteral
// | ReservedIdentifier
function parseFieldType() {
var key, rangeStart = previous;
key = parseFieldName();
if (token === Token.COLON) {
consume(Token.COLON);
return maybeAddRange({
type: Syntax.FieldType,
key: key,
value: parseTypeExpression()
}, [rangeStart, previous]);
}
return maybeAddRange({
type: Syntax.FieldType,
key: key,
value: null
}, [rangeStart, previous]);
}
// RecordType := '{' FieldTypeList '}'
//
// FieldTypeList :=
// <<empty>>
// | FieldType
// | FieldType ',' FieldTypeList
function parseRecordType() {
var fields, rangeStart = index - 1, rangeEnd;
consume(Token.LBRACE, 'RecordType should start with {');
fields = [];
if (token === Token.COMMA) {
consume(Token.COMMA);
} else {
while (token !== Token.RBRACE) {
fields.push(parseFieldType());
if (token !== Token.RBRACE) {
expect(Token.COMMA);
}
}
}
rangeEnd = index;
expect(Token.RBRACE);
return maybeAddRange({
type: Syntax.RecordType,
fields: fields
}, [rangeStart, rangeEnd]);
}
// NameExpression :=
// Identifier
// | TagIdentifier ':' Identifier
//
// Tag identifier is one of "module", "external" or "event"
// Identifier is the same as Token.NAME, including any dots, something like
// namespace.module.MyClass
function parseNameExpression() {
var name = value, rangeStart = index - name.length;
expect(Token.NAME);
if (token === Token.COLON && (
name === 'module' ||
name === 'external' ||
name === 'event')) {
consume(Token.COLON);
name += ':' + value;
expect(Token.NAME);
}
return maybeAddRange({
type: Syntax.NameExpression,
name: name
}, [rangeStart, previous]);
}
// TypeExpressionList :=
// TopLevelTypeExpression
// | TopLevelTypeExpression ',' TypeExpressionList
function parseTypeExpressionList() {
var elements = [];
elements.push(parseTop());
while (token === Token.COMMA) {
consume(Token.COMMA);
elements.push(parseTop());
}
return elements;
}
// TypeName :=
// NameExpression
// | NameExpression TypeApplication
//
// TypeApplication :=
// '.<' TypeExpressionList '>'
// | '<' TypeExpressionList '>' // this is extension of doctrine
function parseTypeName() {
var expr, applications, startIndex = index - value.length;
expr = parseNameExpression();
if (token === Token.DOT_LT || token === Token.LT) {
next();
applications = parseTypeExpressionList();
expect(Token.GT);
return maybeAddRange({
type: Syntax.TypeApplication,
expression: expr,
applications: applications
}, [startIndex, previous]);
}
return expr;
}
// ResultType :=
// <<empty>>
// | ':' void
// | ':' TypeExpression
//
// BNF is above
// but, we remove <<empty>> pattern, so token is always TypeToken::COLON
function parseResultType() {
consume(Token.COLON, 'ResultType should start with :');
if (token === Token.NAME && value === 'void') {
consume(Token.NAME);
return {
type: Syntax.VoidLiteral
};
}
return parseTypeExpression();
}
// ParametersType :=
// RestParameterType
// | NonRestParametersType
// | NonRestParametersType ',' RestParameterType
//
// RestParameterType :=
// '...'
// '...' Identifier
//
// NonRestParametersType :=
// ParameterType ',' NonRestParametersType
// | ParameterType
// | OptionalParametersType
//
// OptionalParametersType :=
// OptionalParameterType
// | OptionalParameterType, OptionalParametersType
//
// OptionalParameterType := ParameterType=
//
// ParameterType := TypeExpression | Identifier ':' TypeExpression
//
// Identifier is "new" or "this"
function parseParametersType() {
var params = [], optionalSequence = false, expr, rest = false, startIndex, restStartIndex = index - 3, nameStartIndex;
while (token !== Token.RPAREN) {
if (token === Token.REST) {
// RestParameterType
consume(Token.REST);
rest = true;
}
startIndex = previous;
expr = parseTypeExpression();
if (expr.type === Syntax.NameExpression && token === Token.COLON) {
nameStartIndex = previous - expr.name.length;
// Identifier ':' TypeExpression
consume(Token.COLON);
expr = maybeAddRange({
type: Syntax.ParameterType,
name: expr.name,
expression: parseTypeExpression()
}, [nameStartIndex, previous]);
}
if (token === Token.EQUAL) {
consume(Token.EQUAL);
expr = maybeAddRange({
type: Syntax.OptionalType,
expression: expr
}, [startIndex, previous]);
optionalSequence = true;
} else {
if (optionalSequence) {
utility.throwError('unexpected token');
}
}
if (rest) {
expr = maybeAddRange({
type: Syntax.RestType,
expression: expr
}, [restStartIndex, previous]);
}
params.push(expr);
if (token !== Token.RPAREN) {
expect(Token.COMMA);
}
}
return params;
}
// FunctionType := 'function' FunctionSignatureType
//
// FunctionSignatureType :=
// | TypeParameters '(' ')' ResultType
// | TypeParameters '(' ParametersType ')' ResultType
// | TypeParameters '(' 'this' ':' TypeName ')' ResultType
// | TypeParameters '(' 'this' ':' TypeName ',' ParametersType ')' ResultType
function parseFunctionType() {
var isNew, thisBinding, params, result, fnType, startIndex = index - value.length;
utility.assert(token === Token.NAME && value === 'function', 'FunctionType should start with \'function\'');
consume(Token.NAME);
// Google Closure Compiler is not implementing TypeParameters.
// So we do not. if we don't get '(', we see it as error.
expect(Token.LPAREN);
isNew = false;
params = [];
thisBinding = null;
if (token !== Token.RPAREN) {
// ParametersType or 'this'
if (token === Token.NAME &&
(value === 'this' || value === 'new')) {
// 'this' or 'new'
// 'new' is Closure Compiler extension
isNew = value === 'new';
consume(Token.NAME);
expect(Token.COLON);
thisBinding = parseTypeName();
if (token === Token.COMMA) {
consume(Token.COMMA);
params = parseParametersType();
}
} else {
params = parseParametersType();
}
}
expect(Token.RPAREN);
result = null;
if (token === Token.COLON) {
result = parseResultType();
}
fnType = maybeAddRange({
type: Syntax.FunctionType,
params: params,
result: result
}, [startIndex, previous]);
if (thisBinding) {
// avoid adding null 'new' and 'this' properties
fnType['this'] = thisBinding;
if (isNew) {
fnType['new'] = true;
}
}
return fnType;
}
// BasicTypeExpression :=
// '*'
// | 'null'
// | 'undefined'
// | TypeName
// | FunctionType
// | UnionType
// | RecordType
// | ArrayType
function parseBasicTypeExpression() {
var context, startIndex;
switch (token) {
case Token.STAR:
consume(Token.STAR);
return maybeAddRange({
type: Syntax.AllLiteral
}, [previous - 1, previous]);
case Token.LPAREN:
return parseUnionType();
case Token.LBRACK:
return parseArrayType();
case Token.LBRACE:
return parseRecordType();
case Token.NAME:
startIndex = index - value.length;
if (value === 'null') {
consume(Token.NAME);
return maybeAddRange({
type: Syntax.NullLiteral
}, [startIndex, previous]);
}
if (value === 'undefined') {
consume(Token.NAME);
return maybeAddRange({
type: Syntax.UndefinedLiteral
}, [startIndex, previous]);
}
if (value === 'true' || value === 'false') {
consume(Token.NAME);
return maybeAddRange({
type: Syntax.BooleanLiteralType,
value: value === 'true'
}, [startIndex, previous]);
}
context = Context.save();
if (value === 'function') {
try {
return parseFunctionType();
} catch (e) {
context.restore();
}
}
return parseTypeName();
case Token.STRING:
next();
return maybeAddRange({
type: Syntax.StringLiteralType,
value: value
}, [previous - value.length - 2, previous]);
case Token.NUMBER:
next();
return maybeAddRange({
type: Syntax.NumericLiteralType,
value: value
}, [previous - String(value).length, previous]);
default:
utility.throwError('unexpected token');
}
}
// TypeExpression :=
// BasicTypeExpression
// | '?' BasicTypeExpression
// | '!' BasicTypeExpression
// | BasicTypeExpression '?'
// | BasicTypeExpression '!'
// | '?'
// | BasicTypeExpression '[]'
function parseTypeExpression() {
var expr, rangeStart;
if (token === Token.QUESTION) {
rangeStart = index - 1;
consume(Token.QUESTION);
if (token === Token.COMMA || token === Token.EQUAL || token === Token.RBRACE ||
token === Token.RPAREN || token === Token.PIPE || token === Token.EOF ||
token === Token.RBRACK || token === Token.GT) {
return maybeAddRange({
type: Syntax.NullableLiteral
}, [rangeStart, previous]);
}
return maybeAddRange({
type: Syntax.NullableType,
expression: parseBasicTypeExpression(),
prefix: true
}, [rangeStart, previous]);
} else if (token === Token.BANG) {
rangeStart = index - 1;
consume(Token.BANG);
return maybeAddRange({
type: Syntax.NonNullableType,
expression: parseBasicTypeExpression(),
prefix: true
}, [rangeStart, previous]);
} else {
rangeStart = previous;
}
expr = parseBasicTypeExpression();
if (token === Token.BANG) {
consume(Token.BANG);
return maybeAddRange({
type: Syntax.NonNullableType,
expression: expr,
prefix: false
}, [rangeStart, previous]);
}
if (token === Token.QUESTION) {
consume(Token.QUESTION);
return maybeAddRange({
type: Syntax.NullableType,
expression: expr,
prefix: false
}, [rangeStart, previous]);
}
if (token === Token.LBRACK) {
consume(Token.LBRACK);
expect(Token.RBRACK, 'expected an array-style type declaration (' + value + '[])');
return maybeAddRange({
type: Syntax.TypeApplication,
expression: maybeAddRange({
type: Syntax.NameExpression,
name: 'Array'
}, [rangeStart, previous]),
applications: [expr]
}, [rangeStart, previous]);
}
return expr;
}
// TopLevelTypeExpression :=
// TypeExpression
// | TypeUnionList
//
// This rule is Google Closure Compiler extension, not ES4
// like,
// { number | string }
// If strict to ES4, we should write it as
// { (number|string) }
function parseTop() {
var expr, elements;
expr = parseTypeExpression();
if (token !== Token.PIPE) {
return expr;
}
elements = [expr];
consume(Token.PIPE);
while (true) {
elements.push(parseTypeExpression());
if (token !== Token.PIPE) {
break;
}
consume(Token.PIPE);
}
return maybeAddRange({
type: Syntax.UnionType,
elements: elements
}, [0, index]);
}
function parseTopParamType() {
var expr;
if (token === Token.REST) {
consume(Token.REST);
return maybeAddRange({
type: Syntax.RestType,
expression: parseTop()
}, [0, index]);
}
expr = parseTop();
if (token === Token.EQUAL) {
consume(Token.EQUAL);
return maybeAddRange({
type: Syntax.OptionalType,
expression: expr
}, [0, index]);
}
return expr;
}
function parseType(src, opt) {
var expr;
source = src;
length = source.length;
index = 0;
previous = 0;
addRange = opt && opt.range;
rangeOffset = opt && opt.startIndex || 0;
next();
expr = parseTop();
if (opt && opt.midstream) {
return {
expression: expr,
index: previous
};
}
if (token !== Token.EOF) {
utility.throwError('not reach to EOF');
}
return expr;
}
function parseParamType(src, opt) {
var expr;
source = src;
length = source.length;
index = 0;
previous = 0;
addRange = opt && opt.range;
rangeOffset = opt && opt.startIndex || 0;
next();
expr = parseTopParamType();
if (opt && opt.midstream) {
return {
expression: expr,
index: previous
};
}
if (token !== Token.EOF) {
utility.throwError('not reach to EOF');
}
return expr;
}
function stringifyImpl(node, compact, topLevel) {
var result, i, iz;
switch (node.type) {
case Syntax.NullableLiteral:
result = '?';
break;
case Syntax.AllLiteral:
result = '*';
break;
case Syntax.NullLiteral:
result = 'null';
break;
case Syntax.UndefinedLiteral:
result = 'undefined';
break;
case Syntax.VoidLiteral:
result = 'void';
break;
case Syntax.UnionType:
if (!topLevel) {
result = '(';
} else {
result = '';
}
for (i = 0, iz = node.elements.length; i < iz; ++i) {
result += stringifyImpl(node.elements[i], compact);
if ((i + 1) !== iz) {
result += compact ? '|' : ' | ';
}
}
if (!topLevel) {
result += ')';
}
break;
case Syntax.ArrayType:
result = '[';
for (i = 0, iz = node.elements.length; i < iz; ++i) {
result += stringifyImpl(node.elements[i], compact);
if ((i + 1) !== iz) {
result += compact ? ',' : ', ';
}
}
result += ']';
break;
case Syntax.RecordType:
result = '{';
for (i = 0, iz = node.fields.length; i < iz; ++i) {
result += stringifyImpl(node.fields[i], compact);
if ((i + 1) !== iz) {
result += compact ? ',' : ', ';
}
}
result += '}';
break;
case Syntax.FieldType:
if (node.value) {
result = node.key + (compact ? ':' : ': ') + stringifyImpl(node.value, compact);
} else {
result = node.key;
}
break;
case Syntax.FunctionType:
result = compact ? 'function(' : 'function (';
if (node['this']) {
if (node['new']) {
result += (compact ? 'new:' : 'new: ');
} else {
result += (compact ? 'this:' : 'this: ');
}
result += stringifyImpl(node['this'], compact);
if (node.params.length !== 0) {
result += compact ? ',' : ', ';
}
}
for (i = 0, iz = node.params.length; i < iz; ++i) {
result += stringifyImpl(node.params[i], compact);
if ((i + 1) !== iz) {
result += compact ? ',' : ', ';
}
}
result += ')';
if (node.result) {
result += (compact ? ':' : ': ') + stringifyImpl(node.result, compact);
}
break;
case Syntax.ParameterType:
result = node.name + (compact ? ':' : ': ') + stringifyImpl(node.expression, compact);
break;
case Syntax.RestType:
result = '...';
if (node.expression) {
result += stringifyImpl(node.expression, compact);
}
break;
case Syntax.NonNullableType:
if (node.prefix) {
result = '!' + stringifyImpl(node.expression, compact);
} else {
result = stringifyImpl(node.expression, compact) + '!';
}
break;
case Syntax.OptionalType:
result = stringifyImpl(node.expression, compact) + '=';
break;
case Syntax.NullableType:
if (node.prefix) {
result = '?' + stringifyImpl(node.expression, compact);
} else {
result = stringifyImpl(node.expression, compact) + '?';
}
break;
case Syntax.NameExpression:
result = node.name;
break;
case Syntax.TypeApplication:
result = stringifyImpl(node.expression, compact) + '.<';
for (i = 0, iz = node.applications.length; i < iz; ++i) {
result += stringifyImpl(node.applications[i], compact);
if ((i + 1) !== iz) {
result += compact ? ',' : ', ';
}
}
result += '>';
break;
case Syntax.StringLiteralType:
result = '"' + node.value + '"';
break;
case Syntax.NumericLiteralType:
result = String(node.value);
break;
case Syntax.BooleanLiteralType:
result = String(node.value);
break;
default:
utility.throwError('Unknown type ' + node.type);
}
return result;
}
function stringify(node, options) {
if (options == null) {
options = {};
}
return stringifyImpl(node, options.compact, options.topLevel);
}
exports.parseType = parseType;
exports.parseParamType = parseParamType;
exports.stringify = stringify;
exports.Syntax = Syntax;
}());
/* vim: set sw=4 ts=4 et tw=80 : */
/*
* @fileoverview Utilities for Doctrine
* @author Yusuke Suzuki <utatane.tea@gmail.com>
*/
(function () {
'use strict';
var VERSION;
VERSION = require('../package.json').version;
exports.VERSION = VERSION;
function DoctrineError(message) {
this.name = 'DoctrineError';
this.message = message;
}
DoctrineError.prototype = (function () {
var Middle = function () { };
Middle.prototype = Error.prototype;
return new Middle();
}());
DoctrineError.prototype.constructor = DoctrineError;
exports.DoctrineError = DoctrineError;
function throwError(message) {
throw new DoctrineError(message);
}
exports.throwError = throwError;
exports.assert = require('assert');
}());
/* vim: set sw=4 ts=4 et tw=80 : */
{
"name": "doctrine",
"description": "JSDoc parser",
"homepage": "https://github.com/eslint/doctrine",
"main": "lib/doctrine.js",
"version": "3.0.0",
"engines": {
"node": ">=6.0.0"
},
"directories": {
"lib": "./lib"
},
"files": [
"lib"
],
"maintainers": [
{
"name": "Nicholas C. Zakas",
"email": "nicholas+npm@nczconsulting.com",
"web": "https://www.nczonline.net"
},
{
"name": "Yusuke Suzuki",
"email": "utatane.tea@gmail.com",
"web": "https://github.com/Constellation"
}
],
"repository": "eslint/doctrine",
"devDependencies": {
"coveralls": "^3.0.1",
"dateformat": "^1.0.11",
"eslint": "^1.10.3",
"eslint-release": "^1.0.0",
"linefix": "^0.1.1",
"mocha": "^3.4.2",
"npm-license": "^0.3.1",
"nyc": "^10.3.2",
"semver": "^5.0.3",
"shelljs": "^0.5.3",
"shelljs-nodecli": "^0.1.1",
"should": "^5.0.1"
},
"license": "Apache-2.0",
"scripts": {
"pretest": "npm run lint",
"test": "nyc mocha",
"coveralls": "nyc report --reporter=text-lcov | coveralls",
"lint": "eslint lib/",
"generate-release": "eslint-generate-release",
"generate-alpharelease": "eslint-generate-prerelease alpha",
"generate-betarelease": "eslint-generate-prerelease beta",
"generate-rcrelease": "eslint-generate-prerelease rc",
"publish-release": "eslint-publish-release"
},
"dependencies": {
"esutils": "^2.0.2"
}
}
Copyright Mathias Bynens <https://mathiasbynens.be/>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# emoji-regex [![Build status](https://travis-ci.org/mathiasbynens/emoji-regex.svg?branch=master)](https://travis-ci.org/mathiasbynens/emoji-regex)
_emoji-regex_ offers a regular expression to match all emoji symbols (including textual representations of emoji) as per the Unicode Standard.
This repository contains a script that generates this regular expression based on [the data from Unicode v12](https://github.com/mathiasbynens/unicode-12.0.0). Because of this, the regular expression can easily be updated whenever new emoji are added to the Unicode standard.
## Installation
Via [npm](https://www.npmjs.com/):
```bash
npm install emoji-regex
```
In [Node.js](https://nodejs.org/):
```js
const emojiRegex = require('emoji-regex');
// Note: because the regular expression has the global flag set, this module
// exports a function that returns the regex rather than exporting the regular
// expression itself, to make it impossible to (accidentally) mutate the
// original regular expression.
const text = `
\u{231A}: ⌚ default emoji presentation character (Emoji_Presentation)
\u{2194}\u{FE0F}: ↔️ default text presentation character rendered as emoji
\u{1F469}: 👩 emoji modifier base (Emoji_Modifier_Base)
\u{1F469}\u{1F3FF}: 👩🏿 emoji modifier base followed by a modifier
`;
const regex = emojiRegex();
let match;
while (match = regex.exec(text)) {
const emoji = match[0];
console.log(`Matched sequence ${ emoji } — code points: ${ [...emoji].length }`);
}
```
Console output:
```
Matched sequence ⌚ — code points: 1
Matched sequence ⌚ — code points: 1
Matched sequence ↔️ — code points: 2
Matched sequence ↔️ — code points: 2
Matched sequence 👩 — code points: 1
Matched sequence 👩 — code points: 1
Matched sequence 👩🏿 — code points: 2
Matched sequence 👩🏿 — code points: 2
```
To match emoji in their textual representation as well (i.e. emoji that are not `Emoji_Presentation` symbols and that aren’t forced to render as emoji by a variation selector), `require` the other regex:
```js
const emojiRegex = require('emoji-regex/text.js');
```
Additionally, in environments which support ES2015 Unicode escapes, you may `require` ES2015-style versions of the regexes:
```js
const emojiRegex = require('emoji-regex/es2015/index.js');
const emojiRegexText = require('emoji-regex/es2015/text.js');
```
## Author
| [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") |
|---|
| [Mathias Bynens](https://mathiasbynens.be/) |
## License
_emoji-regex_ is available under the [MIT](https://mths.be/mit) license.
"use strict";
module.exports = () => {
// https://mths.be/emoji
return /\u{1F3F4}\u{E0067}\u{E0062}(?:\u{E0065}\u{E006E}\u{E0067}|\u{E0073}\u{E0063}\u{E0074}|\u{E0077}\u{E006C}\u{E0073})\u{E007F}|\u{1F468}(?:\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}\u{1F3FB}|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FE}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F468}|[\u{1F468}\u{1F469}]\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}]|[\u{1F468}\u{1F469}]\u200D[\u{1F466}\u{1F467}]|[\u2695\u2696\u2708]\uFE0F|[\u{1F466}\u{1F467}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|(?:\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708])\uFE0F|\u{1F3FB}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|[\u{1F3FB}-\u{1F3FF}])|(?:\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469})\u{1F3FB}|\u{1F9D1}(?:\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u200D\u{1F91D}\u200D\u{1F9D1})|(?:\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}-\u{1F3FE}]|(?:\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}\u{1F3FC}]|\u{1F469}(?:\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FD}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FB}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FC}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}\u{1F3FE}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D[\u{1F468}\u{1F469}]|[\u{1F468}\u{1F469}])|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F469}\u200D\u{1F469}\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|(?:\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}-\u{1F3FD}]|\u{1F469}\u200D\u{1F466}\u200D\u{1F466}|\u{1F469}\u200D\u{1F469}\u200D[\u{1F466}\u{1F467}]|(?:\u{1F441}\uFE0F\u200D\u{1F5E8}|\u{1F469}(?:\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708]|\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}]\uFE0F|[\u{1F46F}\u{1F93C}\u{1F9DE}\u{1F9DF}])\u200D[\u2640\u2642]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}](?:[\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\u{1F3F4}\u200D\u2620)\uFE0F|\u{1F469}\u200D\u{1F467}\u200D[\u{1F466}\u{1F467}]|\u{1F3F3}\uFE0F\u200D\u{1F308}|\u{1F415}\u200D\u{1F9BA}|\u{1F469}\u200D\u{1F466}|\u{1F469}\u200D\u{1F467}|\u{1F1FD}\u{1F1F0}|\u{1F1F4}\u{1F1F2}|\u{1F1F6}\u{1F1E6}|[#\*0-9]\uFE0F\u20E3|\u{1F1E7}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EF}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1F9}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1ED}\u{1F1EF}-\u{1F1F4}\u{1F1F7}\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FF}]|\u{1F1EA}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1ED}\u{1F1F7}-\u{1F1FA}]|\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F7}[\u{1F1EA}\u{1F1F4}\u{1F1F8}\u{1F1FA}\u{1F1FC}]|\u{1F469}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F2}[\u{1F1E6}\u{1F1E8}-\u{1F1ED}\u{1F1F0}-\u{1F1FF}]|\u{1F1E6}[\u{1F1E8}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F2}\u{1F1F4}\u{1F1F6}-\u{1F1FA}\u{1F1FC}\u{1F1FD}\u{1F1FF}]|\u{1F1F0}[\u{1F1EA}\u{1F1EC}-\u{1F1EE}\u{1F1F2}\u{1F1F3}\u{1F1F5}\u{1F1F7}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1ED}[\u{1F1F0}\u{1F1F2}\u{1F1F3}\u{1F1F7}\u{1F1F9}\u{1F1FA}]|\u{1F1E9}[\u{1F1EA}\u{1F1EC}\u{1F1EF}\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1FF}]|\u{1F1FE}[\u{1F1EA}\u{1F1F9}]|\u{1F1EC}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EE}\u{1F1F1}-\u{1F1F3}\u{1F1F5}-\u{1F1FA}\u{1F1FC}\u{1F1FE}]|\u{1F1F8}[\u{1F1E6}-\u{1F1EA}\u{1F1EC}-\u{1F1F4}\u{1F1F7}-\u{1F1F9}\u{1F1FB}\u{1F1FD}-\u{1F1FF}]|\u{1F1EB}[\u{1F1EE}-\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1F7}]|\u{1F1F5}[\u{1F1E6}\u{1F1EA}-\u{1F1ED}\u{1F1F0}-\u{1F1F3}\u{1F1F7}-\u{1F1F9}\u{1F1FC}\u{1F1FE}]|\u{1F1FB}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1EE}\u{1F1F3}\u{1F1FA}]|\u{1F1F3}[\u{1F1E6}\u{1F1E8}\u{1F1EA}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F4}\u{1F1F5}\u{1F1F7}\u{1F1FA}\u{1F1FF}]|\u{1F1E8}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1EE}\u{1F1F0}-\u{1F1F5}\u{1F1F7}\u{1F1FA}-\u{1F1FF}]|\u{1F1F1}[\u{1F1E6}-\u{1F1E8}\u{1F1EE}\u{1F1F0}\u{1F1F7}-\u{1F1FB}\u{1F1FE}]|\u{1F1FF}[\u{1F1E6}\u{1F1F2}\u{1F1FC}]|\u{1F1FC}[\u{1F1EB}\u{1F1F8}]|\u{1F1FA}[\u{1F1E6}\u{1F1EC}\u{1F1F2}\u{1F1F3}\u{1F1F8}\u{1F1FE}\u{1F1FF}]|\u{1F1EE}[\u{1F1E8}-\u{1F1EA}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}]|\u{1F1EF}[\u{1F1EA}\u{1F1F2}\u{1F1F4}\u{1F1F5}]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}][\u{1F3FB}-\u{1F3FF}]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]|[\u261D\u270A-\u270D\u{1F385}\u{1F3C2}\u{1F3C7}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}\u{1F467}\u{1F46B}-\u{1F46D}\u{1F470}\u{1F472}\u{1F474}-\u{1F476}\u{1F478}\u{1F47C}\u{1F483}\u{1F485}\u{1F4AA}\u{1F574}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F64C}\u{1F64F}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91C}\u{1F91E}\u{1F91F}\u{1F930}-\u{1F936}\u{1F9B5}\u{1F9B6}\u{1F9BB}\u{1F9D2}-\u{1F9D5}][\u{1F3FB}-\u{1F3FF}]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55\u{1F004}\u{1F0CF}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F236}\u{1F238}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F320}\u{1F32D}-\u{1F335}\u{1F337}-\u{1F37C}\u{1F37E}-\u{1F393}\u{1F3A0}-\u{1F3CA}\u{1F3CF}-\u{1F3D3}\u{1F3E0}-\u{1F3F0}\u{1F3F4}\u{1F3F8}-\u{1F43E}\u{1F440}\u{1F442}-\u{1F4FC}\u{1F4FF}-\u{1F53D}\u{1F54B}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F57A}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5FB}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CC}\u{1F6D0}-\u{1F6D2}\u{1F6D5}\u{1F6EB}\u{1F6EC}\u{1F6F4}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]|[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299\u{1F004}\u{1F0CF}\u{1F170}\u{1F171}\u{1F17E}\u{1F17F}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F202}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F321}\u{1F324}-\u{1F393}\u{1F396}\u{1F397}\u{1F399}-\u{1F39B}\u{1F39E}-\u{1F3F0}\u{1F3F3}-\u{1F3F5}\u{1F3F7}-\u{1F4FD}\u{1F4FF}-\u{1F53D}\u{1F549}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F56F}\u{1F570}\u{1F573}-\u{1F57A}\u{1F587}\u{1F58A}-\u{1F58D}\u{1F590}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5A5}\u{1F5A8}\u{1F5B1}\u{1F5B2}\u{1F5BC}\u{1F5C2}-\u{1F5C4}\u{1F5D1}-\u{1F5D3}\u{1F5DC}-\u{1F5DE}\u{1F5E1}\u{1F5E3}\u{1F5E8}\u{1F5EF}\u{1F5F3}\u{1F5FA}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CB}-\u{1F6D2}\u{1F6D5}\u{1F6E0}-\u{1F6E5}\u{1F6E9}\u{1F6EB}\u{1F6EC}\u{1F6F0}\u{1F6F3}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]\uFE0F|[\u261D\u26F9\u270A-\u270D\u{1F385}\u{1F3C2}-\u{1F3C4}\u{1F3C7}\u{1F3CA}-\u{1F3CC}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}-\u{1F478}\u{1F47C}\u{1F481}-\u{1F483}\u{1F485}-\u{1F487}\u{1F48F}\u{1F491}\u{1F4AA}\u{1F574}\u{1F575}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F645}-\u{1F647}\u{1F64B}-\u{1F64F}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91F}\u{1F926}\u{1F930}-\u{1F939}\u{1F93C}-\u{1F93E}\u{1F9B5}\u{1F9B6}\u{1F9B8}\u{1F9B9}\u{1F9BB}\u{1F9CD}-\u{1F9CF}\u{1F9D1}-\u{1F9DD}]/gu;
};
"use strict";
module.exports = () => {
// https://mths.be/emoji
return /\u{1F3F4}\u{E0067}\u{E0062}(?:\u{E0065}\u{E006E}\u{E0067}|\u{E0073}\u{E0063}\u{E0074}|\u{E0077}\u{E006C}\u{E0073})\u{E007F}|\u{1F468}(?:\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}\u{1F3FB}|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FE}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D)?\u{1F468}|[\u{1F468}\u{1F469}]\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}]|[\u{1F468}\u{1F469}]\u200D[\u{1F466}\u{1F467}]|[\u2695\u2696\u2708]\uFE0F|[\u{1F466}\u{1F467}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|(?:\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708])\uFE0F|\u{1F3FB}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}]|[\u{1F3FB}-\u{1F3FF}])|(?:\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F469})\u{1F3FB}|\u{1F9D1}(?:\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u200D\u{1F91D}\u200D\u{1F9D1})|(?:\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FF}\u200D\u{1F91D}\u200D[\u{1F468}\u{1F469}])[\u{1F3FB}-\u{1F3FE}]|(?:\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}\u{1F3FC}]|\u{1F469}(?:\u{1F3FE}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}-\u{1F3FD}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FC}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FD}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FB}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FC}-\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FD}\u200D(?:\u{1F91D}\u200D\u{1F468}[\u{1F3FB}\u{1F3FC}\u{1F3FE}\u{1F3FF}]|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u200D(?:\u2764\uFE0F\u200D(?:\u{1F48B}\u200D[\u{1F468}\u{1F469}]|[\u{1F468}\u{1F469}])|[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F3FF}\u200D[\u{1F33E}\u{1F373}\u{1F393}\u{1F3A4}\u{1F3A8}\u{1F3EB}\u{1F3ED}\u{1F4BB}\u{1F4BC}\u{1F527}\u{1F52C}\u{1F680}\u{1F692}\u{1F9AF}-\u{1F9B3}\u{1F9BC}\u{1F9BD}])|\u{1F469}\u200D\u{1F469}\u200D(?:\u{1F466}\u200D\u{1F466}|\u{1F467}\u200D[\u{1F466}\u{1F467}])|(?:\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}|\u{1F469}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F469})[\u{1F3FB}-\u{1F3FD}]|\u{1F469}\u200D\u{1F466}\u200D\u{1F466}|\u{1F469}\u200D\u{1F469}\u200D[\u{1F466}\u{1F467}]|(?:\u{1F441}\uFE0F\u200D\u{1F5E8}|\u{1F469}(?:\u{1F3FF}\u200D[\u2695\u2696\u2708]|\u{1F3FE}\u200D[\u2695\u2696\u2708]|\u{1F3FC}\u200D[\u2695\u2696\u2708]|\u{1F3FB}\u200D[\u2695\u2696\u2708]|\u{1F3FD}\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}]\uFE0F|[\u{1F46F}\u{1F93C}\u{1F9DE}\u{1F9DF}])\u200D[\u2640\u2642]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}](?:[\u{1F3FB}-\u{1F3FF}]\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\u{1F3F4}\u200D\u2620)\uFE0F|\u{1F469}\u200D\u{1F467}\u200D[\u{1F466}\u{1F467}]|\u{1F3F3}\uFE0F\u200D\u{1F308}|\u{1F415}\u200D\u{1F9BA}|\u{1F469}\u200D\u{1F466}|\u{1F469}\u200D\u{1F467}|\u{1F1FD}\u{1F1F0}|\u{1F1F4}\u{1F1F2}|\u{1F1F6}\u{1F1E6}|[#\*0-9]\uFE0F\u20E3|\u{1F1E7}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EF}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1F9}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1ED}\u{1F1EF}-\u{1F1F4}\u{1F1F7}\u{1F1F9}\u{1F1FB}\u{1F1FC}\u{1F1FF}]|\u{1F1EA}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1ED}\u{1F1F7}-\u{1F1FA}]|\u{1F9D1}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F7}[\u{1F1EA}\u{1F1F4}\u{1F1F8}\u{1F1FA}\u{1F1FC}]|\u{1F469}[\u{1F3FB}-\u{1F3FF}]|\u{1F1F2}[\u{1F1E6}\u{1F1E8}-\u{1F1ED}\u{1F1F0}-\u{1F1FF}]|\u{1F1E6}[\u{1F1E8}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F2}\u{1F1F4}\u{1F1F6}-\u{1F1FA}\u{1F1FC}\u{1F1FD}\u{1F1FF}]|\u{1F1F0}[\u{1F1EA}\u{1F1EC}-\u{1F1EE}\u{1F1F2}\u{1F1F3}\u{1F1F5}\u{1F1F7}\u{1F1FC}\u{1F1FE}\u{1F1FF}]|\u{1F1ED}[\u{1F1F0}\u{1F1F2}\u{1F1F3}\u{1F1F7}\u{1F1F9}\u{1F1FA}]|\u{1F1E9}[\u{1F1EA}\u{1F1EC}\u{1F1EF}\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1FF}]|\u{1F1FE}[\u{1F1EA}\u{1F1F9}]|\u{1F1EC}[\u{1F1E6}\u{1F1E7}\u{1F1E9}-\u{1F1EE}\u{1F1F1}-\u{1F1F3}\u{1F1F5}-\u{1F1FA}\u{1F1FC}\u{1F1FE}]|\u{1F1F8}[\u{1F1E6}-\u{1F1EA}\u{1F1EC}-\u{1F1F4}\u{1F1F7}-\u{1F1F9}\u{1F1FB}\u{1F1FD}-\u{1F1FF}]|\u{1F1EB}[\u{1F1EE}-\u{1F1F0}\u{1F1F2}\u{1F1F4}\u{1F1F7}]|\u{1F1F5}[\u{1F1E6}\u{1F1EA}-\u{1F1ED}\u{1F1F0}-\u{1F1F3}\u{1F1F7}-\u{1F1F9}\u{1F1FC}\u{1F1FE}]|\u{1F1FB}[\u{1F1E6}\u{1F1E8}\u{1F1EA}\u{1F1EC}\u{1F1EE}\u{1F1F3}\u{1F1FA}]|\u{1F1F3}[\u{1F1E6}\u{1F1E8}\u{1F1EA}-\u{1F1EC}\u{1F1EE}\u{1F1F1}\u{1F1F4}\u{1F1F5}\u{1F1F7}\u{1F1FA}\u{1F1FF}]|\u{1F1E8}[\u{1F1E6}\u{1F1E8}\u{1F1E9}\u{1F1EB}-\u{1F1EE}\u{1F1F0}-\u{1F1F5}\u{1F1F7}\u{1F1FA}-\u{1F1FF}]|\u{1F1F1}[\u{1F1E6}-\u{1F1E8}\u{1F1EE}\u{1F1F0}\u{1F1F7}-\u{1F1FB}\u{1F1FE}]|\u{1F1FF}[\u{1F1E6}\u{1F1F2}\u{1F1FC}]|\u{1F1FC}[\u{1F1EB}\u{1F1F8}]|\u{1F1FA}[\u{1F1E6}\u{1F1EC}\u{1F1F2}\u{1F1F3}\u{1F1F8}\u{1F1FE}\u{1F1FF}]|\u{1F1EE}[\u{1F1E8}-\u{1F1EA}\u{1F1F1}-\u{1F1F4}\u{1F1F6}-\u{1F1F9}]|\u{1F1EF}[\u{1F1EA}\u{1F1F2}\u{1F1F4}\u{1F1F5}]|[\u{1F3C3}\u{1F3C4}\u{1F3CA}\u{1F46E}\u{1F471}\u{1F473}\u{1F477}\u{1F481}\u{1F482}\u{1F486}\u{1F487}\u{1F645}-\u{1F647}\u{1F64B}\u{1F64D}\u{1F64E}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F926}\u{1F937}-\u{1F939}\u{1F93D}\u{1F93E}\u{1F9B8}\u{1F9B9}\u{1F9CD}-\u{1F9CF}\u{1F9D6}-\u{1F9DD}][\u{1F3FB}-\u{1F3FF}]|[\u26F9\u{1F3CB}\u{1F3CC}\u{1F575}][\u{1F3FB}-\u{1F3FF}]|[\u261D\u270A-\u270D\u{1F385}\u{1F3C2}\u{1F3C7}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}\u{1F467}\u{1F46B}-\u{1F46D}\u{1F470}\u{1F472}\u{1F474}-\u{1F476}\u{1F478}\u{1F47C}\u{1F483}\u{1F485}\u{1F4AA}\u{1F574}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F64C}\u{1F64F}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91C}\u{1F91E}\u{1F91F}\u{1F930}-\u{1F936}\u{1F9B5}\u{1F9B6}\u{1F9BB}\u{1F9D2}-\u{1F9D5}][\u{1F3FB}-\u{1F3FF}]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55\u{1F004}\u{1F0CF}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F236}\u{1F238}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F320}\u{1F32D}-\u{1F335}\u{1F337}-\u{1F37C}\u{1F37E}-\u{1F393}\u{1F3A0}-\u{1F3CA}\u{1F3CF}-\u{1F3D3}\u{1F3E0}-\u{1F3F0}\u{1F3F4}\u{1F3F8}-\u{1F43E}\u{1F440}\u{1F442}-\u{1F4FC}\u{1F4FF}-\u{1F53D}\u{1F54B}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F57A}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5FB}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CC}\u{1F6D0}-\u{1F6D2}\u{1F6D5}\u{1F6EB}\u{1F6EC}\u{1F6F4}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]|[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299\u{1F004}\u{1F0CF}\u{1F170}\u{1F171}\u{1F17E}\u{1F17F}\u{1F18E}\u{1F191}-\u{1F19A}\u{1F1E6}-\u{1F1FF}\u{1F201}\u{1F202}\u{1F21A}\u{1F22F}\u{1F232}-\u{1F23A}\u{1F250}\u{1F251}\u{1F300}-\u{1F321}\u{1F324}-\u{1F393}\u{1F396}\u{1F397}\u{1F399}-\u{1F39B}\u{1F39E}-\u{1F3F0}\u{1F3F3}-\u{1F3F5}\u{1F3F7}-\u{1F4FD}\u{1F4FF}-\u{1F53D}\u{1F549}-\u{1F54E}\u{1F550}-\u{1F567}\u{1F56F}\u{1F570}\u{1F573}-\u{1F57A}\u{1F587}\u{1F58A}-\u{1F58D}\u{1F590}\u{1F595}\u{1F596}\u{1F5A4}\u{1F5A5}\u{1F5A8}\u{1F5B1}\u{1F5B2}\u{1F5BC}\u{1F5C2}-\u{1F5C4}\u{1F5D1}-\u{1F5D3}\u{1F5DC}-\u{1F5DE}\u{1F5E1}\u{1F5E3}\u{1F5E8}\u{1F5EF}\u{1F5F3}\u{1F5FA}-\u{1F64F}\u{1F680}-\u{1F6C5}\u{1F6CB}-\u{1F6D2}\u{1F6D5}\u{1F6E0}-\u{1F6E5}\u{1F6E9}\u{1F6EB}\u{1F6EC}\u{1F6F0}\u{1F6F3}-\u{1F6FA}\u{1F7E0}-\u{1F7EB}\u{1F90D}-\u{1F93A}\u{1F93C}-\u{1F945}\u{1F947}-\u{1F971}\u{1F973}-\u{1F976}\u{1F97A}-\u{1F9A2}\u{1F9A5}-\u{1F9AA}\u{1F9AE}-\u{1F9CA}\u{1F9CD}-\u{1F9FF}\u{1FA70}-\u{1FA73}\u{1FA78}-\u{1FA7A}\u{1FA80}-\u{1FA82}\u{1FA90}-\u{1FA95}]\uFE0F?|[\u261D\u26F9\u270A-\u270D\u{1F385}\u{1F3C2}-\u{1F3C4}\u{1F3C7}\u{1F3CA}-\u{1F3CC}\u{1F442}\u{1F443}\u{1F446}-\u{1F450}\u{1F466}-\u{1F478}\u{1F47C}\u{1F481}-\u{1F483}\u{1F485}-\u{1F487}\u{1F48F}\u{1F491}\u{1F4AA}\u{1F574}\u{1F575}\u{1F57A}\u{1F590}\u{1F595}\u{1F596}\u{1F645}-\u{1F647}\u{1F64B}-\u{1F64F}\u{1F6A3}\u{1F6B4}-\u{1F6B6}\u{1F6C0}\u{1F6CC}\u{1F90F}\u{1F918}-\u{1F91F}\u{1F926}\u{1F930}-\u{1F939}\u{1F93C}-\u{1F93E}\u{1F9B5}\u{1F9B6}\u{1F9B8}\u{1F9B9}\u{1F9BB}\u{1F9CD}-\u{1F9CF}\u{1F9D1}-\u{1F9DD}]/gu;
};
declare module 'emoji-regex' {
function emojiRegex(): RegExp;
export default emojiRegex;
}
declare module 'emoji-regex/text' {
function emojiRegex(): RegExp;
export default emojiRegex;
}
declare module 'emoji-regex/es2015' {
function emojiRegex(): RegExp;
export default emojiRegex;
}
declare module 'emoji-regex/es2015/text' {
function emojiRegex(): RegExp;
export default emojiRegex;
}
"use strict";
module.exports = function () {
// https://mths.be/emoji
return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
};
{
"name": "emoji-regex",
"version": "8.0.0",
"description": "A regular expression to match all Emoji-only symbols as per the Unicode Standard.",
"homepage": "https://mths.be/emoji-regex",
"main": "index.js",
"types": "index.d.ts",
"keywords": [
"unicode",
"regex",
"regexp",
"regular expressions",
"code points",
"symbols",
"characters",
"emoji"
],
"license": "MIT",
"author": {
"name": "Mathias Bynens",
"url": "https://mathiasbynens.be/"
},
"repository": {
"type": "git",
"url": "https://github.com/mathiasbynens/emoji-regex.git"
},
"bugs": "https://github.com/mathiasbynens/emoji-regex/issues",
"files": [
"LICENSE-MIT.txt",
"index.js",
"index.d.ts",
"text.js",
"es2015/index.js",
"es2015/text.js"
],
"scripts": {
"build": "rm -rf -- es2015; babel src -d .; NODE_ENV=es2015 babel src -d ./es2015; node script/inject-sequences.js",
"test": "mocha",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/plugin-proposal-unicode-property-regex": "^7.2.0",
"@babel/preset-env": "^7.3.4",
"mocha": "^6.0.2",
"regexgen": "^1.3.0",
"unicode-12.0.0": "^0.7.9"
}
}
"use strict";
module.exports = function () {
// https://mths.be/emoji
return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F?|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
};
# Release history
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
<details>
<summary><strong>Guiding Principles</strong></summary>
- Changelogs are for humans, not machines.
- There should be an entry for every single version.
- The same types of changes should be grouped.
- Versions and sections should be linkable.
- The latest version comes first.
- The release date of each versions is displayed.
- Mention whether you follow Semantic Versioning.
</details>
<details>
<summary><strong>Types of changes</strong></summary>
Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_):
- `Added` for new features.
- `Changed` for changes in existing functionality.
- `Deprecated` for soon-to-be removed features.
- `Removed` for now removed features.
- `Fixed` for any bug fixes.
- `Security` in case of vulnerabilities.
</details>
## 2.3.6 - 2020-07-02
### Changed
- Upgraded [ansi-colors](https://github.com/doowb/ansi-colors) dependency to v4, thanks to [@trySound](https://github.com/TrySound), [#297](https://github.com/enquirer/enquirer/pull/297).
## 2.3.5 - 2020-04-07
### Fixed
- PR #259 fixed typing numbers in the autocomplete prompt, which fixes #112, #199, and #237
- PR #266 add the `template` property to the `SnippetPromptOptions` TypeScript interface
## 2.3.4 - 2020-01-13
### Added
- `MultiSelectPrompt` new example for `result` option.
### Fixed
- Updated typings to use `EventEmitter` class from `events` directly due to changes in `@types/node`.
## 2.3.3 - 2020-01-13
### Added
- `BooleanPrompt` new example for `header` option.
### Fixed
- using `await` in `keypress` and returning the `number` result in the `array` type fixes an issue with tests failing only on Travis
- `autocomplete` highlighting issue
- Typos in some documentation and example comments.
- Syntax errors in example code on the README.md.
## 2.3.2 - 2019-09-17
### Added
- `AuthPrompt` type for creating authentication based prompts.
- `BasicAuth` prompt as an example of creating an authentication prompt using basic username/password authentication
- Examples for different authentication prompts.
- `QuizPrompt`
### Fixed
- More examples were updated to fix any known bugs.
- Couple of fixes to the editable and autocomplete prompts.
- Documentation updates to highlight options available to some prompts.
## 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
### Fixed
- Several improvements were made for handling custom `format`, `result` and `initial` functions defined on the options.
## 2.0.7 - 2018-11-14
### Fixed
- `validate` function now properly accepts `false` as a return value, thanks to [@g-plane](https://github.com/g-plane).
### Added
- Adds support for <kbd>ctrl</kbd>+<kbd>n</kbd> to add choices
- Adds support for `options.required` on all prompts. Uses the built-in `validate()` function, allowing this functionality to be overridden or customized.
- Adds support for `options.scroll` to disable scrolling in array prompts.
- Adds support for `options.onRun`, which is called when `prompt.run()` is called, after the readline instance is created.
- Adds support for `options.history` on the `Input` and `Text` prompts.
- Adds support for `options.term` to set the terminal, thanks to [@tunnckoCore](https://github.com/tunnckoCore). At the moment this is only used in a couple of edge cases with the `Survey` and `Scale` prompts to check if the terminal is Hyper.
- `options.skip` may now be a Boolean, thanks to [@tunnckoCore](https://github.com/tunnckoCore)
## 2.0.0 - 2018-11-07
### Changed
Enquire 2.0 is a bottom-up complete re-write:
- Several prompts that were previously published as individual packages will be included in Enquirer itself.
- Why? - As users, we didn't like having to add commonly-used prompts as plugins. Enquirer 2.0 will still support custom prompts as plugins, but many prompts will also be built-in.
- Enquirer will only have a single dependency, https://github.com/doowb/ansi-colors, which itself has no other dependencies). This will make Enquirer easier to maintain and faster for users.
- Methods for registering "questions" have been removed. While it was nice to be able to preregister questions that could be called upon later, this is something that is better left to implementors, as it's relatively trivial to do with custom code.
- `options.default` is now `options.initial`
### Added
- Many prompts that were previously separate packages are now bundled into Enquirer itself.
[Unreleased]: https://github.com/enquirer/enquirer/compare/2.0.2...HEAD
[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog
The MIT License (MIT)
Copyright (c) 2016-present, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<h1 align="center">Enquirer</h1>
<p align="center">
<a href="https://npmjs.org/package/enquirer">
<img src="https://img.shields.io/npm/v/enquirer.svg" alt="version">
</a>
<a href="https://travis-ci.org/enquirer/enquirer">
<img src="https://img.shields.io/travis/enquirer/enquirer.svg" alt="travis">
</a>
<a href="https://npmjs.org/package/enquirer">
<img src="https://img.shields.io/npm/dm/enquirer.svg" alt="downloads">
</a>
</p>
<br>
<br>
<p align="center">
<b>Stylish CLI prompts that are user-friendly, intuitive and easy to create.</b><br>
<sub>>_ Prompts should be more like conversations than inquisitions▌</sub>
</p>
<br>
<p align="center">
<sub>(Example shows Enquirer's <a href="#survey-prompt">Survey Prompt</a>)</a></sub>
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/survey-prompt.gif" alt="Enquirer Survey Prompt" width="750"><br>
<sub>The terminal in all examples is <a href="https://hyper.is/">Hyper</a>, theme is <a href="https://github.com/jonschlinkert/hyper-monokai-extended">hyper-monokai-extended</a>.</sub><br><br>
<a href="#built-in-prompts"><strong>See more prompt examples</strong></a>
</p>
<br>
<br>
Created by [jonschlinkert](https://github.com/jonschlinkert) and [doowb](https://github.com/doowb), Enquirer is fast, easy to use, and lightweight enough for small projects, while also being powerful and customizable enough for the most advanced use cases.
* **Fast** - [Loads in ~4ms](#-performance) (that's about _3-4 times faster than a [single frame of a HD movie](http://www.endmemo.com/sconvert/framespersecondframespermillisecond.php) at 60fps_)
* **Lightweight** - Only one dependency, the excellent [ansi-colors](https://github.com/doowb/ansi-colors) by [Brian Woodward](https://github.com/doowb).
* **Easy to implement** - Uses promises and async/await and sensible defaults to make prompts easy to create and implement.
* **Easy to use** - Thrill your users with a better experience! Navigating around input and choices is a breeze. You can even create [quizzes](examples/fun/countdown.js), or [record](examples/fun/record.js) and [playback](examples/fun/play.js) key bindings to aid with tutorials and videos.
* **Intuitive** - Keypress combos are available to simplify usage.
* **Flexible** - All prompts can be used standalone or chained together.
* **Stylish** - Easily override semantic styles and symbols for any part of the prompt.
* **Extensible** - Easily create and use custom prompts by extending Enquirer's built-in [prompts](#-prompts).
* **Pluggable** - Add advanced features to Enquirer using plugins.
* **Validation** - Optionally validate user input with any prompt.
* **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) available to help you get started.
If you like Enquirer, please consider starring or tweeting about this project to show your support. Thanks!
<br>
<p align="center">
<b>>_ Ready to start making prompts your users will love? ▌</b><br>
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/heartbeat.gif" alt="Enquirer Select Prompt with heartbeat example" width="750">
</p>
<br>
<br>
## ❯ Getting started
Get started with Enquirer, the most powerful and easy-to-use Node.js library for creating interactive CLI prompts.
* [Install](#-install)
* [Usage](#-usage)
* [Enquirer](#-enquirer)
* [Prompts](#-prompts)
- [Built-in Prompts](#-prompts)
- [Custom Prompts](#-custom-prompts)
* [Key Bindings](#-key-bindings)
* [Options](#-options)
* [Release History](#-release-history)
* [Performance](#-performance)
* [About](#-about)
<br>
## ❯ Install
Install with [npm](https://www.npmjs.com/):
```sh
$ npm install enquirer --save
```
Install with [yarn](https://yarnpkg.com/en/):
```sh
$ yarn add enquirer
```
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/npm-install.gif" alt="Install Enquirer with NPM" width="750">
</p>
_(Requires Node.js 8.6 or higher. Please let us know if you need support for an earlier version by creating an [issue](../../issues/new).)_
<br>
## ❯ Usage
### Single prompt
The easiest way to get started with enquirer is to pass a [question object](#prompt-options) to the `prompt` method.
```js
const { prompt } = require('enquirer');
const response = await prompt({
type: 'input',
name: 'username',
message: 'What is your username?'
});
console.log(response); // { username: 'jonschlinkert' }
```
_(Examples with `await` need to be run inside an `async` function)_
### Multiple prompts
Pass an array of ["question" objects](#prompt-options) to run a series of prompts.
```js
const response = await prompt([
{
type: 'input',
name: 'name',
message: 'What is your name?'
},
{
type: 'input',
name: 'username',
message: 'What is your username?'
}
]);
console.log(response); // { name: 'Edward Chan', username: 'edwardmchan' }
```
### Different ways to run enquirer
#### 1. By importing the specific `built-in prompt`
```js
const { Confirm } = require('enquirer');
const prompt = new Confirm({
name: 'question',
message: 'Did you like enquirer?'
});
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>
## ❯ Enquirer
**Enquirer is a prompt runner**
Add Enquirer to your JavaScript project with following line of code.
```js
const Enquirer = require('enquirer');
```
The main export of this library is the `Enquirer` class, which has methods and features designed to simplify running prompts.
```js
const { prompt } = require('enquirer');
const question = [
{
type: 'input',
name: 'username',
message: 'What is your username?'
},
{
type: 'password',
name: 'password',
message: 'What is your password?'
}
];
let answers = await prompt(question);
console.log(answers);
```
**Prompts control how values are rendered and returned**
Each individual prompt is a class with special features and functionality for rendering the types of values you want to show users in the terminal, and subsequently returning the types of values you need to use in your application.
**How can I customize prompts?**
Below in this guide you will find information about creating [custom prompts](#-custom-prompts). For now, we'll focus on how to customize an existing 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()`.
Use this approach if you need to modify a prompt instance, or listen for events on the prompt.
**Example**
```js
const { Input } = require('enquirer');
const prompt = new Input({
name: 'username',
message: 'What is your username?'
});
prompt.run()
.then(answer => console.log('Username:', answer))
.catch(console.error);
```
### [Enquirer](index.js#L20)
Create an instance of `Enquirer`.
**Params**
* `options` **{Object}**: (optional) Options to use with all prompts.
* `answers` **{Object}**: (optional) Answers object to initialize with.
**Example**
```js
const Enquirer = require('enquirer');
const enquirer = new Enquirer();
```
### [register()](index.js#L42)
Register a custom prompt type.
**Params**
* `type` **{String}**
* `fn` **{Function|Prompt}**: `Prompt` class, or a function that returns a `Prompt` class.
* `returns` **{Object}**: Returns the Enquirer instance
**Example**
```js
const Enquirer = require('enquirer');
const enquirer = new Enquirer();
enquirer.register('customType', require('./custom-prompt'));
```
### [prompt()](index.js#L78)
Prompt function that takes a "question" object or array of question objects, and returns an object with responses from the user.
**Params**
* `questions` **{Array|Object}**: Options objects for one or more prompts to run.
* `returns` **{Promise}**: Promise that returns an "answers" object with the user's responses.
**Example**
```js
const Enquirer = require('enquirer');
const enquirer = new Enquirer();
const response = await enquirer.prompt({
type: 'input',
name: 'username',
message: 'What is your username?'
});
console.log(response);
```
### [use()](index.js#L160)
Use an enquirer plugin.
**Params**
* `plugin` **{Function}**: Plugin function that takes an instance of Enquirer.
* `returns` **{Object}**: Returns the Enquirer instance.
**Example**
```js
const Enquirer = require('enquirer');
const enquirer = new Enquirer();
const plugin = enquirer => {
// do stuff to enquire instance
};
enquirer.use(plugin);
```
### [Enquirer#prompt](index.js#L210)
Prompt function that takes a "question" object or array of question objects, and returns an object with responses from the user.
**Params**
* `questions` **{Array|Object}**: Options objects for one or more prompts to run.
* `returns` **{Promise}**: Promise that returns an "answers" object with the user's responses.
**Example**
```js
const { prompt } = require('enquirer');
const response = await prompt({
type: 'input',
name: 'username',
message: 'What is your username?'
});
console.log(response);
```
<br>
## ❯ Prompts
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.
**Getting started with Enquirer's prompts**
* [Prompt](#prompt) - The base `Prompt` class used by other prompts
- [Prompt Options](#prompt-options)
* [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.
### Prompt
The base `Prompt` class is used to create all other prompts.
```js
const { Prompt } = require('enquirer');
class MyCustomPrompt extends Prompt {}
```
See the documentation for [creating custom prompts](#-custom-prompts) to learn more about how this works.
#### Prompt Options
Each prompt takes an options object (aka "question" object), that implements the following interface:
```js
{
// required
type: string | function,
name: string | function,
message: string | function | async function,
// optional
skip: boolean | function | async function,
initial: string | function | async function,
format: function | async function,
result: function | async function,
validate: function | async function,
}
```
Each property of the options object is described below:
| **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**
```js
const { prompt } = require('enquirer');
const question = {
type: 'input',
name: 'username',
message: 'What is your username?'
};
prompt(question)
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
<br>
### Built-in prompts
* [AutoComplete Prompt](#autocomplete-prompt)
* [BasicAuth Prompt](#basicauth-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)
* [Quiz Prompt](#quiz-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)
### AutoComplete Prompt
Prompt that auto-completes as the user types, and returns the selected value as a string.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/autocomplete-prompt.gif" alt="Enquirer AutoComplete Prompt" width="750">
</p>
**Example Usage**
```js
const { AutoComplete } = require('enquirer');
const prompt = new AutoComplete({
name: 'flavor',
message: 'Pick your favorite flavor',
limit: 10,
initial: 2,
choices: [
'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);
```
**AutoComplete Options**
| 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. |
| `initial` | `number` | 0 | Preselected item in the list of choices. |
| `footer` | `function` | None | Function that displays [footer text](https://github.com/enquirer/enquirer/blob/6c2819518a1e2ed284242a99a685655fbaabfa28/examples/autocomplete/option-footer.js#L10) |
**Related prompts**
* [Select](#select-prompt)
* [MultiSelect](#multiselect-prompt)
* [Survey](#survey-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### BasicAuth Prompt
Prompt that asks for username and password to authenticate the user. The default implementation of `authenticate` function in `BasicAuth` prompt is to compare the username and password with the values supplied while running the prompt. The implementer is expected to override the `authenticate` function with a custom logic such as making an API request to a server to authenticate the username and password entered and expect a token back.
<p align="center">
<img src="https://user-images.githubusercontent.com/13731210/61570485-7ffd9c00-aaaa-11e9-857a-d47dc7008284.gif" alt="Enquirer BasicAuth Prompt" width="750">
</p>
**Example Usage**
```js
const { BasicAuth } = require('enquirer');
const prompt = new BasicAuth({
name: 'password',
message: 'Please enter your password',
username: 'rajat-sr',
password: '123',
showPassword: true
});
prompt
.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Confirm Prompt
Prompt that returns `true` or `false`.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/confirm-prompt.gif" alt="Enquirer Confirm Prompt" width="750">
</p>
**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**
* [Input](#input-prompt)
* [Numeral](#numeral-prompt)
* [Password](#password-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Form Prompt
Prompt that allows the user to enter and submit multiple values on a single terminal screen.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/form-prompt.gif" alt="Enquirer Form Prompt" width="750">
</p>
**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**
* [Input](#input-prompt)
* [Survey](#survey-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Input Prompt
Prompt that takes user input and returns a string.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/input-prompt.gif" alt="Enquirer Input Prompt" width="750">
</p>
**Example Usage**
```js
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);
```
You can use [data-store](https://github.com/jonschlinkert/data-store) to store [input history](https://github.com/enquirer/enquirer/blob/master/examples/input/option-history.js) that the user can cycle through (see [source](https://github.com/enquirer/enquirer/blob/8407dc3579123df5e6e20215078e33bb605b0c37/lib/prompts/input.js)).
**Related prompts**
* [Confirm](#confirm-prompt)
* [Numeral](#numeral-prompt)
* [Password](#password-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Invisible Prompt
Prompt that takes user input, hides it from the terminal, and returns a string.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/invisible-prompt.gif" alt="Enquirer Invisible Prompt" width="750">
</p>
**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**
* [Password](#password-prompt)
* [Input](#input-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### List Prompt
Prompt that returns a list of values, created by splitting the user input. The default split character is `,` with optional trailing whitespace.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/list-prompt.gif" alt="Enquirer List Prompt" width="750">
</p>
**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**
* [Sort](#sort-prompt)
* [Select](#select-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### MultiSelect Prompt
Prompt that allows the user to select multiple items from a list of options.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/multiselect-prompt.gif" alt="Enquirer MultiSelect Prompt" width="750">
</p>
**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);
// Answer: ['aqua', 'blue', 'fuchsia']
```
**Example key-value pairs**
Optionally, pass a `result` function and use the `.map` method to return an object of key-value pairs of the selected names and values: [example](./examples/multiselect/option-result.js)
```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' }
],
result(names) {
return this.map(names);
}
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
// Answer: { aqua: '#00ffff', blue: '#0000ff', fuchsia: '#ff00ff' }
```
**Related prompts**
* [AutoComplete](#autocomplete-prompt)
* [Select](#select-prompt)
* [Survey](#survey-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Numeral Prompt
Prompt that takes a number as input.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/numeral-prompt.gif" alt="Enquirer Numeral Prompt" width="750">
</p>
**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**
* [Input](#input-prompt)
* [Confirm](#confirm-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Password Prompt
Prompt that takes user input and masks it in the terminal. Also see the [invisible prompt](#invisible-prompt)
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/password-prompt.gif" alt="Enquirer Password Prompt" width="750">
</p>
**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**
* [Input](#input-prompt)
* [Invisible](#invisible-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Quiz Prompt
Prompt that allows the user to play multiple-choice quiz questions.
<p align="center">
<img src="https://user-images.githubusercontent.com/13731210/61567561-891d4780-aa6f-11e9-9b09-3d504abd24ed.gif" alt="Enquirer Quiz Prompt" width="750">
</p>
**Example Usage**
```js
const { Quiz } = require('enquirer');
const prompt = new Quiz({
name: 'countries',
message: 'How many countries are there in the world?',
choices: ['165', '175', '185', '195', '205'],
correctChoice: 3
});
prompt
.run()
.then(answer => {
if (answer.correct) {
console.log('Correct!');
} else {
console.log(`Wrong! Correct answer is ${answer.correctAnswer}`);
}
})
.catch(console.error);
```
**Quiz Options**
| Option | Type | Required | Description |
| ----------- | ---------- | ---------- | ------------------------------------------------------------------------------------------------------------ |
| `choices` | `array` | Yes | The list of possible answers to the quiz question. |
| `correctChoice`| `number` | Yes | Index of the correct choice from the `choices` array. |
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### 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
A more compact version of the [Survey prompt](#survey-prompt), the Scale prompt allows the user to quickly provide feedback using a [Likert Scale](https://en.wikipedia.org/wiki/Likert_scale).
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/scale-prompt.gif" alt="Enquirer Scale Prompt" width="750">
</p>
**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**
* [AutoComplete](#autocomplete-prompt)
* [Select](#select-prompt)
* [Survey](#survey-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Select Prompt
Prompt that allows the user to select from a list of options.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/select-prompt.gif" alt="Enquirer Select Prompt" width="750">
</p>
**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**
* [AutoComplete](#autocomplete-prompt)
* [MultiSelect](#multiselect-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Sort Prompt
Prompt that allows the user to sort items in a list.
**Example**
In this [example](https://github.com/enquirer/enquirer/raw/master/examples/sort/prompt.js), custom styling is applied to the returned values to make it easier to see what's happening.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/sort-prompt.gif" alt="Enquirer Sort Prompt" width="750">
</p>
**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**
* [List](#list-prompt)
* [Select](#select-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Snippet Prompt
Prompt that allows the user to replace placeholders in a snippet of code or text.
<p align="center">
<img src="https://raw.githubusercontent.com/enquirer/enquirer/master/media/snippet-prompt.gif" alt="Prompts" width="750">
</p>
**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**
* [Survey](#survey-prompt)
* [AutoComplete](#autocomplete-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Toggle Prompt
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>
**Example Usage**
```js
const { Toggle } = require('enquirer');
const prompt = new Toggle({
message: 'Want to answer?',
enabled: 'Yep',
disabled: 'Nope'
});
prompt.run()
.then(answer => console.log('Answer:', answer))
.catch(console.error);
```
**Related prompts**
* [Confirm](#confirm-prompt)
* [Input](#input-prompt)
* [Sort](#sort-prompt)
**↑ back to:** [Getting Started](#-getting-started) · [Prompts](#-prompts)
***
### Prompt Types
There are 5 (soon to be 6!) type classes:
* [ArrayPrompt](#arrayprompt)
- [Options](#options)
- [Properties](#properties)
- [Methods](#methods)
- [Choices](#choices)
- [Defining choices](#defining-choices)
- [Choice properties](#choice-properties)
- [Related prompts](#related-prompts)
* [AuthPrompt](#authprompt)
* [BooleanPrompt](#booleanprompt)
* DatePrompt (Coming Soon!)
* [NumberPrompt](#numberprompt)
* [StringPrompt](#stringprompt)
Each type is a low-level class that may be used as a starting point for creating higher level prompts. Continue reading to learn how.
### ArrayPrompt
The `ArrayPrompt` class is used for creating prompts that display a list of choices in the terminal. For example, Enquirer uses this class as the basis for the [Select](#select) and [Survey](#survey) prompts.
#### Options
In addition to the [options](#options) available to all prompts, Array prompts also support the following options.
| **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`. |
| |
#### Properties
Array prompts have the following instance properties and getters.
| **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** |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `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. |
#### Choices
Array prompts support the `choices` option, which is the array of choices users will be able to select from when rendered in the terminal.
**Type**: `string|object`
**Example**
```js
const { prompt } = require('enquirer');
const questions = [{
type: 'select',
name: 'color',
message: 'Favorite color?',
initial: 1,
choices: [
{ name: 'red', message: 'Red', value: '#ff0000' }, //<= choice object
{ name: 'green', message: 'Green', value: '#00ff00' }, //<= choice object
{ name: 'blue', message: 'Blue', value: '#0000ff' } //<= choice object
]
}];
let answers = await prompt(questions);
console.log('Answer:', answers.color);
```
#### Defining choices
Whether defined as a string or object, choices are normalized to the following interface:
```js
{
name: string;
message: string | undefined;
value: string | undefined;
hint: string | undefined;
disabled: boolean | string | undefined;
}
```
**Example**
```js
const question = {
name: 'fruit',
message: 'Favorite fruit?',
choices: ['Apple', 'Orange', 'Raspberry']
};
```
Normalizes to the following when the prompt is run:
```js
const question = {
name: 'fruit',
message: 'Favorite fruit?',
choices: [
{ name: 'Apple', message: 'Apple', value: 'Apple' },
{ name: 'Orange', message: 'Orange', value: 'Orange' },
{ name: 'Raspberry', message: 'Raspberry', value: 'Raspberry' }
]
};
```
#### Choice properties
The following properties are supported on `choice` objects.
| **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). |
#### Related prompts
* [AutoComplete](#autocomplete-prompt)
* [Form](#form-prompt)
* [MultiSelect](#multiselect-prompt)
* [Select](#select-prompt)
* [Survey](#survey-prompt)
***
### AuthPrompt
The `AuthPrompt` is used to create prompts to log in user using any authentication method. For example, Enquirer uses this class as the basis for the [BasicAuth Prompt](#basicauth-prompt). You can also find prompt examples in `examples/auth/` folder that utilizes `AuthPrompt` to create OAuth based authentication prompt or a prompt that authenticates using time-based OTP, among others.
`AuthPrompt` has a factory function that creates an instance of `AuthPrompt` class and it expects an `authenticate` function, as an argument, which overrides the `authenticate` function of the `AuthPrompt` class.
#### Methods
| **Method** | **Description** |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `authenticate()` | Contain all the authentication logic. This function should be overridden to implement custom authentication logic. The default `authenticate` function throws an error if no other function is provided. |
#### Choices
Auth prompt supports the `choices` option, which is the similar to the choices used in [Form Prompt](#form-prompt).
**Example**
```js
const { AuthPrompt } = require('enquirer');
function authenticate(value, state) {
if (value.username === this.options.username && value.password === this.options.password) {
return true;
}
return false;
}
const CustomAuthPrompt = AuthPrompt.create(authenticate);
const prompt = new CustomAuthPrompt({
name: 'password',
message: 'Please enter your password',
username: 'rajat-sr',
password: '1234567',
choices: [
{ name: 'username', message: 'username' },
{ name: 'password', message: 'password' }
]
});
prompt
.run()
.then(answer => console.log('Authenticated?', answer))
.catch(console.error);
```
#### Related prompts
* [BasicAuth Prompt](#basicauth-prompt)
***
### BooleanPrompt
The `BooleanPrompt` class is used for creating prompts that display and return a boolean value.
```js
const { BooleanPrompt } = require('enquirer');
const prompt = new BooleanPrompt({
header: '========================',
message: 'Do you love enquirer?',
footer: '========================',
});
prompt.run()
.then(answer => console.log('Selected:', answer))
.catch(console.error);
```
**Returns**: `boolean`
***
### NumberPrompt
The `NumberPrompt` class is used for creating prompts that display and return a numerical value.
```js
const { NumberPrompt } = require('enquirer');
const prompt = new NumberPrompt({
header: '************************',
message: 'Input the Numbers:',
footer: '************************',
});
prompt.run()
.then(answer => console.log('Numbers are:', answer))
.catch(console.error);
```
**Returns**: `string|number` (number, or number formatted as a string)
***
### StringPrompt
The `StringPrompt` class is used for creating prompts that display and return a string value.
```js
const { StringPrompt } = require('enquirer');
const prompt = new StringPrompt({
header: '************************',
message: 'Input the String:',
footer: '************************'
});
prompt.run()
.then(answer => console.log('String is:', answer))
.catch(console.error);
```
**Returns**: `string`
<br>
## ❯ Custom prompts
With Enquirer 2.0, custom prompts are easier than ever to create and use.
**How do I create a custom prompt?**
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 -->
```js
const { Prompt } = require('enquirer');
class HaiKarate extends Prompt {
constructor(options = {}) {
super(options);
this.value = options.initial || 0;
this.cursorHide();
}
up() {
this.value++;
this.render();
}
down() {
this.value--;
this.render();
}
render() {
this.clear(); // clear previously rendered prompt from the terminal
this.write(`${this.state.message}: ${this.value}`);
}
}
// Use the prompt by creating an instance of your custom prompt class.
const prompt = new HaiKarate({
message: 'How many sprays do you want?',
initial: 10
});
prompt.run()
.then(answer => console.log('Sprays:', answer))
.catch(console.error);
```
If you want to be able to specify your prompt by `type` so that it may be used alongside other prompts, you will need to first create an instance of `Enquirer`.
```js
const Enquirer = require('enquirer');
const enquirer = new Enquirer();
```
Then use the `.register()` method to add your custom prompt.
```js
enquirer.register('haikarate', HaiKarate);
```
Now you can do the following when defining "questions".
```js
let spritzer = require('cologne-drone');
let answers = await enquirer.prompt([
{
type: 'haikarate',
name: 'cologne',
message: 'How many sprays do you need?',
initial: 10,
async onSubmit(name, value) {
await spritzer.activate(value); //<= activate drone
return value;
}
}
]);
```
<br>
## ❯ Key Bindings
### All prompts
These key combinations may be used with all prompts.
| **command** | **description** |
| -------------------------------- | -------------------------------------- |
| <kbd>ctrl</kbd> + <kbd>c</kbd> | Cancel the prompt. |
| <kbd>ctrl</kbd> + <kbd>g</kbd> | Reset the prompt to its initial state. |
<br>
### Move cursor
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 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 |
<br>
### Edit Input
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 |
<br>
| **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)). |
### Select choices
These key combinations may be used on prompts that support _multiple_ choices, such as the [multiselect prompt](#multiselect-prompt), or the [select prompt](#select-prompt) when the `multiple` options 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. |
<br>
### Hide/show choices
| **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. |
<br>
### Move/lock Pointer
| **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). |
<br>
| **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. |
<br>
## ❯ Release History
Please see [CHANGELOG.md](CHANGELOG.md).
## ❯ Performance
### System specs
MacBook Pro, Intel Core i7, 2.5 GHz, 16 GB.
### Load time
Time it takes for the module to load the first time (average of 3 runs):
```
enquirer: 4.013ms
inquirer: 286.717ms
```
<br>
## ❯ About
<details>
<summary><strong>Contributing</strong></summary>
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
### 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>
<details>
<summary><strong>Running Tests</strong></summary>
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
```sh
$ npm install && npm test
```
```sh
$ yarn && yarn test
```
</details>
<details>
<summary><strong>Building docs</strong></summary>
_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
To generate the readme, run the following command:
```sh
$ npm install -g verbose/verb#dev verb-generate-readme && verb
```
</details>
#### Contributors
| **Commits** | **Contributor** |
| --- | --- |
| 283 | [jonschlinkert](https://github.com/jonschlinkert) |
| 82 | [doowb](https://github.com/doowb) |
| 32 | [rajat-sr](https://github.com/rajat-sr) |
| 20 | [318097](https://github.com/318097) |
| 15 | [g-plane](https://github.com/g-plane) |
| 12 | [pixelass](https://github.com/pixelass) |
| 5 | [adityavyas611](https://github.com/adityavyas611) |
| 5 | [satotake](https://github.com/satotake) |
| 3 | [tunnckoCore](https://github.com/tunnckoCore) |
| 3 | [Ovyerus](https://github.com/Ovyerus) |
| 3 | [sw-yx](https://github.com/sw-yx) |
| 2 | [DanielRuf](https://github.com/DanielRuf) |
| 2 | [GabeL7r](https://github.com/GabeL7r) |
| 1 | [AlCalzone](https://github.com/AlCalzone) |
| 1 | [hipstersmoothie](https://github.com/hipstersmoothie) |
| 1 | [danieldelcore](https://github.com/danieldelcore) |
| 1 | [ImgBotApp](https://github.com/ImgBotApp) |
| 1 | [jsonkao](https://github.com/jsonkao) |
| 1 | [knpwrs](https://github.com/knpwrs) |
| 1 | [yeskunall](https://github.com/yeskunall) |
| 1 | [mischah](https://github.com/mischah) |
| 1 | [renarsvilnis](https://github.com/renarsvilnis) |
| 1 | [sbugert](https://github.com/sbugert) |
| 1 | [stephencweiss](https://github.com/stephencweiss) |
| 1 | [skellock](https://github.com/skellock) |
| 1 | [whxaxes](https://github.com/whxaxes) |
#### Author
**Jon Schlinkert**
* [GitHub Profile](https://github.com/jonschlinkert)
* [Twitter Profile](https://twitter.com/jonschlinkert)
* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
#### 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
Copyright © 2018-present, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).
\ No newline at end of file
import { EventEmitter } from "events";
interface BasePromptOptions {
name: string | (() => string)
type: string | (() => string)
message: string | (() => string) | (() => Promise<string>)
initial?: any
required?: boolean
format?(value: string): string | Promise<string>
result?(value: string): string | Promise<string>
skip?: ((state: object) => boolean | Promise<boolean>) | boolean
validate?(value: string): boolean | Promise<boolean> | string | Promise<string>
onSubmit?(name: string, value: any, prompt: Enquirer.Prompt): boolean | Promise<boolean>
onCancel?(name: string, value: any, prompt: Enquirer.Prompt): boolean | Promise<boolean>
stdin?: NodeJS.ReadStream
stdout?: NodeJS.WriteStream
}
interface Choice {
name: string
message?: string
value?: string
hint?: string
disabled?: boolean | string
}
interface ArrayPromptOptions extends BasePromptOptions {
type:
| 'autocomplete'
| 'editable'
| 'form'
| 'multiselect'
| 'select'
| 'survey'
| 'list'
| 'scale'
choices: string[] | Choice[]
maxChoices?: number
muliple?: boolean
initial?: number
delay?: number
separator?: boolean
sort?: boolean
linebreak?: boolean
edgeLength?: number
align?: 'left' | 'right'
scroll?: boolean
}
interface BooleanPromptOptions extends BasePromptOptions {
type: 'confirm'
initial?: boolean
}
interface StringPromptOptions extends BasePromptOptions {
type: 'input' | 'invisible' | 'list' | 'password' | 'text'
initial?: string
multiline?: boolean
}
interface NumberPromptOptions extends BasePromptOptions {
type: 'numeral'
min?: number
max?: number
delay?: number
float?: boolean
round?: boolean
major?: number
minor?: number
initial?: number
}
interface SnippetPromptOptions extends BasePromptOptions {
type: 'snippet'
newline?: string
template?: string
}
interface SortPromptOptions extends BasePromptOptions {
type: 'sort'
hint?: string
drag?: boolean
numbered?: boolean
}
type PromptOptions =
| BasePromptOptions
| ArrayPromptOptions
| BooleanPromptOptions
| StringPromptOptions
| NumberPromptOptions
| SnippetPromptOptions
| SortPromptOptions
declare class BasePrompt extends EventEmitter {
constructor(options?: PromptOptions);
render(): void;
run(): Promise<any>;
}
declare class Enquirer<T = object> extends EventEmitter {
constructor(options?: object, answers?: T);
/**
* Register a custom prompt type.
*
* @param type
* @param fn `Prompt` class, or a function that returns a `Prompt` class.
*/
register(type: string, fn: typeof BasePrompt | (() => typeof BasePrompt)): this;
/**
* Register a custom prompt type.
*/
register(type: { [key: string]: typeof BasePrompt | (() => typeof BasePrompt) }): this;
/**
* Prompt function that takes a "question" object or array of question objects,
* and returns an object with responses from the user.
*
* @param questions Options objects for one or more prompts to run.
*/
prompt(
questions:
| PromptOptions
| ((this: Enquirer) => PromptOptions)
| (PromptOptions | ((this: Enquirer) => PromptOptions))[]
): Promise<T>;
/**
* Use an enquirer plugin.
*
* @param plugin Plugin function that takes an instance of Enquirer.
*/
use(plugin: (this: this, enquirer: this) => void): this;
}
declare namespace Enquirer {
function prompt<T = object>(
questions:
| PromptOptions
| ((this: Enquirer) => PromptOptions)
| (PromptOptions | ((this: Enquirer) => PromptOptions))[]
): Promise<T>;
class Prompt extends BasePrompt {}
}
export = Enquirer;
'use strict';
const assert = require('assert');
const Events = require('events');
const utils = require('./lib/utils');
/**
* Create an instance of `Enquirer`.
*
* ```js
* const Enquirer = require('enquirer');
* const enquirer = new Enquirer();
* ```
* @name Enquirer
* @param {Object} `options` (optional) Options to use with all prompts.
* @param {Object} `answers` (optional) Answers object to initialize with.
* @api public
*/
class Enquirer extends Events {
constructor(options, answers) {
super();
this.options = utils.merge({}, options);
this.answers = { ...answers };
}
/**
* Register a custom prompt type.
*
* ```js
* const Enquirer = require('enquirer');
* const enquirer = new Enquirer();
* enquirer.register('customType', require('./custom-prompt'));
* ```
* @name register()
* @param {String} `type`
* @param {Function|Prompt} `fn` `Prompt` class, or a function that returns a `Prompt` class.
* @return {Object} Returns the Enquirer instance
* @api public
*/
register(type, fn) {
if (utils.isObject(type)) {
for (let key of Object.keys(type)) this.register(key, type[key]);
return this;
}
assert.equal(typeof fn, 'function', 'expected a function');
let name = type.toLowerCase();
if (fn.prototype instanceof this.Prompt) {
this.prompts[name] = fn;
} else {
this.prompts[name] = fn(this.Prompt, this);
}
return this;
}
/**
* Prompt function that takes a "question" object or array of question objects,
* and returns an object with responses from the user.
*
* ```js
* const Enquirer = require('enquirer');
* const enquirer = new Enquirer();
*
* const response = await enquirer.prompt({
* type: 'input',
* name: 'username',
* message: 'What is your username?'
* });
* console.log(response);
* ```
* @name prompt()
* @param {Array|Object} `questions` Options objects for one or more prompts to run.
* @return {Promise} Promise that returns an "answers" object with the user's responses.
* @api public
*/
async prompt(questions = []) {
for (let question of [].concat(questions)) {
try {
if (typeof question === 'function') question = await question.call(this);
await this.ask(utils.merge({}, this.options, question));
} catch (err) {
return Promise.reject(err);
}
}
return this.answers;
}
async ask(question) {
if (typeof question === 'function') {
question = await question.call(this);
}
let opts = utils.merge({}, this.options, question);
let { type, name } = question;
let { set, get } = utils;
if (typeof type === 'function') {
type = await type.call(this, question, this.answers);
}
if (!type) return this.answers[name];
assert(this.prompts[type], `Prompt "${type}" is not registered`);
let prompt = new this.prompts[type](opts);
let value = get(this.answers, name);
prompt.state.answers = this.answers;
prompt.enquirer = this;
if (name) {
prompt.on('submit', value => {
this.emit('answer', name, value, prompt);
set(this.answers, name, value);
});
}
// bubble events
let emit = prompt.emit.bind(prompt);
prompt.emit = (...args) => {
this.emit.call(this, ...args);
return emit(...args);
};
this.emit('prompt', prompt, this);
if (opts.autofill && value != null) {
prompt.value = prompt.input = value;
// if "autofill=show" render the prompt, otherwise stay "silent"
if (opts.autofill === 'show') {
await prompt.submit();
}
} else {
value = prompt.value = await prompt.run();
}
return value;
}
/**
* Use an enquirer plugin.
*
* ```js
* const Enquirer = require('enquirer');
* const enquirer = new Enquirer();
* const plugin = enquirer => {
* // do stuff to enquire instance
* };
* enquirer.use(plugin);
* ```
* @name use()
* @param {Function} `plugin` Plugin function that takes an instance of Enquirer.
* @return {Object} Returns the Enquirer instance.
* @api public
*/
use(plugin) {
plugin.call(this, this);
return this;
}
set Prompt(value) {
this._Prompt = value;
}
get Prompt() {
return this._Prompt || this.constructor.Prompt;
}
get prompts() {
return this.constructor.prompts;
}
static set Prompt(value) {
this._Prompt = value;
}
static get Prompt() {
return this._Prompt || require('./lib/prompt');
}
static get prompts() {
return require('./lib/prompts');
}
static get types() {
return require('./lib/types');
}
/**
* Prompt function that takes a "question" object or array of question objects,
* and returns an object with responses from the user.
*
* ```js
* const { prompt } = require('enquirer');
* const response = await prompt({
* type: 'input',
* name: 'username',
* message: 'What is your username?'
* });
* console.log(response);
* ```
* @name Enquirer#prompt
* @param {Array|Object} `questions` Options objects for one or more prompts to run.
* @return {Promise} Promise that returns an "answers" object with the user's responses.
* @api public
*/
static get prompt() {
const fn = (questions, ...rest) => {
let enquirer = new this(...rest);
let emit = enquirer.emit.bind(enquirer);
enquirer.emit = (...args) => {
fn.emit(...args);
return emit(...args);
};
return enquirer.prompt(questions);
};
utils.mixinEmitter(fn, new Events());
return fn;
}
}
utils.mixinEmitter(Enquirer, new Events());
const prompts = Enquirer.prompts;
for (let name of Object.keys(prompts)) {
let key = name.toLowerCase();
let run = options => new prompts[name](options).run();
Enquirer.prompt[key] = run;
Enquirer[key] = run;
if (!Enquirer[name]) {
Reflect.defineProperty(Enquirer, name, { get: () => prompts[name] });
}
}
const exp = name => {
utils.defineExport(Enquirer, name, () => Enquirer.types[name]);
};
exp('ArrayPrompt');
exp('AuthPrompt');
exp('BooleanPrompt');
exp('NumberPrompt');
exp('StringPrompt');
module.exports = Enquirer;
'use strict';
const isTerm = process.env.TERM_PROGRAM === 'Apple_Terminal';
const colors = require('ansi-colors');
const utils = require('./utils');
const ansi = module.exports = exports;
const ESC = '\u001b[';
const BEL = '\u0007';
let hidden = false;
const code = ansi.code = {
bell: BEL,
beep: BEL,
beginning: `${ESC}G`,
down: `${ESC}J`,
esc: ESC,
getPosition: `${ESC}6n`,
hide: `${ESC}?25l`,
line: `${ESC}2K`,
lineEnd: `${ESC}K`,
lineStart: `${ESC}1K`,
restorePosition: ESC + (isTerm ? '8' : 'u'),
savePosition: ESC + (isTerm ? '7' : 's'),
screen: `${ESC}2J`,
show: `${ESC}?25h`,
up: `${ESC}1J`
};
const cursor = ansi.cursor = {
get hidden() {
return hidden;
},
hide() {
hidden = true;
return code.hide;
},
show() {
hidden = false;
return code.show;
},
forward: (count = 1) => `${ESC}${count}C`,
backward: (count = 1) => `${ESC}${count}D`,
nextLine: (count = 1) => `${ESC}E`.repeat(count),
prevLine: (count = 1) => `${ESC}F`.repeat(count),
up: (count = 1) => count ? `${ESC}${count}A` : '',
down: (count = 1) => count ? `${ESC}${count}B` : '',
right: (count = 1) => count ? `${ESC}${count}C` : '',
left: (count = 1) => count ? `${ESC}${count}D` : '',
to(x, y) {
return y ? `${ESC}${y + 1};${x + 1}H` : `${ESC}${x + 1}G`;
},
move(x = 0, y = 0) {
let res = '';
res += (x < 0) ? cursor.left(-x) : (x > 0) ? cursor.right(x) : '';
res += (y < 0) ? cursor.up(-y) : (y > 0) ? cursor.down(y) : '';
return res;
},
restore(state = {}) {
let { after, cursor, initial, input, prompt, size, value } = state;
initial = utils.isPrimitive(initial) ? String(initial) : '';
input = utils.isPrimitive(input) ? String(input) : '';
value = utils.isPrimitive(value) ? String(value) : '';
if (size) {
let codes = ansi.cursor.up(size) + ansi.cursor.to(prompt.length);
let diff = input.length - cursor;
if (diff > 0) {
codes += ansi.cursor.left(diff);
}
return codes;
}
if (value || after) {
let pos = (!input && !!initial) ? -initial.length : -input.length + cursor;
if (after) pos -= after.length;
if (input === '' && initial && !prompt.includes(initial)) {
pos += initial.length;
}
return ansi.cursor.move(pos);
}
}
};
const erase = ansi.erase = {
screen: code.screen,
up: code.up,
down: code.down,
line: code.line,
lineEnd: code.lineEnd,
lineStart: code.lineStart,
lines(n) {
let str = '';
for (let i = 0; i < n; i++) {
str += ansi.erase.line + (i < n - 1 ? ansi.cursor.up(1) : '');
}
if (n) str += ansi.code.beginning;
return str;
}
};
ansi.clear = (input = '', columns = process.stdout.columns) => {
if (!columns) return erase.line + cursor.to(0);
let width = str => [...colors.unstyle(str)].length;
let lines = input.split(/\r?\n/);
let rows = 0;
for (let line of lines) {
rows += 1 + Math.floor(Math.max(width(line) - 1, 0) / columns);
}
return (erase.line + cursor.prevLine()).repeat(rows - 1) + erase.line + cursor.to(0);
};
'use strict';
/**
* Actions are mappings from keypress event names to method names
* in the prompts.
*/
exports.ctrl = {
a: 'first',
b: 'backward',
c: 'cancel',
d: 'deleteForward',
e: 'last',
f: 'forward',
g: 'reset',
i: 'tab',
k: 'cutForward',
l: 'reset',
n: 'newItem',
m: 'cancel',
j: 'submit',
p: 'search',
r: 'remove',
s: 'save',
u: 'undo',
w: 'cutLeft',
x: 'toggleCursor',
v: 'paste'
};
exports.shift = {
up: 'shiftUp',
down: 'shiftDown',
left: 'shiftLeft',
right: 'shiftRight',
tab: 'prev'
};
exports.fn = {
up: 'pageUp',
down: 'pageDown',
left: 'pageLeft',
right: 'pageRight',
delete: 'deleteForward'
};
// <alt> on Windows
exports.option = {
b: 'backward',
f: 'forward',
d: 'cutRight',
left: 'cutLeft',
up: 'altUp',
down: 'altDown'
};
exports.keys = {
pageup: 'pageUp', // <fn>+<up> (mac), <Page Up> (windows)
pagedown: 'pageDown', // <fn>+<down> (mac), <Page Down> (windows)
home: 'home', // <fn>+<left> (mac), <home> (windows)
end: 'end', // <fn>+<right> (mac), <end> (windows)
cancel: 'cancel',
delete: 'deleteForward',
backspace: 'delete',
down: 'down',
enter: 'submit',
escape: 'cancel',
left: 'left',
space: 'space',
number: 'number',
return: 'submit',
right: 'right',
tab: 'next',
up: 'up'
};
'use strict';
const unique = arr => arr.filter((v, i) => arr.lastIndexOf(v) === i);
const compact = arr => unique(arr).filter(Boolean);
module.exports = (action, data = {}, value = '') => {
let { past = [], present = '' } = data;
let rest, prev;
switch (action) {
case 'prev':
case 'undo':
rest = past.slice(0, past.length - 1);
prev = past[past.length - 1] || '';
return {
past: compact([value, ...rest]),
present: prev
};
case 'next':
case 'redo':
rest = past.slice(1);
prev = past[0] || '';
return {
past: compact([...rest, value]),
present: prev
};
case 'save':
return {
past: compact([...past, value]),
present: ''
};
case 'remove':
prev = compact(past.filter(v => v !== value));
present = '';
if (prev.length) {
present = prev.pop();
}
return {
past: prev,
present
};
default: {
throw new Error(`Invalid action: "${action}"`);
}
}
};
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment