├── .gitignore ├── .npmignore ├── screenshots └── colors.png ├── lib ├── maps │ ├── zebra.js │ ├── america.js │ ├── rainbow.js │ └── random.js ├── index.js ├── system │ ├── has-flag.js │ └── supports-colors.js ├── custom │ ├── trap.js │ └── zalgo.js ├── styles.js ├── extendStringPrototype.js └── colors.js ├── .travis.yml ├── themes └── generic-logging.js ├── .eslintrc.json ├── safe.js ├── package.json ├── LICENSE ├── ROADMAP.md ├── safe.d.ts ├── examples ├── normal-usage.js └── safe-string.js ├── tests ├── safe-test.js └── basic-test.js ├── index.d.ts └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.sw* 2 | node_modules 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Development files 2 | /tests/ 3 | /.travis.yml 4 | /screenshots 5 | *.sw* 6 | -------------------------------------------------------------------------------- /screenshots/colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruricolist/colors.js/master/screenshots/colors.png -------------------------------------------------------------------------------- /lib/maps/zebra.js: -------------------------------------------------------------------------------- 1 | module['exports'] = function(colors) { 2 | return function(letter, i, exploded) { 3 | return i % 2 === 0 ? letter : colors.inverse(letter); 4 | }; 5 | }; 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "12" 4 | - "11" 5 | - "10" 6 | - "9" 7 | - "8" 8 | - "7" 9 | - "6" 10 | - "5" 11 | - "4" 12 | - "0.12" 13 | - "0.11" 14 | - "0.10" 15 | script: 16 | - npm install 17 | - npm test 18 | -------------------------------------------------------------------------------- /themes/generic-logging.js: -------------------------------------------------------------------------------- 1 | module['exports'] = { 2 | silly: 'rainbow', 3 | input: 'grey', 4 | verbose: 'cyan', 5 | prompt: 'grey', 6 | info: 'green', 7 | data: 'grey', 8 | help: 'cyan', 9 | warn: 'yellow', 10 | debug: 'blue', 11 | error: 'red', 12 | }; 13 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "google", 3 | "rules": { 4 | "no-var": "off", 5 | "prefer-const": "off", 6 | "eol-last": ["error", "always"], 7 | "require-jsdoc": "off", 8 | "guard-for-in": "off", 9 | "prefer-rest-params": "off" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /safe.js: -------------------------------------------------------------------------------- 1 | // 2 | // Remark: Requiring this file will use the "safe" colors API, 3 | // which will not touch String.prototype. 4 | // 5 | // var colors = require('colors/safe'); 6 | // colors.red("foo") 7 | // 8 | // 9 | var colors = require('./lib/colors'); 10 | module['exports'] = colors; 11 | -------------------------------------------------------------------------------- /lib/maps/america.js: -------------------------------------------------------------------------------- 1 | module['exports'] = function(colors) { 2 | return function(letter, i, exploded) { 3 | if (letter === ' ') return letter; 4 | switch (i%3) { 5 | case 0: return colors.red(letter); 6 | case 1: return colors.white(letter); 7 | case 2: return colors.blue(letter); 8 | } 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /lib/maps/rainbow.js: -------------------------------------------------------------------------------- 1 | module['exports'] = function(colors) { 2 | // RoY G BiV 3 | var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; 4 | return function(letter, i, exploded) { 5 | if (letter === ' ') { 6 | return letter; 7 | } else { 8 | return colors[rainbowColors[i++ % rainbowColors.length]](letter); 9 | } 10 | }; 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | var colors = require('./colors'); 2 | module['exports'] = colors; 3 | 4 | // Remark: By default, colors will add style properties to String.prototype. 5 | // 6 | // If you don't wish to extend String.prototype, you can do this instead and 7 | // native String will not be touched: 8 | // 9 | // var colors = require('colors/safe); 10 | // colors.red("foo") 11 | // 12 | // 13 | require('./extendStringPrototype')(); 14 | -------------------------------------------------------------------------------- /lib/maps/random.js: -------------------------------------------------------------------------------- 1 | module['exports'] = function(colors) { 2 | var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green', 3 | 'blue', 'white', 'cyan', 'magenta', 'brightYellow', 'brightRed', 4 | 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 'brightMagenta']; 5 | return function(letter, i, exploded) { 6 | return letter === ' ' ? letter : 7 | colors[ 8 | available[Math.round(Math.random() * (available.length - 2))] 9 | ](letter); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colors", 3 | "description": "get colors in your node.js console", 4 | "version": "1.4.0", 5 | "author": "Marak Squires", 6 | "contributors": [ 7 | { 8 | "name": "DABH", 9 | "url": "https://github.com/DABH" 10 | } 11 | ], 12 | "homepage": "https://github.com/Marak/colors.js", 13 | "bugs": "https://github.com/Marak/colors.js/issues", 14 | "keywords": [ 15 | "ansi", 16 | "terminal", 17 | "colors" 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "http://github.com/Marak/colors.js.git" 22 | }, 23 | "license": "MIT", 24 | "scripts": { 25 | "lint": "eslint . --fix", 26 | "test": "node tests/basic-test.js && node tests/safe-test.js" 27 | }, 28 | "engines": { 29 | "node": ">=0.1.90" 30 | }, 31 | "main": "lib/index.js", 32 | "files": [ 33 | "examples", 34 | "lib", 35 | "LICENSE", 36 | "safe.js", 37 | "themes", 38 | "index.d.ts", 39 | "safe.d.ts" 40 | ], 41 | "devDependencies": { 42 | "eslint": "^5.2.0", 43 | "eslint-config-google": "^0.11.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Original Library 4 | - Copyright (c) Marak Squires 5 | 6 | Additional Functionality 7 | - Copyright (c) Sindre Sorhus (sindresorhus.com) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | # colors.js roadmap / changelog 2 | 3 | Here we describe upcoming and recent releases and the key features/fixes they include. Don't see your feature/issue listed here? Get more +1's! 4 | 5 | ## Currently Planned Releases 6 | 7 | ### 1.5.0 8 | * Support custom colors 9 | 10 | ### 1.4.1 11 | * Refactor tests to use a testing library like jest (only affects dev/testing) 12 | 13 | ### ~~1.4.0 (9/22/19)~~ 14 | * ~~Allow colorizing null/undefined in safe mode (@givehug, @jweinsteincbt)~~ 15 | * ~~Add bright/background colors (ASCI standard) (@vsimonian, @mejenborg)~~ 16 | * ~~Improve docs around enable()/disable() (@mrjacobbloom)~~ 17 | 18 | ### ~~1.3.3 (12/9/18)~~ 19 | 20 | * ~~Remove extraneous swap files~~ 21 | * ~~Fix subtle bug in custom theme properties mixing themes and styles~~ 22 | 23 | ### ~~1.3.1 (7/22/18)~~ 24 | 25 | * ~~Remove circular dependencies due to color maps~~ 26 | * ~~Fix multiple attributes in custom setTheme in safe mode~~ 27 | * ~~Preserve multiple consecutive newlines when applying style~~ 28 | 29 | ### ~~1.2.3 (4/30/18)~~ 30 | * ~~Add ESLint and lint all the things~~ 31 | 32 | ### ~~1.2.2 (4/30/18)~~ 33 | * ~~Fix multiline string support, Typescript fixes, etc.~~ 34 | 35 | ### ~~1.2.0 (release date: about 3/5/18, barring any new issues)~~ 36 | * ~~Built-in Typescript definitions~~ 37 | * ~~Key bug fixes for webpack/bundlers, webstorm, etc.~~ 38 | 39 | -------------------------------------------------------------------------------- /lib/system/has-flag.js: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) Sindre Sorhus (sindresorhus.com) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | module.exports = function(flag, argv) { 28 | argv = argv || process.argv; 29 | 30 | var terminatorPos = argv.indexOf('--'); 31 | var prefix = /^-{1,2}/.test(flag) ? '' : '--'; 32 | var pos = argv.indexOf(prefix + flag); 33 | 34 | return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos); 35 | }; 36 | -------------------------------------------------------------------------------- /lib/custom/trap.js: -------------------------------------------------------------------------------- 1 | module['exports'] = function runTheTrap(text, options) { 2 | var result = ''; 3 | text = text || 'Run the trap, drop the bass'; 4 | text = text.split(''); 5 | var trap = { 6 | a: ['\u0040', '\u0104', '\u023a', '\u0245', '\u0394', '\u039b', '\u0414'], 7 | b: ['\u00df', '\u0181', '\u0243', '\u026e', '\u03b2', '\u0e3f'], 8 | c: ['\u00a9', '\u023b', '\u03fe'], 9 | d: ['\u00d0', '\u018a', '\u0500', '\u0501', '\u0502', '\u0503'], 10 | e: ['\u00cb', '\u0115', '\u018e', '\u0258', '\u03a3', '\u03be', '\u04bc', 11 | '\u0a6c'], 12 | f: ['\u04fa'], 13 | g: ['\u0262'], 14 | h: ['\u0126', '\u0195', '\u04a2', '\u04ba', '\u04c7', '\u050a'], 15 | i: ['\u0f0f'], 16 | j: ['\u0134'], 17 | k: ['\u0138', '\u04a0', '\u04c3', '\u051e'], 18 | l: ['\u0139'], 19 | m: ['\u028d', '\u04cd', '\u04ce', '\u0520', '\u0521', '\u0d69'], 20 | n: ['\u00d1', '\u014b', '\u019d', '\u0376', '\u03a0', '\u048a'], 21 | o: ['\u00d8', '\u00f5', '\u00f8', '\u01fe', '\u0298', '\u047a', '\u05dd', 22 | '\u06dd', '\u0e4f'], 23 | p: ['\u01f7', '\u048e'], 24 | q: ['\u09cd'], 25 | r: ['\u00ae', '\u01a6', '\u0210', '\u024c', '\u0280', '\u042f'], 26 | s: ['\u00a7', '\u03de', '\u03df', '\u03e8'], 27 | t: ['\u0141', '\u0166', '\u0373'], 28 | u: ['\u01b1', '\u054d'], 29 | v: ['\u05d8'], 30 | w: ['\u0428', '\u0460', '\u047c', '\u0d70'], 31 | x: ['\u04b2', '\u04fe', '\u04fc', '\u04fd'], 32 | y: ['\u00a5', '\u04b0', '\u04cb'], 33 | z: ['\u01b5', '\u0240'], 34 | }; 35 | text.forEach(function(c) { 36 | c = c.toLowerCase(); 37 | var chars = trap[c] || [' ']; 38 | var rand = Math.floor(Math.random() * chars.length); 39 | if (typeof trap[c] !== 'undefined') { 40 | result += trap[c][rand]; 41 | } else { 42 | result += c; 43 | } 44 | }); 45 | return result; 46 | }; 47 | -------------------------------------------------------------------------------- /safe.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Colors.js 1.2 2 | // Project: https://github.com/Marak/colors.js 3 | // Definitions by: Bart van der Schoor , Staffan Eketorp 4 | // Definitions: https://github.com/Marak/colors.js 5 | 6 | export const enabled: boolean; 7 | export function enable(): void; 8 | export function disable(): void; 9 | export function setTheme(theme: any): void; 10 | 11 | export function strip(str: string): string; 12 | export function stripColors(str: string): string; 13 | 14 | export function black(str: string): string; 15 | export function red(str: string): string; 16 | export function green(str: string): string; 17 | export function yellow(str: string): string; 18 | export function blue(str: string): string; 19 | export function magenta(str: string): string; 20 | export function cyan(str: string): string; 21 | export function white(str: string): string; 22 | export function gray(str: string): string; 23 | export function grey(str: string): string; 24 | 25 | export function bgBlack(str: string): string; 26 | export function bgRed(str: string): string; 27 | export function bgGreen(str: string): string; 28 | export function bgYellow(str: string): string; 29 | export function bgBlue(str: string): string; 30 | export function bgMagenta(str: string): string; 31 | export function bgCyan(str: string): string; 32 | export function bgWhite(str: string): string; 33 | 34 | export function reset(str: string): string; 35 | export function bold(str: string): string; 36 | export function dim(str: string): string; 37 | export function italic(str: string): string; 38 | export function underline(str: string): string; 39 | export function inverse(str: string): string; 40 | export function hidden(str: string): string; 41 | export function strikethrough(str: string): string; 42 | 43 | export function rainbow(str: string): string; 44 | export function zebra(str: string): string; 45 | export function america(str: string): string; 46 | export function trap(str: string): string; 47 | export function random(str: string): string; 48 | export function zalgo(str: string): string; 49 | -------------------------------------------------------------------------------- /examples/normal-usage.js: -------------------------------------------------------------------------------- 1 | var colors = require('../lib/index'); 2 | 3 | console.log('First some yellow text'.yellow); 4 | 5 | console.log('Underline that text'.yellow.underline); 6 | 7 | console.log('Make it bold and red'.red.bold); 8 | 9 | console.log(('Double Raindows All Day Long').rainbow); 10 | 11 | console.log('Drop the bass'.trap); 12 | 13 | console.log('DROP THE RAINBOW BASS'.trap.rainbow); 14 | 15 | // styles not widely supported 16 | console.log('Chains are also cool.'.bold.italic.underline.red); 17 | 18 | // styles not widely supported 19 | console.log('So '.green + 'are'.underline + ' ' + 'inverse'.inverse 20 | + ' styles! '.yellow.bold); 21 | console.log('Zebras are so fun!'.zebra); 22 | 23 | // 24 | // Remark: .strikethrough may not work with Mac OS Terminal App 25 | // 26 | console.log('This is ' + 'not'.strikethrough + ' fun.'); 27 | 28 | console.log('Background color attack!'.black.bgWhite); 29 | console.log('Use random styles on everything!'.random); 30 | console.log('America, Heck Yeah!'.america); 31 | 32 | console.log('Blindingly '.brightCyan + 'bright? '.brightRed + 'Why '.brightYellow + 'not?!'.brightGreen); 33 | 34 | console.log('Setting themes is useful'); 35 | 36 | // 37 | // Custom themes 38 | // 39 | console.log('Generic logging theme as JSON'.green.bold.underline); 40 | // Load theme with JSON literal 41 | colors.setTheme({ 42 | silly: 'rainbow', 43 | input: 'grey', 44 | verbose: 'cyan', 45 | prompt: 'grey', 46 | info: 'green', 47 | data: 'grey', 48 | help: 'cyan', 49 | warn: 'yellow', 50 | debug: 'blue', 51 | error: 'red', 52 | }); 53 | 54 | // outputs red text 55 | console.log('this is an error'.error); 56 | 57 | // outputs yellow text 58 | console.log('this is a warning'.warn); 59 | 60 | // outputs grey text 61 | console.log('this is an input'.input); 62 | 63 | console.log('Generic logging theme as file'.green.bold.underline); 64 | 65 | // Load a theme from file 66 | try { 67 | colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); 68 | } catch (err) { 69 | console.log(err); 70 | } 71 | 72 | // outputs red text 73 | console.log('this is an error'.error); 74 | 75 | // outputs yellow text 76 | console.log('this is a warning'.warn); 77 | 78 | // outputs grey text 79 | console.log('this is an input'.input); 80 | 81 | // console.log("Don't summon".zalgo) 82 | 83 | -------------------------------------------------------------------------------- /examples/safe-string.js: -------------------------------------------------------------------------------- 1 | var colors = require('../safe'); 2 | 3 | console.log(colors.yellow('First some yellow text')); 4 | 5 | console.log(colors.yellow.underline('Underline that text')); 6 | 7 | console.log(colors.red.bold('Make it bold and red')); 8 | 9 | console.log(colors.rainbow('Double Raindows All Day Long')); 10 | 11 | console.log(colors.trap('Drop the bass')); 12 | 13 | console.log(colors.rainbow(colors.trap('DROP THE RAINBOW BASS'))); 14 | 15 | // styles not widely supported 16 | console.log(colors.bold.italic.underline.red('Chains are also cool.')); 17 | 18 | // styles not widely supported 19 | console.log(colors.green('So ') + colors.underline('are') + ' ' 20 | + colors.inverse('inverse') + colors.yellow.bold(' styles! ')); 21 | 22 | console.log(colors.zebra('Zebras are so fun!')); 23 | 24 | console.log('This is ' + colors.strikethrough('not') + ' fun.'); 25 | 26 | 27 | console.log(colors.black.bgWhite('Background color attack!')); 28 | console.log(colors.random('Use random styles on everything!')); 29 | console.log(colors.america('America, Heck Yeah!')); 30 | 31 | console.log(colors.brightCyan('Blindingly ') + colors.brightRed('bright? ') + colors.brightYellow('Why ') + colors.brightGreen('not?!')); 32 | 33 | console.log('Setting themes is useful'); 34 | 35 | // 36 | // Custom themes 37 | // 38 | // console.log('Generic logging theme as JSON'.green.bold.underline); 39 | // Load theme with JSON literal 40 | colors.setTheme({ 41 | silly: 'rainbow', 42 | input: 'blue', 43 | verbose: 'cyan', 44 | prompt: 'grey', 45 | info: 'green', 46 | data: 'grey', 47 | help: 'cyan', 48 | warn: 'yellow', 49 | debug: 'blue', 50 | error: 'red', 51 | }); 52 | 53 | // outputs red text 54 | console.log(colors.error('this is an error')); 55 | 56 | // outputs yellow text 57 | console.log(colors.warn('this is a warning')); 58 | 59 | // outputs blue text 60 | console.log(colors.input('this is an input')); 61 | 62 | 63 | // console.log('Generic logging theme as file'.green.bold.underline); 64 | 65 | // Load a theme from file 66 | colors.setTheme(require(__dirname + '/../themes/generic-logging.js')); 67 | 68 | // outputs red text 69 | console.log(colors.error('this is an error')); 70 | 71 | // outputs yellow text 72 | console.log(colors.warn('this is a warning')); 73 | 74 | // outputs grey text 75 | console.log(colors.input('this is an input')); 76 | 77 | // console.log(colors.zalgo("Don't summon him")) 78 | 79 | 80 | -------------------------------------------------------------------------------- /lib/styles.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) Sindre Sorhus (sindresorhus.com) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | */ 25 | 26 | var styles = {}; 27 | module['exports'] = styles; 28 | 29 | var codes = { 30 | reset: [0, 0], 31 | 32 | bold: [1, 22], 33 | dim: [2, 22], 34 | italic: [3, 23], 35 | underline: [4, 24], 36 | inverse: [7, 27], 37 | hidden: [8, 28], 38 | strikethrough: [9, 29], 39 | 40 | black: [30, 39], 41 | red: [31, 39], 42 | green: [32, 39], 43 | yellow: [33, 39], 44 | blue: [34, 39], 45 | magenta: [35, 39], 46 | cyan: [36, 39], 47 | white: [37, 39], 48 | gray: [90, 39], 49 | grey: [90, 39], 50 | 51 | brightRed: [91, 39], 52 | brightGreen: [92, 39], 53 | brightYellow: [93, 39], 54 | brightBlue: [94, 39], 55 | brightMagenta: [95, 39], 56 | brightCyan: [96, 39], 57 | brightWhite: [97, 39], 58 | 59 | bgBlack: [40, 49], 60 | bgRed: [41, 49], 61 | bgGreen: [42, 49], 62 | bgYellow: [43, 49], 63 | bgBlue: [44, 49], 64 | bgMagenta: [45, 49], 65 | bgCyan: [46, 49], 66 | bgWhite: [47, 49], 67 | bgGray: [100, 49], 68 | bgGrey: [100, 49], 69 | 70 | bgBrightRed: [101, 49], 71 | bgBrightGreen: [102, 49], 72 | bgBrightYellow: [103, 49], 73 | bgBrightBlue: [104, 49], 74 | bgBrightMagenta: [105, 49], 75 | bgBrightCyan: [106, 49], 76 | bgBrightWhite: [107, 49], 77 | 78 | // legacy styles for colors pre v1.0.0 79 | blackBG: [40, 49], 80 | redBG: [41, 49], 81 | greenBG: [42, 49], 82 | yellowBG: [43, 49], 83 | blueBG: [44, 49], 84 | magentaBG: [45, 49], 85 | cyanBG: [46, 49], 86 | whiteBG: [47, 49], 87 | 88 | }; 89 | 90 | Object.keys(codes).forEach(function(key) { 91 | var val = codes[key]; 92 | var style = styles[key] = []; 93 | style.open = '\u001b[' + val[0] + 'm'; 94 | style.close = '\u001b[' + val[1] + 'm'; 95 | }); 96 | -------------------------------------------------------------------------------- /tests/safe-test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var colors = require('../safe'); 3 | 4 | var s = 'string'; 5 | 6 | function a(s, code) { 7 | return '\x1B[' + code.toString() + 'm' + s + '\x1B[39m'; 8 | } 9 | 10 | function aE(s, color, code) { 11 | assert.equal(colors[color](s), a(s, code)); 12 | assert.equal(colors.strip(s), s); 13 | } 14 | 15 | var stylesColors = ['white', 'black', 'blue', 'cyan', 'green', 'magenta', 16 | 'red', 'yellow', 'brightYellow', 'brightRed', 17 | 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 18 | 'brightMagenta']; 19 | // eslint-disable-next-line 20 | var stylesAll = stylesColors.concat(['bold', 'italic', 'underline', 'inverse', 21 | 'rainbow']); 22 | 23 | colors.mode = 'console'; 24 | assert.equal(colors.bold(s), '\x1B[1m' + s + '\x1B[22m'); 25 | assert.equal(colors.italic(s), '\x1B[3m' + s + '\x1B[23m'); 26 | assert.equal(colors.underline(s), '\x1B[4m' + s + '\x1B[24m'); 27 | assert.equal(colors.strikethrough(s), '\x1B[9m' + s + '\x1B[29m'); 28 | assert.equal(colors.inverse(s), '\x1B[7m' + s + '\x1B[27m'); 29 | 30 | assert.ok(colors.rainbow); 31 | 32 | aE(s, 'white', 37); 33 | aE(s, 'grey', 90); 34 | aE(s, 'black', 30); 35 | aE(s, 'blue', 34); 36 | aE(s, 'cyan', 36); 37 | aE(s, 'green', 32); 38 | aE(s, 'magenta', 35); 39 | aE(s, 'red', 31); 40 | aE(s, 'yellow', 33); 41 | 42 | aE(s, 'brightWhite', 97); 43 | aE(s, 'brightBlue', 94); 44 | aE(s, 'brightCyan', 96); 45 | aE(s, 'brightGreen', 92); 46 | aE(s, 'brightMagenta', 95); 47 | aE(s, 'brightRed', 91); 48 | aE(s, 'brightYellow', 93); 49 | 50 | assert.equal(s, 'string'); 51 | 52 | var testStringWithNewLines = s + '\n' + s; 53 | 54 | // single style 55 | assert.equal(colors.red(testStringWithNewLines), 56 | '\x1b[31m' + s + '\x1b[39m' + '\n' + '\x1b[31m' + s + '\x1b[39m'); 57 | 58 | var testStringWithNewLinesStyled = colors.underline(s) + '\n' + colors.bold(s); 59 | 60 | // nested styles 61 | assert.equal(colors.red(testStringWithNewLinesStyled), 62 | '\x1b[31m' + '\x1b[4m' + s + '\x1b[24m' + '\x1b[39m' + '\n' + '\x1b[31m' + 63 | '\x1b[1m' + s + '\x1b[22m' + '\x1b[39m'); 64 | 65 | colors.setTheme({error: 'red'}); 66 | 67 | assert.equal(typeof (colors.red('astring')), 'string'); 68 | assert.equal(typeof (colors.error('astring')), 'string'); 69 | 70 | colors.setTheme({custom: ['blue', 'bold', 'underline']}); 71 | assert.equal(colors.custom(s), 72 | '\x1b[4m' + '\x1b[1m' + '\x1b[34m' + s + 73 | '\x1b[39m' + '\x1b[22m' + '\x1b[24m' ); 74 | 75 | colors.setTheme({custom: ['red', 'italic', 'inverse']}); 76 | assert.equal(colors.custom(s), 77 | '\x1b[7m' + '\x1b[3m' + '\x1b[31m' + s + 78 | '\x1b[39m' + '\x1b[23m' + '\x1b[27m' ); 79 | 80 | // should not throw error on null or undefined values 81 | var undef; 82 | assert.equal(colors.yellow(undef), '\x1b[33mundefined\x1b[39m'); 83 | 84 | // was failing: 85 | assert.equal(colors.red(null), '\x1b[31mnull\x1b[39m'); 86 | -------------------------------------------------------------------------------- /tests/basic-test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var colors = require('../lib/index'); 3 | 4 | var s = 'string'; 5 | 6 | function a(s, code) { 7 | return '\x1B[' + code.toString() + 'm' + s + '\x1B[39m'; 8 | } 9 | 10 | function aE(s, color, code) { 11 | assert.equal(s[color], a(s, code)); 12 | assert.equal(colors[color](s), a(s, code)); 13 | assert.equal(s[color], colors[color](s)); 14 | assert.equal(s[color].strip, s); 15 | assert.equal(s[color].strip, colors.strip(s)); 16 | } 17 | 18 | var stylesColors = ['white', 'black', 'blue', 'cyan', 'green', 'magenta', 19 | 'red', 'yellow', 'brightYellow', 'brightRed', 20 | 'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 21 | 'brightMagenta']; 22 | 23 | // eslint-disable-next-line 24 | var stylesAll = stylesColors.concat(['bold', 'italic', 'underline', 25 | 'inverse', 'rainbow']); 26 | 27 | colors.mode = 'console'; 28 | assert.equal(s.bold, '\x1B[1m' + s + '\x1B[22m'); 29 | assert.equal(s.italic, '\x1B[3m' + s + '\x1B[23m'); 30 | assert.equal(s.underline, '\x1B[4m' + s + '\x1B[24m'); 31 | assert.equal(s.strikethrough, '\x1B[9m' + s + '\x1B[29m'); 32 | assert.equal(s.inverse, '\x1B[7m' + s + '\x1B[27m'); 33 | 34 | assert.ok(s.rainbow); 35 | 36 | assert.equal(colors.stylize("foo", "rainbow"), '\u001b[31mf\u001b[39m\u001b[33mo\u001b[39m\u001b[32mo\u001b[39m'); 37 | assert.ok(colors.stylize(s, "america")); 38 | assert.ok(colors.stylize(s, "zebra")); 39 | assert.ok(colors.stylize(s, "trap")); 40 | assert.ok(colors.stylize(s, "random")); 41 | 42 | aE(s, 'white', 37); 43 | aE(s, 'grey', 90); 44 | aE(s, 'black', 30); 45 | aE(s, 'blue', 34); 46 | aE(s, 'cyan', 36); 47 | aE(s, 'green', 32); 48 | aE(s, 'magenta', 35); 49 | aE(s, 'red', 31); 50 | aE(s, 'yellow', 33); 51 | 52 | aE(s, 'brightWhite', 97); 53 | aE(s, 'brightBlue', 94); 54 | aE(s, 'brightCyan', 96); 55 | aE(s, 'brightGreen', 92); 56 | aE(s, 'brightMagenta', 95); 57 | aE(s, 'brightRed', 91); 58 | aE(s, 'brightYellow', 93); 59 | 60 | assert.equal(s, 'string'); 61 | 62 | var testStringWithNewLines = s + '\n' + s; 63 | 64 | // single style 65 | assert.equal(testStringWithNewLines.red, '\x1b[31m' + s + '\n' + s + 66 | '\x1b[39m'); 67 | 68 | var testStringWithNewLinesStyled = s.underline + '\n' + s.bold; 69 | 70 | // nested styles 71 | assert.equal(testStringWithNewLinesStyled.red, 72 | '\x1b[31m' + '\x1b[4m' + s + '\x1b[24m' + '\n' + '\x1b[1m' + s + 73 | '\x1b[22m' + '\x1b[39m'); 74 | 75 | colors.setTheme({error: 'red'}); 76 | 77 | assert.equal(typeof ('astring'.red), 'string'); 78 | assert.equal(typeof ('astring'.error), 'string'); 79 | 80 | assert.equal(s, 'string'); 81 | 82 | colors.setTheme({custom: ['blue', 'bold', 'underline']}); 83 | assert.equal(colors.custom(s), 84 | '\x1b[4m' + '\x1b[1m' + '\x1b[34m' + s + 85 | '\x1b[39m' + '\x1b[22m' + '\x1b[24m' ); 86 | 87 | colors.setTheme({custom: ['red', 'italic', 'inverse']}); 88 | assert.equal(colors.custom(s), 89 | '\x1b[7m' + '\x1b[3m' + '\x1b[31m' + s + 90 | '\x1b[39m' + '\x1b[23m' + '\x1b[27m' ); 91 | -------------------------------------------------------------------------------- /lib/custom/zalgo.js: -------------------------------------------------------------------------------- 1 | // please no 2 | module['exports'] = function zalgo(text, options) { 3 | text = text || ' he is here '; 4 | var soul = { 5 | 'up': [ 6 | '̍', '̎', '̄', '̅', 7 | '̿', '̑', '̆', '̐', 8 | '͒', '͗', '͑', '̇', 9 | '̈', '̊', '͂', '̓', 10 | '̈', '͊', '͋', '͌', 11 | '̃', '̂', '̌', '͐', 12 | '̀', '́', '̋', '̏', 13 | '̒', '̓', '̔', '̽', 14 | '̉', 'ͣ', 'ͤ', 'ͥ', 15 | 'ͦ', 'ͧ', 'ͨ', 'ͩ', 16 | 'ͪ', 'ͫ', 'ͬ', 'ͭ', 17 | 'ͮ', 'ͯ', '̾', '͛', 18 | '͆', '̚', 19 | ], 20 | 'down': [ 21 | '̖', '̗', '̘', '̙', 22 | '̜', '̝', '̞', '̟', 23 | '̠', '̤', '̥', '̦', 24 | '̩', '̪', '̫', '̬', 25 | '̭', '̮', '̯', '̰', 26 | '̱', '̲', '̳', '̹', 27 | '̺', '̻', '̼', 'ͅ', 28 | '͇', '͈', '͉', '͍', 29 | '͎', '͓', '͔', '͕', 30 | '͖', '͙', '͚', '̣', 31 | ], 32 | 'mid': [ 33 | '̕', '̛', '̀', '́', 34 | '͘', '̡', '̢', '̧', 35 | '̨', '̴', '̵', '̶', 36 | '͜', '͝', '͞', 37 | '͟', '͠', '͢', '̸', 38 | '̷', '͡', ' ҉', 39 | ], 40 | }; 41 | var all = [].concat(soul.up, soul.down, soul.mid); 42 | 43 | function randomNumber(range) { 44 | var r = Math.floor(Math.random() * range); 45 | return r; 46 | } 47 | 48 | function isChar(character) { 49 | var bool = false; 50 | all.filter(function(i) { 51 | bool = (i === character); 52 | }); 53 | return bool; 54 | } 55 | 56 | 57 | function heComes(text, options) { 58 | var result = ''; 59 | var counts; 60 | var l; 61 | options = options || {}; 62 | options['up'] = 63 | typeof options['up'] !== 'undefined' ? options['up'] : true; 64 | options['mid'] = 65 | typeof options['mid'] !== 'undefined' ? options['mid'] : true; 66 | options['down'] = 67 | typeof options['down'] !== 'undefined' ? options['down'] : true; 68 | options['size'] = 69 | typeof options['size'] !== 'undefined' ? options['size'] : 'maxi'; 70 | text = text.split(''); 71 | for (l in text) { 72 | if (isChar(l)) { 73 | continue; 74 | } 75 | result = result + text[l]; 76 | counts = {'up': 0, 'down': 0, 'mid': 0}; 77 | switch (options.size) { 78 | case 'mini': 79 | counts.up = randomNumber(8); 80 | counts.mid = randomNumber(2); 81 | counts.down = randomNumber(8); 82 | break; 83 | case 'maxi': 84 | counts.up = randomNumber(16) + 3; 85 | counts.mid = randomNumber(4) + 1; 86 | counts.down = randomNumber(64) + 3; 87 | break; 88 | default: 89 | counts.up = randomNumber(8) + 1; 90 | counts.mid = randomNumber(6) / 2; 91 | counts.down = randomNumber(8) + 1; 92 | break; 93 | } 94 | 95 | var arr = ['up', 'mid', 'down']; 96 | for (var d in arr) { 97 | var index = arr[d]; 98 | for (var i = 0; i <= counts[index]; i++) { 99 | if (options[index]) { 100 | result = result + soul[index][randomNumber(soul[index].length)]; 101 | } 102 | } 103 | } 104 | } 105 | return result; 106 | } 107 | // don't summon him 108 | return heComes(text, options); 109 | }; 110 | 111 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Colors.js 1.2 2 | // Project: https://github.com/Marak/colors.js 3 | // Definitions by: Bart van der Schoor , Staffan Eketorp 4 | // Definitions: https://github.com/Marak/colors.js 5 | 6 | export interface Color { 7 | (text: string): string; 8 | 9 | strip: Color; 10 | stripColors: Color; 11 | 12 | black: Color; 13 | red: Color; 14 | green: Color; 15 | yellow: Color; 16 | blue: Color; 17 | magenta: Color; 18 | cyan: Color; 19 | white: Color; 20 | gray: Color; 21 | grey: Color; 22 | 23 | bgBlack: Color; 24 | bgRed: Color; 25 | bgGreen: Color; 26 | bgYellow: Color; 27 | bgBlue: Color; 28 | bgMagenta: Color; 29 | bgCyan: Color; 30 | bgWhite: Color; 31 | 32 | reset: Color; 33 | bold: Color; 34 | dim: Color; 35 | italic: Color; 36 | underline: Color; 37 | inverse: Color; 38 | hidden: Color; 39 | strikethrough: Color; 40 | 41 | rainbow: Color; 42 | zebra: Color; 43 | america: Color; 44 | trap: Color; 45 | random: Color; 46 | zalgo: Color; 47 | } 48 | 49 | export function enable(): void; 50 | export function disable(): void; 51 | export function setTheme(theme: any): void; 52 | 53 | export let enabled: boolean; 54 | 55 | export const strip: Color; 56 | export const stripColors: Color; 57 | 58 | export const black: Color; 59 | export const red: Color; 60 | export const green: Color; 61 | export const yellow: Color; 62 | export const blue: Color; 63 | export const magenta: Color; 64 | export const cyan: Color; 65 | export const white: Color; 66 | export const gray: Color; 67 | export const grey: Color; 68 | 69 | export const bgBlack: Color; 70 | export const bgRed: Color; 71 | export const bgGreen: Color; 72 | export const bgYellow: Color; 73 | export const bgBlue: Color; 74 | export const bgMagenta: Color; 75 | export const bgCyan: Color; 76 | export const bgWhite: Color; 77 | 78 | export const reset: Color; 79 | export const bold: Color; 80 | export const dim: Color; 81 | export const italic: Color; 82 | export const underline: Color; 83 | export const inverse: Color; 84 | export const hidden: Color; 85 | export const strikethrough: Color; 86 | 87 | export const rainbow: Color; 88 | export const zebra: Color; 89 | export const america: Color; 90 | export const trap: Color; 91 | export const random: Color; 92 | export const zalgo: Color; 93 | 94 | declare global { 95 | interface String { 96 | strip: string; 97 | stripColors: string; 98 | 99 | black: string; 100 | red: string; 101 | green: string; 102 | yellow: string; 103 | blue: string; 104 | magenta: string; 105 | cyan: string; 106 | white: string; 107 | gray: string; 108 | grey: string; 109 | 110 | bgBlack: string; 111 | bgRed: string; 112 | bgGreen: string; 113 | bgYellow: string; 114 | bgBlue: string; 115 | bgMagenta: string; 116 | bgCyan: string; 117 | bgWhite: string; 118 | 119 | reset: string; 120 | // @ts-ignore 121 | bold: string; 122 | dim: string; 123 | italic: string; 124 | underline: string; 125 | inverse: string; 126 | hidden: string; 127 | strikethrough: string; 128 | 129 | rainbow: string; 130 | zebra: string; 131 | america: string; 132 | trap: string; 133 | random: string; 134 | zalgo: string; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /lib/extendStringPrototype.js: -------------------------------------------------------------------------------- 1 | var colors = require('./colors'); 2 | 3 | module['exports'] = function() { 4 | // 5 | // Extends prototype of native string object to allow for "foo".red syntax 6 | // 7 | var addProperty = function(color, func) { 8 | String.prototype.__defineGetter__(color, func); 9 | }; 10 | 11 | addProperty('strip', function() { 12 | return colors.strip(this); 13 | }); 14 | 15 | addProperty('stripColors', function() { 16 | return colors.strip(this); 17 | }); 18 | 19 | addProperty('trap', function() { 20 | return colors.trap(this); 21 | }); 22 | 23 | addProperty('zalgo', function() { 24 | return colors.zalgo(this); 25 | }); 26 | 27 | addProperty('zebra', function() { 28 | return colors.zebra(this); 29 | }); 30 | 31 | addProperty('rainbow', function() { 32 | return colors.rainbow(this); 33 | }); 34 | 35 | addProperty('random', function() { 36 | return colors.random(this); 37 | }); 38 | 39 | addProperty('america', function() { 40 | return colors.america(this); 41 | }); 42 | 43 | // 44 | // Iterate through all default styles and colors 45 | // 46 | var x = Object.keys(colors.styles); 47 | x.forEach(function(style) { 48 | addProperty(style, function() { 49 | return colors.stylize(this, style); 50 | }); 51 | }); 52 | 53 | function applyTheme(theme) { 54 | // 55 | // Remark: This is a list of methods that exist 56 | // on String that you should not overwrite. 57 | // 58 | var stringPrototypeBlacklist = [ 59 | '__defineGetter__', '__defineSetter__', '__lookupGetter__', 60 | '__lookupSetter__', 'charAt', 'constructor', 'hasOwnProperty', 61 | 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 62 | 'valueOf', 'charCodeAt', 'indexOf', 'lastIndexOf', 'length', 63 | 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', 64 | 'split', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase', 65 | 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 66 | ]; 67 | 68 | Object.keys(theme).forEach(function(prop) { 69 | if (stringPrototypeBlacklist.indexOf(prop) !== -1) { 70 | console.log('warn: '.red + ('String.prototype' + prop).magenta + 71 | ' is probably something you don\'t want to override. ' + 72 | 'Ignoring style name'); 73 | } else { 74 | if (typeof(theme[prop]) === 'string') { 75 | colors[prop] = colors[theme[prop]]; 76 | addProperty(prop, function() { 77 | return colors[prop](this); 78 | }); 79 | } else { 80 | var themePropApplicator = function(str) { 81 | var ret = str || this; 82 | for (var t = 0; t < theme[prop].length; t++) { 83 | ret = colors[theme[prop][t]](ret); 84 | } 85 | return ret; 86 | }; 87 | addProperty(prop, themePropApplicator); 88 | colors[prop] = function(str) { 89 | return themePropApplicator(str); 90 | }; 91 | } 92 | } 93 | }); 94 | } 95 | 96 | colors.setTheme = function(theme) { 97 | if (typeof theme === 'string') { 98 | console.log('colors.setTheme now only accepts an object, not a string. ' + 99 | 'If you are trying to set a theme from a file, it is now your (the ' + 100 | 'caller\'s) responsibility to require the file. The old syntax ' + 101 | 'looked like colors.setTheme(__dirname + ' + 102 | '\'/../themes/generic-logging.js\'); The new syntax looks like '+ 103 | 'colors.setTheme(require(__dirname + ' + 104 | '\'/../themes/generic-logging.js\'));'); 105 | return; 106 | } else { 107 | applyTheme(theme); 108 | } 109 | }; 110 | }; 111 | -------------------------------------------------------------------------------- /lib/system/supports-colors.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) Sindre Sorhus (sindresorhus.com) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | */ 25 | 26 | 'use strict'; 27 | 28 | var os = require('os'); 29 | var hasFlag = require('./has-flag.js'); 30 | 31 | var env = process.env; 32 | 33 | var forceColor = void 0; 34 | if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) { 35 | forceColor = false; 36 | } else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true') 37 | || hasFlag('color=always')) { 38 | forceColor = true; 39 | } 40 | if ('FORCE_COLOR' in env) { 41 | forceColor = env.FORCE_COLOR.length === 0 42 | || parseInt(env.FORCE_COLOR, 10) !== 0; 43 | } 44 | 45 | function translateLevel(level) { 46 | if (level === 0) { 47 | return false; 48 | } 49 | 50 | return { 51 | level: level, 52 | hasBasic: true, 53 | has256: level >= 2, 54 | has16m: level >= 3, 55 | }; 56 | } 57 | 58 | function supportsColor(stream) { 59 | if (forceColor === false) { 60 | return 0; 61 | } 62 | 63 | if (hasFlag('color=16m') || hasFlag('color=full') 64 | || hasFlag('color=truecolor')) { 65 | return 3; 66 | } 67 | 68 | if (hasFlag('color=256')) { 69 | return 2; 70 | } 71 | 72 | if (stream && !stream.isTTY && forceColor !== true) { 73 | return 0; 74 | } 75 | 76 | var min = forceColor ? 1 : 0; 77 | 78 | if (process.platform === 'win32') { 79 | // Node.js 7.5.0 is the first version of Node.js to include a patch to 80 | // libuv that enables 256 color output on Windows. Anything earlier and it 81 | // won't work. However, here we target Node.js 8 at minimum as it is an LTS 82 | // release, and Node.js 7 is not. Windows 10 build 10586 is the first 83 | // Windows release that supports 256 colors. Windows 10 build 14931 is the 84 | // first release that supports 16m/TrueColor. 85 | var osRelease = os.release().split('.'); 86 | if (Number(process.versions.node.split('.')[0]) >= 8 87 | && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) { 88 | return Number(osRelease[2]) >= 14931 ? 3 : 2; 89 | } 90 | 91 | return 1; 92 | } 93 | 94 | if ('CI' in env) { 95 | if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) { 96 | return sign in env; 97 | }) || env.CI_NAME === 'codeship') { 98 | return 1; 99 | } 100 | 101 | return min; 102 | } 103 | 104 | if ('TEAMCITY_VERSION' in env) { 105 | return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0 106 | ); 107 | } 108 | 109 | if ('TERM_PROGRAM' in env) { 110 | var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); 111 | 112 | switch (env.TERM_PROGRAM) { 113 | case 'iTerm.app': 114 | return version >= 3 ? 3 : 2; 115 | case 'Hyper': 116 | return 3; 117 | case 'Apple_Terminal': 118 | return 2; 119 | // No default 120 | } 121 | } 122 | 123 | if (/-256(color)?$/i.test(env.TERM)) { 124 | return 2; 125 | } 126 | 127 | if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { 128 | return 1; 129 | } 130 | 131 | if ('COLORTERM' in env) { 132 | return 1; 133 | } 134 | 135 | if (env.TERM === 'dumb') { 136 | return min; 137 | } 138 | 139 | return min; 140 | } 141 | 142 | function getSupportLevel(stream) { 143 | var level = supportsColor(stream); 144 | return translateLevel(level); 145 | } 146 | 147 | module.exports = { 148 | supportsColor: getSupportLevel, 149 | stdout: getSupportLevel(process.stdout), 150 | stderr: getSupportLevel(process.stderr), 151 | }; 152 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # colors.js 2 | [![Build Status](https://travis-ci.org/Marak/colors.js.svg?branch=master)](https://travis-ci.org/Marak/colors.js) 3 | [![version](https://img.shields.io/npm/v/colors.svg)](https://www.npmjs.org/package/colors) 4 | [![dependencies](https://david-dm.org/Marak/colors.js.svg)](https://david-dm.org/Marak/colors.js) 5 | [![devDependencies](https://david-dm.org/Marak/colors.js/dev-status.svg)](https://david-dm.org/Marak/colors.js#info=devDependencies) 6 | 7 | Please check out the [roadmap](ROADMAP.md) for upcoming features and releases. Please open Issues to provide feedback, and check the `develop` branch for the latest bleeding-edge updates. 8 | 9 | ## get color and style in your node.js console 10 | 11 | ![Demo](https://raw.githubusercontent.com/Marak/colors.js/master/screenshots/colors.png) 12 | 13 | ## Installation 14 | 15 | npm install colors 16 | 17 | ## colors and styles! 18 | 19 | ### text colors 20 | 21 | - black 22 | - red 23 | - green 24 | - yellow 25 | - blue 26 | - magenta 27 | - cyan 28 | - white 29 | - gray 30 | - grey 31 | 32 | ### bright text colors 33 | 34 | - brightRed 35 | - brightGreen 36 | - brightYellow 37 | - brightBlue 38 | - brightMagenta 39 | - brightCyan 40 | - brightWhite 41 | 42 | ### background colors 43 | 44 | - bgBlack 45 | - bgRed 46 | - bgGreen 47 | - bgYellow 48 | - bgBlue 49 | - bgMagenta 50 | - bgCyan 51 | - bgWhite 52 | - bgGray 53 | - bgGrey 54 | 55 | ### bright background colors 56 | 57 | - bgBrightRed 58 | - bgBrightGreen 59 | - bgBrightYellow 60 | - bgBrightBlue 61 | - bgBrightMagenta 62 | - bgBrightCyan 63 | - bgBrightWhite 64 | 65 | ### styles 66 | 67 | - reset 68 | - bold 69 | - dim 70 | - italic 71 | - underline 72 | - inverse 73 | - hidden 74 | - strikethrough 75 | 76 | ### extras 77 | 78 | - rainbow 79 | - zebra 80 | - america 81 | - trap 82 | - random 83 | 84 | 85 | ## Usage 86 | 87 | By popular demand, `colors` now ships with two types of usages! 88 | 89 | The super nifty way 90 | 91 | ```js 92 | var colors = require('colors'); 93 | 94 | console.log('hello'.green); // outputs green text 95 | console.log('i like cake and pies'.underline.red); // outputs red underlined text 96 | console.log('inverse the color'.inverse); // inverses the color 97 | console.log('OMG Rainbows!'.rainbow); // rainbow 98 | console.log('Run the trap'.trap); // Drops the bass 99 | 100 | ``` 101 | 102 | or a slightly less nifty way which doesn't extend `String.prototype` 103 | 104 | ```js 105 | var colors = require('colors/safe'); 106 | 107 | console.log(colors.green('hello')); // outputs green text 108 | console.log(colors.red.underline('i like cake and pies')); // outputs red underlined text 109 | console.log(colors.inverse('inverse the color')); // inverses the color 110 | console.log(colors.rainbow('OMG Rainbows!')); // rainbow 111 | console.log(colors.trap('Run the trap')); // Drops the bass 112 | 113 | ``` 114 | 115 | I prefer the first way. Some people seem to be afraid of extending `String.prototype` and prefer the second way. 116 | 117 | If you are writing good code you will never have an issue with the first approach. If you really don't want to touch `String.prototype`, the second usage will not touch `String` native object. 118 | 119 | ## Enabling/Disabling Colors 120 | 121 | The package will auto-detect whether your terminal can use colors and enable/disable accordingly. When colors are disabled, the color functions do nothing. You can override this with a command-line flag: 122 | 123 | ```bash 124 | node myapp.js --no-color 125 | node myapp.js --color=false 126 | 127 | node myapp.js --color 128 | node myapp.js --color=true 129 | node myapp.js --color=always 130 | 131 | FORCE_COLOR=1 node myapp.js 132 | ``` 133 | 134 | Or in code: 135 | 136 | ```javascript 137 | var colors = require('colors'); 138 | colors.enable(); 139 | colors.disable(); 140 | ``` 141 | 142 | ## Console.log [string substitution](http://nodejs.org/docs/latest/api/console.html#console_console_log_data) 143 | 144 | ```js 145 | var name = 'Marak'; 146 | console.log(colors.green('Hello %s'), name); 147 | // outputs -> 'Hello Marak' 148 | ``` 149 | 150 | ## Custom themes 151 | 152 | ### Using standard API 153 | 154 | ```js 155 | 156 | var colors = require('colors'); 157 | 158 | colors.setTheme({ 159 | silly: 'rainbow', 160 | input: 'grey', 161 | verbose: 'cyan', 162 | prompt: 'grey', 163 | info: 'green', 164 | data: 'grey', 165 | help: 'cyan', 166 | warn: 'yellow', 167 | debug: 'blue', 168 | error: 'red' 169 | }); 170 | 171 | // outputs red text 172 | console.log("this is an error".error); 173 | 174 | // outputs yellow text 175 | console.log("this is a warning".warn); 176 | ``` 177 | 178 | ### Using string safe API 179 | 180 | ```js 181 | var colors = require('colors/safe'); 182 | 183 | // set single property 184 | var error = colors.red; 185 | error('this is red'); 186 | 187 | // set theme 188 | colors.setTheme({ 189 | silly: 'rainbow', 190 | input: 'grey', 191 | verbose: 'cyan', 192 | prompt: 'grey', 193 | info: 'green', 194 | data: 'grey', 195 | help: 'cyan', 196 | warn: 'yellow', 197 | debug: 'blue', 198 | error: 'red' 199 | }); 200 | 201 | // outputs red text 202 | console.log(colors.error("this is an error")); 203 | 204 | // outputs yellow text 205 | console.log(colors.warn("this is a warning")); 206 | 207 | ``` 208 | 209 | ### Combining Colors 210 | 211 | ```javascript 212 | var colors = require('colors'); 213 | 214 | colors.setTheme({ 215 | custom: ['red', 'underline'] 216 | }); 217 | 218 | console.log('test'.custom); 219 | ``` 220 | 221 | *Protip: There is a secret undocumented style in `colors`. If you find the style you can summon him.* 222 | -------------------------------------------------------------------------------- /lib/colors.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Original Library 6 | - Copyright (c) Marak Squires 7 | 8 | Additional functionality 9 | - Copyright (c) Sindre Sorhus (sindresorhus.com) 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in 19 | all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | THE SOFTWARE. 28 | 29 | */ 30 | 31 | var colors = {}; 32 | module['exports'] = colors; 33 | 34 | colors.themes = {}; 35 | 36 | var util = require('util'); 37 | var ansiStyles = colors.styles = require('./styles'); 38 | var defineProps = Object.defineProperties; 39 | var newLineRegex = new RegExp(/[\r\n]+/g); 40 | 41 | colors.supportsColor = require('./system/supports-colors').supportsColor; 42 | 43 | if (typeof colors.enabled === 'undefined') { 44 | colors.enabled = colors.supportsColor() !== false; 45 | } 46 | 47 | colors.enable = function() { 48 | colors.enabled = true; 49 | }; 50 | 51 | colors.disable = function() { 52 | colors.enabled = false; 53 | }; 54 | 55 | colors.stripColors = colors.strip = function(str) { 56 | return ('' + str).replace(/\x1B\[\d+m/g, ''); 57 | }; 58 | 59 | // eslint-disable-next-line no-unused-vars 60 | var stylize = colors.stylize = function stylize(str, style) { 61 | if (!colors.enabled) { 62 | return str+''; 63 | } 64 | 65 | var styleMap = ansiStyles[style]; 66 | 67 | // Stylize should work for non-ANSI styles, too 68 | if(!styleMap && style in colors){ 69 | // Style maps like trap operate as functions on strings; 70 | // they don't have properties like open or close. 71 | return colors[style](str); 72 | } 73 | 74 | return styleMap.open + str + styleMap.close; 75 | }; 76 | 77 | var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; 78 | var escapeStringRegexp = function(str) { 79 | if (typeof str !== 'string') { 80 | throw new TypeError('Expected a string'); 81 | } 82 | return str.replace(matchOperatorsRe, '\\$&'); 83 | }; 84 | 85 | function build(_styles) { 86 | var builder = function builder() { 87 | return applyStyle.apply(builder, arguments); 88 | }; 89 | builder._styles = _styles; 90 | // __proto__ is used because we must return a function, but there is 91 | // no way to create a function with a different prototype. 92 | builder.__proto__ = proto; 93 | return builder; 94 | } 95 | 96 | var styles = (function() { 97 | var ret = {}; 98 | ansiStyles.grey = ansiStyles.gray; 99 | Object.keys(ansiStyles).forEach(function(key) { 100 | ansiStyles[key].closeRe = 101 | new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); 102 | ret[key] = { 103 | get: function() { 104 | return build(this._styles.concat(key)); 105 | }, 106 | }; 107 | }); 108 | return ret; 109 | })(); 110 | 111 | var proto = defineProps(function colors() {}, styles); 112 | 113 | function applyStyle() { 114 | var args = Array.prototype.slice.call(arguments); 115 | 116 | var str = args.map(function(arg) { 117 | // Use weak equality check so we can colorize null/undefined in safe mode 118 | if (arg != null && arg.constructor === String) { 119 | return arg; 120 | } else { 121 | return util.inspect(arg); 122 | } 123 | }).join(' '); 124 | 125 | if (!colors.enabled || !str) { 126 | return str; 127 | } 128 | 129 | var newLinesPresent = str.indexOf('\n') != -1; 130 | 131 | var nestedStyles = this._styles; 132 | 133 | var i = nestedStyles.length; 134 | while (i--) { 135 | var code = ansiStyles[nestedStyles[i]]; 136 | str = code.open + str.replace(code.closeRe, code.open) + code.close; 137 | if (newLinesPresent) { 138 | str = str.replace(newLineRegex, function(match) { 139 | return code.close + match + code.open; 140 | }); 141 | } 142 | } 143 | 144 | return str; 145 | } 146 | 147 | colors.setTheme = function(theme) { 148 | if (typeof theme === 'string') { 149 | console.log('colors.setTheme now only accepts an object, not a string. ' + 150 | 'If you are trying to set a theme from a file, it is now your (the ' + 151 | 'caller\'s) responsibility to require the file. The old syntax ' + 152 | 'looked like colors.setTheme(__dirname + ' + 153 | '\'/../themes/generic-logging.js\'); The new syntax looks like '+ 154 | 'colors.setTheme(require(__dirname + ' + 155 | '\'/../themes/generic-logging.js\'));'); 156 | return; 157 | } 158 | for (var style in theme) { 159 | (function(style) { 160 | colors[style] = function(str) { 161 | if (typeof theme[style] === 'object') { 162 | var out = str; 163 | for (var i in theme[style]) { 164 | out = colors[theme[style][i]](out); 165 | } 166 | return out; 167 | } 168 | return colors[theme[style]](str); 169 | }; 170 | })(style); 171 | } 172 | }; 173 | 174 | function init() { 175 | var ret = {}; 176 | Object.keys(styles).forEach(function(name) { 177 | ret[name] = { 178 | get: function() { 179 | return build([name]); 180 | }, 181 | }; 182 | }); 183 | return ret; 184 | } 185 | 186 | var sequencer = function sequencer(map, str) { 187 | var exploded = str.split(''); 188 | exploded = exploded.map(map); 189 | return exploded.join(''); 190 | }; 191 | 192 | // custom formatter methods 193 | colors.trap = require('./custom/trap'); 194 | colors.zalgo = require('./custom/zalgo'); 195 | 196 | // maps 197 | colors.maps = {}; 198 | colors.maps.america = require('./maps/america')(colors); 199 | colors.maps.zebra = require('./maps/zebra')(colors); 200 | colors.maps.rainbow = require('./maps/rainbow')(colors); 201 | colors.maps.random = require('./maps/random')(colors); 202 | 203 | for (var map in colors.maps) { 204 | (function(map) { 205 | colors[map] = function(str) { 206 | return sequencer(colors.maps[map], str); 207 | }; 208 | })(map); 209 | } 210 | 211 | defineProps(colors, init()); 212 | --------------------------------------------------------------------------------