Repository: chalk/chalk
Pull request #315 (2018-12-21 14:23:13)

Update docs for `FORCE_COLOR` environment variable
Copy the new [documentation](https://github.com/chalk/supports-color/commit/eedbbbda11e4f773a0c7bec454ac68c355584688) of supports-color




Patch:
diff --git a/.flowconfig b/.flowconfig
deleted file mode 100644
index 2318f0d..0000000
--- a/.flowconfig
+++ /dev/null
@@ -1,5 +0,0 @@
-[ignore]
-.*/node_modules/.*
-
-[options]
-suppress_comment= \\(.\\|\n\\)*\\$ExpectError
diff --git a/.github/funding.yml b/.github/funding.yml
new file mode 100644
index 0000000..baa12cf
--- /dev/null
+++ b/.github/funding.yml
@@ -0,0 +1,5 @@
+github: sindresorhus
+open_collective: sindresorhus
+patreon: sindresorhus
+tidelift: npm/chalk
+custom: https://sindresorhus.com/donate
diff --git a/.github/security.md b/.github/security.md
new file mode 100644
index 0000000..5358dc5
--- /dev/null
+++ b/.github/security.md
@@ -0,0 +1,3 @@
+# Security Policy
+
+To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
diff --git a/.travis.yml b/.travis.yml
index 60e38d8..1492647 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,7 @@
 language: node_js
 node_js:
+  - '12'
+  - '10'
   - '8'
-  - '6'
 after_success:
   - './node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls'
diff --git a/benchmark.js b/benchmark.js
index f4e9cf3..dc24696 100644
--- a/benchmark.js
+++ b/benchmark.js
@@ -3,22 +3,48 @@
 const chalk = require('.');
 
 suite('chalk', () => {
-	set('iterations', 100000);
+	set('iterations', 1000000);
 
-	bench('single style', () => {
+	const chalkRed = chalk.red;
+	const chalkBgRed = chalk.bgRed;
+	const chalkBlueBgRed = chalk.blue.bgRed;
+	const chalkBlueBgRedBold = chalk.blue.bgRed.bold;
+
+	const blueStyledString = 'the fox jumps' + chalk.blue('over the lazy dog') + '!';
+
+	bench('1 style', () => {
 		chalk.red('the fox jumps over the lazy dog');
 	});
 
-	bench('several styles', () => {
+	bench('2 styles', () => {
+		chalk.blue.bgRed('the fox jumps over the lazy dog');
+	});
+
+	bench('3 styles', () => {
 		chalk.blue.bgRed.bold('the fox jumps over the lazy dog');
 	});
 
-	const cached = chalk.blue.bgRed.bold;
-	bench('cached styles', () => {
-		cached('the fox jumps over the lazy dog');
+	bench('cached: 1 style', () => {
+		chalkRed('the fox jumps over the lazy dog');
+	});
+
+	bench('cached: 2 styles', () => {
+		chalkBlueBgRed('the fox jumps over the lazy dog');
+	});
+
+	bench('cached: 3 styles', () => {
+		chalkBlueBgRedBold('the fox jumps over the lazy dog');
+	});
+
+	bench('cached: 1 style with newline', () => {
+		chalkRed('the fox jumps\nover the lazy dog');
+	});
+
+	bench('cached: 1 style nested intersecting', () => {
+		chalkRed(blueStyledString);
 	});
 
-	bench('nested styles', () => {
-		chalk.red('the fox jumps', chalk.underline.bgBlue('over the lazy dog') + '!');
+	bench('cached: 1 style nested non-intersecting', () => {
+		chalkBgRed(blueStyledString);
 	});
 });
diff --git a/examples/rainbow.js b/examples/rainbow.js
index fc086fa..813e026 100644
--- a/examples/rainbow.js
+++ b/examples/rainbow.js
@@ -3,36 +3,39 @@ const chalk = require('..');
 
 const ignoreChars = /[^!-~]/g;
 
-function rainbow(str, offset) {
-	if (!str || str.length === 0) {
-		return str;
+const delay = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
+
+function rainbow(string, offset) {
+	if (!string || string.length === 0) {
+		return string;
 	}
 
-	const hueStep = 360 / str.replace(ignoreChars, '').length;
+	const hueStep = 360 / string.replace(ignoreChars, '').length;
 
 	let hue = offset % 360;
-	const chars = [];
-	for (const c of str) {
-		if (c.match(ignoreChars)) {
-			chars.push(c);
+	const characters = [];
+	for (const character of string) {
+		if (character.match(ignoreChars)) {
+			characters.push(character);
 		} else {
-			chars.push(chalk.hsl(hue, 100, 50)(c));
+			characters.push(chalk.hsl(hue, 100, 50)(character));
 			hue = (hue + hueStep) % 360;
 		}
 	}
 
-	return chars.join('');
+	return characters.join('');
 }
 
-const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
-
-async function animateString(str) {
+async function animateString(string) {
 	console.log();
 	for (let i = 0; i < 360 * 5; i++) {
-		console.log('\u001B[1F\u001B[G ', rainbow(str, i));
-		await sleep(2); // eslint-disable-line no-await-in-loop
+		console.log('\u001B[1F\u001B[G', rainbow(string, i));
+		await delay(2); // eslint-disable-line no-await-in-loop
 	}
 }
 
-console.log();
-animateString('We hope you enjoy the new version of Chalk 2! <3').then(() => console.log());
+(async () => {
+	console.log();
+	await animateString('We hope you enjoy Chalk! <3');
+	console.log();
+})();
diff --git a/examples/screenshot.js b/examples/screenshot.js
index 7d195a6..37f5850 100644
--- a/examples/screenshot.js
+++ b/examples/screenshot.js
@@ -1,6 +1,6 @@
 'use strict';
-const chalk = require('..');
 const styles = require('ansi-styles');
+const chalk = require('..');
 
 // Generates screenshot
 for (const key of Object.keys(styles)) {
diff --git a/index.d.ts b/index.d.ts
new file mode 100644
index 0000000..0f5d885
--- /dev/null
+++ b/index.d.ts
@@ -0,0 +1,303 @@
+declare const enum LevelEnum {
+	/**
+	All colors disabled.
+	*/
+	None = 0,
+
+	/**
+	Basic 16 colors support.
+	*/
+	Basic = 1,
+
+	/**
+	ANSI 256 colors support.
+	*/
+	Ansi256 = 2,
+
+	/**
+	Truecolor 16 million colors support.
+	*/
+	TrueColor = 3
+}
+
+declare namespace chalk {
+	type Level = LevelEnum;
+
+	interface Options {
+		/**
+		Enable or disable Chalk.
+
+		@default true
+		*/
+		enabled?: boolean;
+
+		/**
+		Specify the color support for Chalk.
+		By default, color support is automatically detected based on the environment.
+		*/
+		level?: Level;
+	}
+
+	interface Instance {
+		/**
+		Return a new Chalk instance.
+		*/
+		new (options?: Options): Chalk;
+	}
+
+	/**
+	Detect whether the terminal supports color.
+	*/
+	interface ColorSupport {
+		/**
+		The color level used by Chalk.
+		*/
+		level: Level;
+
+		/**
+		Return whether Chalk supports basic 16 colors.
+		*/
+		hasBasic: boolean;
+
+		/**
+		Return whether Chalk supports ANSI 256 colors.
+		*/
+		has256: boolean;
+
+		/**
+		Return whether Chalk supports Truecolor 16 million colors.
+		*/
+		has16m: boolean;
+	}
+
+	interface ChalkFunction {
+		/**
+		Use a template string.
+
+		@remarks Template literals are unsupported for nested calls (see [issue #341](https://github.com/chalk/chalk/issues/341))
+
+		@example
+		```
+		log(chalk`
+		CPU: {red ${cpu.totalPercent}%}
+		RAM: {green ${ram.used / ram.total * 100}%}
+		DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
+		`);
+		```
+		*/
+		(text: TemplateStringsArray, ...placeholders: unknown[]): string;
+
+		(...text: unknown[]): string;
+	}
+
+	interface Chalk extends ChalkFunction {
+		/**
+		Return a new Chalk instance.
+		*/
+		Instance: Instance;
+
+		/**
+		Enable or disable Chalk.
+
+		@default true
+		*/
+		enabled: boolean;
+
+		/**
+		The color support for Chalk.
+		By default, color support is automatically detected based on the environment.
+		*/
+		level: Level;
+
+		/**
+		Use HEX value to set text color.
+
+		@param color - Hexadecimal value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.hex('#DEADED');
+		```
+		*/
+		hex(color: string): Chalk;
+
+		/**
+		Use keyword color value to set text color.
+
+		@param color - Keyword value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.keyword('orange');
+		```
+		*/
+		keyword(color: string): Chalk;
+
+		/**
+		Use RGB values to set text color.
+		*/
+		rgb(red: number, green: number, blue: number): Chalk;
+
+		/**
+		Use HSL values to set text color.
+		*/
+		hsl(hue: number, saturation: number, lightness: number): Chalk;
+
+		/**
+		Use HSV values to set text color.
+		*/
+		hsv(hue: number, saturation: number, value: number): Chalk;
+
+		/**
+		Use HWB values to set text color.
+		*/
+		hwb(hue: number, whiteness: number, blackness: number): Chalk;
+
+		/**
+		Use HEX value to set background color.
+
+		@param color - Hexadecimal value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.bgHex('#DEADED');
+		```
+		*/
+		bgHex(color: string): Chalk;
+
+		/**
+		Use keyword color value to set background color.
+
+		@param color - Keyword value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.bgKeyword('orange');
+		```
+		*/
+		bgKeyword(color: string): Chalk;
+
+		/**
+		Use RGB values to set background color.
+		*/
+		bgRgb(red: number, green: number, blue: number): Chalk;
+
+		/**
+		Use HSL values to set background color.
+		*/
+		bgHsl(hue: number, saturation: number, lightness: number): Chalk;
+
+		/**
+		Use HSV values to set background color.
+		*/
+		bgHsv(hue: number, saturation: number, value: number): Chalk;
+
+		/**
+		Use HWB values to set background color.
+		*/
+		bgHwb(hue: number, whiteness: number, blackness: number): Chalk;
+
+		/**
+		Modifier: Resets the current color chain.
+		*/
+		readonly reset: Chalk;
+
+		/**
+		Modifier: Make text bold.
+		*/
+		readonly bold: Chalk;
+
+		/**
+		Modifier: Emitting only a small amount of light.
+		*/
+		readonly dim: Chalk;
+
+		/**
+		Modifier: Make text italic. (Not widely supported)
+		*/
+		readonly italic: Chalk;
+
+		/**
+		Modifier: Make text underline. (Not widely supported)
+		*/
+		readonly underline: Chalk;
+
+		/**
+		Modifier: Inverse background and foreground colors.
+		*/
+		readonly inverse: Chalk;
+
+		/**
+		Modifier: Prints the text, but makes it invisible.
+		*/
+		readonly hidden: Chalk;
+
+		/**
+		Modifier: Puts a horizontal line through the center of the text. (Not widely supported)
+		*/
+		readonly strikethrough: Chalk;
+
+		/**
+		Modifier: Prints the text only when Chalk is enabled.
+		Can be useful for things that are purely cosmetic.
+		*/
+		readonly visible: Chalk;
+
+		readonly black: Chalk;
+		readonly red: Chalk;
+		readonly green: Chalk;
+		readonly yellow: Chalk;
+		readonly blue: Chalk;
+		readonly magenta: Chalk;
+		readonly cyan: Chalk;
+		readonly white: Chalk;
+		readonly gray: Chalk;
+		readonly grey: Chalk;
+		readonly blackBright: Chalk;
+		readonly redBright: Chalk;
+		readonly greenBright: Chalk;
+		readonly yellowBright: Chalk;
+		readonly blueBright: Chalk;
+		readonly magentaBright: Chalk;
+		readonly cyanBright: Chalk;
+		readonly whiteBright: Chalk;
+
+		readonly bgBlack: Chalk;
+		readonly bgRed: Chalk;
+		readonly bgGreen: Chalk;
+		readonly bgYellow: Chalk;
+		readonly bgBlue: Chalk;
+		readonly bgMagenta: Chalk;
+		readonly bgCyan: Chalk;
+		readonly bgWhite: Chalk;
+		readonly bgBlackBright: Chalk;
+		readonly bgRedBright: Chalk;
+		readonly bgGreenBright: Chalk;
+		readonly bgYellowBright: Chalk;
+		readonly bgBlueBright: Chalk;
+		readonly bgMagentaBright: Chalk;
+		readonly bgCyanBright: Chalk;
+		readonly bgWhiteBright: Chalk;
+	}
+}
+
+/**
+Main Chalk object that allows to chain styles together.
+Call the last one as a method with a string argument.
+Order doesn't matter, and later styles take precedent in case of a conflict.
+This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
+*/
+declare const chalk: chalk.Chalk & chalk.ChalkFunction & {
+	supportsColor: chalk.ColorSupport | false;
+	Level: typeof LevelEnum;
+};
+
+export = chalk;
diff --git a/index.js b/index.js
index 917c45f..21d3a83 100644
--- a/index.js
+++ b/index.js
@@ -1,74 +1,83 @@
 'use strict';
-const escapeStringRegexp = require('escape-string-regexp');
 const ansiStyles = require('ansi-styles');
-const stdoutColor = require('supports-color').stdout;
-
+const {stdout: stdoutColor} = require('supports-color');
 const template = require('./templates.js');
 
-const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
+const {
+	stringReplaceAll,
+	stringEncaseCRLFWithFirstIndex
+} = require('./lib/util');
 
 // `supportsColor.level` → `ansiStyles.color[name]` mapping
-const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m'];
+const levelMapping = [
+	'ansi',
+	'ansi',
+	'ansi256',
+	'ansi16m'
+];
 
 // `color-convert` models to exclude from the Chalk API due to conflicts and such
 const skipModels = new Set(['gray']);
 
 const styles = Object.create(null);
 
-function applyOptions(obj, options = {}) {
+const applyOptions = (object, options = {}) => {
 	if (options.level > 3 || options.level < 0) {
 		throw new Error('The `level` option should be an integer from 0 to 3');
 	}
 
 	// Detect level if not set manually
-	const scLevel = stdoutColor ? stdoutColor.level : 0;
-	obj.level = options.level === undefined ? scLevel : options.level;
-	obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0;
+	const colorLevel = stdoutColor ? stdoutColor.level : 0;
+	object.level = options.level === undefined ? colorLevel : options.level;
+	object.enabled = 'enabled' in options ? options.enabled : object.level > 0;
+};
+
+class ChalkClass {
+	constructor(options) {
+		return chalkFactory(options);
+	}
 }
 
-function Chalk(options) {
-	// We check for this.template here since calling `chalk.constructor()`
-	// by itself will have a `this` of a previously constructed chalk object
-	if (!this || !(this instanceof Chalk) || this.template) {
-		const chalk = {};
-		applyOptions(chalk, options);
+const chalkFactory = options => {
+	const chalk = {};
+	applyOptions(chalk, options);
 
-		chalk.template = (...args) => chalkTag(...[chalk.template].concat(args));
+	chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
 
-		Object.setPrototypeOf(chalk, Chalk.prototype);
-		Object.setPrototypeOf(chalk.template, chalk);
+	Object.setPrototypeOf(chalk, Chalk.prototype);
+	Object.setPrototypeOf(chalk.template, chalk);
 
-		chalk.template.constructor = Chalk;
+	chalk.template.constructor = () => {
+		throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
+	};
 
-		return chalk.template;
-	}
+	chalk.template.Instance = ChalkClass;
 
-	applyOptions(this, options);
-}
+	return chalk.template;
+};
 
-// Use bright blue on Windows as the normal blue color is illegible
-if (isSimpleWindowsTerm) {
-	ansiStyles.blue.open = '\u001B[94m';
+function Chalk(options) {
+	return chalkFactory(options);
 }
 
-for (const key of Object.keys(ansiStyles)) {
-	ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
-
-	styles[key] = {
+for (const [styleName, style] of Object.entries(ansiStyles)) {
+	styles[styleName] = {
 		get() {
-			const codes = ansiStyles[key];
-			return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key);
+			const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
+			Object.defineProperty(this, styleName, {value: builder});
+			return builder;
 		}
 	};
 }
 
 styles.visible = {
 	get() {
-		return build.call(this, this._styles || [], true, 'visible');
+		const builder = createBuilder(this, this._styler, true);
+		Object.defineProperty(this, 'visible', {value: builder});
+		return builder;
 	}
 };
 
-ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g');
 for (const model of Object.keys(ansiStyles.color.ansi)) {
 	if (skipModels.has(model)) {
 		continue;
@@ -77,20 +86,14 @@ for (const model of Object.keys(ansiStyles.color.ansi)) {
 	styles[model] = {
 		get() {
 			const {level} = this;
-			return function (...args) {
-				const open = ansiStyles.color[levelMapping[level]][model](...args);
-				const codes = {
-					open,
-					close: ansiStyles.color.close,
-					closeRe: ansiStyles.color.closeRe
-				};
-				return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
+			return function (...arguments_) {
+				const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
+				return createBuilder(this, styler, this._isEmpty);
 			};
 		}
 	};
 }
 
-ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g');
 for (const model of Object.keys(ansiStyles.bgColor.ansi)) {
 	if (skipModels.has(model)) {
 		continue;
@@ -100,106 +103,111 @@ for (const model of Object.keys(ansiStyles.bgColor.ansi)) {
 	styles[bgModel] = {
 		get() {
 			const {level} = this;
-			return function (...args) {
-				const open = ansiStyles.bgColor[levelMapping[level]][model](...args);
-				const codes = {
-					open,
-					close: ansiStyles.bgColor.close,
-					closeRe: ansiStyles.bgColor.closeRe
-				};
-				return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
+			return function (...arguments_) {
+				const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
+				return createBuilder(this, styler, this._isEmpty);
 			};
 		}
 	};
 }
 
-const proto = Object.defineProperties(() => {}, styles);
-
-function build(_styles, _empty, key) {
-	const builder = (...args) => applyStyle.call(builder, ...args);
-	builder._styles = _styles;
-	builder._empty = _empty;
-
-	const self = this;
-
-	Object.defineProperty(builder, 'level', {
+const proto = Object.defineProperties(() => {}, {
+	...styles,
+	level: {
 		enumerable: true,
 		get() {
-			return self.level;
+			return this._generator.level;
 		},
 		set(level) {
-			self.level = level;
+			this._generator.level = level;
 		}
-	});
-
-	Object.defineProperty(builder, 'enabled', {
+	},
+	enabled: {
 		enumerable: true,
 		get() {
-			return self.enabled;
+			return this._generator.enabled;
 		},
 		set(enabled) {
-			self.enabled = enabled;
+			this._generator.enabled = enabled;
 		}
-	});
+	}
+});
+
+const createStyler = (open, close, parent) => {
+	let openAll;
+	let closeAll;
+	if (parent === undefined) {
+		openAll = open;
+		closeAll = close;
+	} else {
+		openAll = parent.openAll + open;
+		closeAll = close + parent.closeAll;
+	}
 
-	// See below for fix regarding invisible grey/dim combination on Windows
-	builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey';
+	return {
+		open,
+		close,
+		openAll,
+		closeAll,
+		parent
+	};
+};
+
+const createBuilder = (self, _styler, _isEmpty) => {
+	const builder = (...arguments_) => {
+		// Single argument is hot path, implicit coercion is faster than anything
+		// eslint-disable-next-line no-implicit-coercion
+		return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
+	};
 
 	// `__proto__` is used because we must return a function, but there is
 	// no way to create a function with a different prototype
 	builder.__proto__ = proto; // eslint-disable-line no-proto
 
-	return builder;
-}
+	builder._generator = self;
+	builder._styler = _styler;
+	builder._isEmpty = _isEmpty;
 
-function applyStyle(...args) {
-	// Support varags, but simply cast to string in case there's only one arg
-	const argsLen = args.length;
-	let str = String(args[0]);
+	return builder;
+};
 
-	if (argsLen === 0) {
-		return '';
+const applyStyle = (self, string) => {
+	if (!self.enabled || self.level <= 0 || !string) {
+		return self._isEmpty ? '' : string;
 	}
 
-	if (argsLen > 1) {
-		// Don't slice `arguments`, it prevents V8 optimizations
-		for (let a = 1; a < argsLen; a++) {
-			str += ' ' + args[a];
-		}
-	}
+	let styler = self._styler;
 
-	if (!this.enabled || this.level <= 0 || !str) {
-		return this._empty ? '' : str;
+	if (styler === undefined) {
+		return string;
 	}
 
-	// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
-	// see https://github.com/chalk/chalk/issues/58
-	// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
-	const originalDim = ansiStyles.dim.open;
-	if (isSimpleWindowsTerm && this.hasGrey) {
-		ansiStyles.dim.open = '';
-	}
-
-	for (const code of this._styles.slice().reverse()) {
-		// Replace any instances already present with a re-opening code
-		// otherwise only the part of the string until said closing code
-		// will be colored, and the rest will simply be 'plain'.
-		str = code.open + str.replace(code.closeRe, code.open) + code.close;
+	const {openAll, closeAll} = styler;
+	if (string.indexOf('\u001B') !== -1) {
+		while (styler !== undefined) {
+			// Replace any instances already present with a re-opening code
+			// otherwise only the part of the string until said closing code
+			// will be colored, and the rest will simply be 'plain'.
+			string = stringReplaceAll(string, styler.close, styler.open);
 
-		// Close the styling before a linebreak and reopen
-		// after next line to fix a bleed issue on macOS
-		// https://github.com/chalk/chalk/pull/92
-		str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`);
+			styler = styler.parent;
+		}
 	}
 
-	// Reset the original `dim` if we changed it to work around the Windows dimmed gray issue
-	ansiStyles.dim.open = originalDim;
+	// We can move both next actions out of loop, because remaining actions in loop won't have any/visible effect on parts we add here
+	// Close the styling before a linebreak and reopen
+	// after next line to fix a bleed issue on macOS
+	// https://github.com/chalk/chalk/pull/92
+	const lfIndex = string.indexOf('\n');
+	if (lfIndex !== -1) {
+		string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
+	}
 
-	return str;
-}
+	return openAll + string + closeAll;
+};
 
-function chalkTag(chalk, ...strings) {
-	const firstString = strings[0];
+const chalkTag = (chalk, ...strings) => {
+	const [firstString] = strings;
 
 	if (!Array.isArray(firstString)) {
 		// If chalk() was called by itself or with a string,
@@ -207,19 +215,20 @@ function chalkTag(chalk, ...strings) {
 		return strings.join(' ');
 	}
 
-	const args = strings.slice(1);
+	const arguments_ = strings.slice(1);
 	const parts = [firstString.raw[0]];
 
 	for (let i = 1; i < firstString.length; i++) {
-		parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&'));
-		parts.push(String(firstString.raw[i]));
+		parts.push(
+			String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
+			String(firstString.raw[i])
+		);
 	}
 
 	return template(chalk, parts.join(''));
-}
+};
 
 Object.defineProperties(Chalk.prototype, styles);
 
 module.exports = Chalk(); // eslint-disable-line new-cap
 module.exports.supportsColor = stdoutColor;
-module.exports.default = module.exports; // For TypeScript
diff --git a/index.js.flow b/index.js.flow
deleted file mode 100644
index 622caaa..0000000
--- a/index.js.flow
+++ /dev/null
@@ -1,93 +0,0 @@
-// @flow strict
-
-type TemplateStringsArray = $ReadOnlyArray<string>;
-
-export type Level = $Values<{
-	None: 0,
-	Basic: 1,
-	Ansi256: 2,
-	TrueColor: 3
-}>;
-
-export type ChalkOptions = {|
-	enabled?: boolean,
-	level?: Level
-|};
-
-export type ColorSupport = {|
-	level: Level,
-	hasBasic: boolean,
-	has256: boolean,
-	has16m: boolean
-|};
-
-export interface Chalk {
-	(...text: string[]): string,
-	(text: TemplateStringsArray, ...placeholders: string[]): string,
-	constructor(options?: ChalkOptions): Chalk,
-	enabled: boolean,
-	level: Level,
-	rgb(r: number, g: number, b: number): Chalk,
-	hsl(h: number, s: number, l: number): Chalk,
-	hsv(h: number, s: number, v: number): Chalk,
-	hwb(h: number, w: number, b: number): Chalk,
-	bgHex(color: string): Chalk,
-	bgKeyword(color: string): Chalk,
-	bgRgb(r: number, g: number, b: number): Chalk,
-	bgHsl(h: number, s: number, l: number): Chalk,
-	bgHsv(h: number, s: number, v: number): Chalk,
-	bgHwb(h: number, w: number, b: number): Chalk,
-	hex(color: string): Chalk,
-	keyword(color: string): Chalk,
-
-	+reset: Chalk,
-	+bold: Chalk,
-	+dim: Chalk,
-	+italic: Chalk,
-	+underline: Chalk,
-	+inverse: Chalk,
-	+hidden: Chalk,
-	+strikethrough: Chalk,
-
-	+visible: Chalk,
-
-	+black: Chalk,
-	+red: Chalk,
-	+green: Chalk,
-	+yellow: Chalk,
-	+blue: Chalk,
-	+magenta: Chalk,
-	+cyan: Chalk,
-	+white: Chalk,
-	+gray: Chalk,
-	+grey: Chalk,
-	+blackBright: Chalk,
-	+redBright: Chalk,
-	+greenBright: Chalk,
-	+yellowBright: Chalk,
-	+blueBright: Chalk,
-	+magentaBright: Chalk,
-	+cyanBright: Chalk,
-	+whiteBright: Chalk,
-
-	+bgBlack: Chalk,
-	+bgRed: Chalk,
-	+bgGreen: Chalk,
-	+bgYellow: Chalk,
-	+bgBlue: Chalk,
-	+bgMagenta: Chalk,
-	+bgCyan: Chalk,
-	+bgWhite: Chalk,
-	+bgBlackBright: Chalk,
-	+bgRedBright: Chalk,
-	+bgGreenBright: Chalk,
-	+bgYellowBright: Chalk,
-	+bgBlueBright: Chalk,
-	+bgMagentaBright: Chalk,
-	+bgCyanBright: Chalk,
-	+bgWhiteBrigh: Chalk,
-
-	supportsColor: ColorSupport
-};
-
-declare module.exports: Chalk;
diff --git a/lib/util.js b/lib/util.js
new file mode 100644
index 0000000..8ce1166
--- /dev/null
+++ b/lib/util.js
@@ -0,0 +1,37 @@
+const stringReplaceAll = (string, substring, replacer) => {
+	let index = string.indexOf(substring);
+	if (index === -1) {
+		return string;
+	}
+
+	const subLen = substring.length;
+	let end = 0;
+	let res = '';
+	do {
+		res += string.substr(end, index - end) + replacer;
+		end = index + subLen;
+		index = string.indexOf(substring, end);
+	} while (index !== -1);
+
+	res += string.substr(end);
+	return res;
+};
+
+const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => {
+	let end = 0;
+	let res = '';
+	do {
+		const gotCR = string[index - 1] === '\r';
+		res += string.substr(end, (gotCR ? index - 1 : index) - end) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
+		end = index + 1;
+		index = string.indexOf('\n', end);
+	} while (index !== -1);
+
+	res += string.substr(end);
+	return res;
+};
+
+module.exports = {
+	stringReplaceAll,
+	stringEncaseCRLFWithFirstIndex
+};
diff --git a/package.json b/package.json
index 32c6f73..48712eb 100644
--- a/package.json
+++ b/package.json
@@ -5,17 +5,16 @@
 	"license": "MIT",
 	"repository": "chalk/chalk",
 	"engines": {
-		"node": ">=6"
+		"node": ">=8"
 	},
 	"scripts": {
-		"test": "xo && nyc ava && tsc --project types && flow --max-warnings=0",
+		"test": "xo && nyc ava && tsd",
 		"bench": "matcha benchmark.js"
 	},
 	"files": [
 		"index.js",
 		"templates.js",
-		"types/index.d.ts",
-		"index.js.flow"
+		"index.d.ts"
 	],
 	"keywords": [
 		"color",
@@ -42,25 +41,18 @@
 	],
 	"dependencies": {
 		"ansi-styles": "^3.2.1",
-		"escape-string-regexp": "^1.0.5",
-		"supports-color": "^5.5.0"
+		"supports-color": "^6.1.0"
 	},
 	"devDependencies": {
-		"ava": "^0.25.0",
-		"coveralls": "^3.0.2",
+		"@sindresorhus/tsconfig": "^0.3.0",
+		"ava": "^1.4.1",
+		"coveralls": "^3.0.3",
 		"execa": "^1.0.0",
-		"flow-bin": "^0.81.0",
-		"import-fresh": "^2.0.0",
+		"import-fresh": "^3.0.0",
 		"matcha": "^0.7.0",
-		"nyc": "^13.0.1",
-		"resolve-from": "^4.0.0",
-		"typescript": "^3.0.3",
-		"xo": "^0.23.0"
-	},
-	"types": "types/index.d.ts",
-	"xo": {
-		"ignores": [
-			"test/_flow.js"
-		]
+		"nyc": "^14.0.0",
+		"resolve-from": "^5.0.0",
+		"tsd": "^0.7.2",
+		"xo": "^0.24.0"
 	}
 }
diff --git a/readme.md b/readme.md
index 53a7e7e..d403085 100644
--- a/readme.md
+++ b/readme.md
@@ -9,24 +9,10 @@
 
 > Terminal string styling done right
 
-[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript- and Flow-ready](https://img.shields.io/npm/types/chalk.svg)
+[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg)
 
 <img src="https://cdn.jsdelivr.net/gh/chalk/ansi-styles@8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
 
----
-
-<div align="center">
-	<b>
-		<a href="https://tidelift.com/subscription/pkg/npm-chalk?utm_source=npm-chalk&utm_medium=referral&utm_campaign=readme">Get professional support for Chalk with a Tidelift subscription</a>
-	</b>
-	<br>
-	<sub>
-		Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
-	</sub>
-</div>
-
----
-
 
 ## Highlights
 
@@ -38,7 +24,7 @@
 - Doesn't extend `String.prototype`
 - Clean and focused
 - Actively maintained
-- [Used by ~30,000 packages](https://www.npmjs.com/browse/depended/chalk) as of August 6, 2018
+- [Used by ~40,000 packages](https://www.npmjs.com/browse/depended/chalk) as of March 1, 2019
 
 
 ## Install
@@ -47,10 +33,6 @@
 $ npm install chalk
 ```
 
-<a href="https://www.patreon.com/sindresorhus">
-	<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
-</a>
-
 
 ## Usage
 
@@ -138,24 +120,24 @@ Multiple arguments will be separated by space.
 
 ### chalk.enabled
 
-Color support is automatically detected, as is the level (see `chalk.level`). However, if you'd like to simply enable/disable Chalk, you can do so via the `.enabled` property.
+Color support is automatically detected, as is the level (see `chalk.level`). However, if you'd like to simply enable/disable Chalk, you can do so via the `.enabled` property. When `chalk.enabled` is `true`, `chalk.level` must *also* be greater than `0` for colored output to be produced.
 
-Chalk is enabled by default unless explicitly disabled via the constructor or `chalk.level` is `0`.
+Chalk is enabled by default unless explicitly disabled via `new chalk.Instance()` or `chalk.level` is `0`.
 
 If you need to change this in a reusable module, create a new instance:
 
 ```js
-const ctx = new chalk.constructor({enabled: false});
+const ctx = new chalk.Instance({enabled: false});
 ```
 
 ### chalk.level
 
-Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
+Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers. When `chalk.level` is greater than `0`, `chalk.enabled` must *also* be `true` for colored output to be produced.
 
 If you need to change this in a reusable module, create a new instance:
 
 ```js
-const ctx = new chalk.constructor({level: 0});
+const ctx = new chalk.Instance({level: 0});
 ```
 
 Levels are as follows:
@@ -169,7 +151,7 @@ Levels are as follows:
 
 Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
 
-Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
+Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
 
 Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
 
@@ -178,15 +160,15 @@ Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=
 
 ### Modifiers
 
-- `reset`
-- `bold`
-- `dim`
-- `italic` *(Not widely supported)*
-- `underline`
-- `inverse`
-- `hidden`
-- `strikethrough` *(Not widely supported)*
-- `visible` (Text is emitted only if enabled)
+- `reset` - Resets the current color chain.
+- `bold` - Make text bold.
+- `dim` - Emitting only a small amount of light.
+- `italic` - Make text italic. *(Not widely supported)*
+- `underline` - Make text underline. *(Not widely supported)*
+- `inverse`- Inverse background and foreground colors.
+- `hidden` - Prints the text, but makes it invisible.
+- `strikethrough` - Puts a horizontal line through the center of the text. *(Not widely supported)*
+- `visible`- Prints the text only when Chalk is enabled. Can be useful for things that are purely cosmetic.
 
 ### Colors
 
@@ -194,7 +176,7 @@ Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=
 - `red`
 - `green`
 - `yellow`
-- `blue` *(On Windows the bright version is used since normal blue is illegible)*
+- `blue`
 - `magenta`
 - `cyan`
 - `white`
@@ -321,6 +303,14 @@ If you're on Windows, do yourself a favor and use [`cmder`](http://cmder.net/) i
 - [Josh Junon](https://github.com/qix-)
 
 
-## License
+---
 
-MIT
+<div align="center">
+	<b>
+		<a href="https://tidelift.com/subscription/pkg/npm-chalk?utm_source=npm-chalk&utm_medium=referral&utm_campaign=readme">Get professional support for Chalk with a Tidelift subscription</a>
+	</b>
+	<br>
+	<sub>
+		Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
+	</sub>
+</div>
diff --git a/templates.js b/templates.js
index 8ce33fe..fe94642 100644
--- a/templates.js
+++ b/templates.js
@@ -1,8 +1,8 @@
 'use strict';
-const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
+const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
 const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
 const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
-const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi;
+const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.)|([^\\])/gi;
 
 const ESCAPES = new Map([
 	['n', '\n'],
@@ -18,23 +18,31 @@ const ESCAPES = new Map([
 ]);
 
 function unescape(c) {
-	if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
+	const u = c[0] === 'u';
+	const bracket = c[1] === '{';
+
+	if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
 		return String.fromCharCode(parseInt(c.slice(1), 16));
 	}
 
+	if (u && bracket) {
+		return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
+	}
+
 	return ESCAPES.get(c) || c;
 }
 
-function parseArguments(name, args) {
+function parseArguments(name, arguments_) {
 	const results = [];
-	const chunks = args.trim().split(/\s*,\s*/g);
+	const chunks = arguments_.trim().split(/\s*,\s*/g);
 	let matches;
 
 	for (const chunk of chunks) {
-		if (!isNaN(chunk)) {
-			results.push(Number(chunk));
+		const number = Number(chunk);
+		if (!Number.isNaN(number)) {
+			results.push(number);
 		} else if ((matches = chunk.match(STRING_REGEX))) {
-			results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr));
+			results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character));
 		} else {
 			throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
 		}
@@ -73,36 +81,34 @@ function buildStyle(chalk, styles) {
 	}
 
 	let current = chalk;
-	for (const styleName of Object.keys(enabled)) {
-		if (Array.isArray(enabled[styleName])) {
-			if (!(styleName in current)) {
-				throw new Error(`Unknown Chalk style: ${styleName}`);
-			}
+	for (const [styleName, styles] of Object.entries(enabled)) {
+		if (!Array.isArray(styles)) {
+			continue;
+		}
 
-			if (enabled[styleName].length > 0) {
-				current = current[styleName](...enabled[styleName]);
-			} else {
-				current = current[styleName];
-			}
+		if (!(styleName in current)) {
+			throw new Error(`Unknown Chalk style: ${styleName}`);
 		}
+
+		current = styles.length > 0 ? current[styleName](...styles) : current[styleName];
 	}
 
 	return current;
 }
 
-module.exports = (chalk, tmp) => {
+module.exports = (chalk, temporary) => {
 	const styles = [];
 	const chunks = [];
 	let chunk = [];
 
 	// eslint-disable-next-line max-params
-	tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => {
-		if (escapeChar) {
-			chunk.push(unescape(escapeChar));
+	temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => {
+		if (escapeCharacter) {
+			chunk.push(unescape(escapeCharacter));
 		} else if (style) {
-			const str = chunk.join('');
+			const string = chunk.join('');
 			chunk = [];
-			chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str));
+			chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string));
 			styles.push({inverse, styles: parseStyle(style)});
 		} else if (close) {
 			if (styles.length === 0) {
@@ -113,7 +119,7 @@ module.exports = (chalk, tmp) => {
 			chunk = [];
 			styles.pop();
 		} else {
-			chunk.push(chr);
+			chunk.push(character);
 		}
 	});
 
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..3d73ee9
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,7 @@
+{
+	"extends": "@sindresorhus/tsconfig",
+	"compilerOptions": {
+		"noEmit": true,
+		"allowJs": true
+	}
+}
diff --git a/types/index.d.ts b/types/index.d.ts
deleted file mode 100644
index b4e4dc5..0000000
--- a/types/index.d.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-// Type definitions for Chalk
-// Definitions by: Thomas Sauer <https://github.com/t-sauer>
-
-export const enum Level {
-	None = 0,
-	Basic = 1,
-	Ansi256 = 2,
-	TrueColor = 3
-}
-
-export interface ChalkOptions {
-	enabled?: boolean;
-	level?: Level;
-}
-
-export interface ChalkConstructor {
-	new (options?: ChalkOptions): Chalk;
-	(options?: ChalkOptions): Chalk;
-}
-
-export interface ColorSupport {
-	level: Level;
-	hasBasic: boolean;
-	has256: boolean;
-	has16m: boolean;
-}
-
-export interface Chalk {
-	(...text: string[]): string;
-	(text: TemplateStringsArray, ...placeholders: string[]): string;
-	constructor: ChalkConstructor;
-	enabled: boolean;
-	level: Level;
-	rgb(r: number, g: number, b: number): this;
-	hsl(h: number, s: number, l: number): this;
-	hsv(h: number, s: number, v: number): this;
-	hwb(h: number, w: number, b: number): this;
-	bgHex(color: string): this;
-	bgKeyword(color: string): this;
-	bgRgb(r: number, g: number, b: number): this;
-	bgHsl(h: number, s: number, l: number): this;
-	bgHsv(h: number, s: number, v: number): this;
-	bgHwb(h: number, w: number, b: number): this;
-	hex(color: string): this;
-	keyword(color: string): this;
-
-	readonly reset: this;
-	readonly bold: this;
-	readonly dim: this;
-	readonly italic: this;
-	readonly underline: this;
-	readonly inverse: this;
-	readonly hidden: this;
-	readonly strikethrough: this;
-
-	readonly visible: this;
-
-	readonly black: this;
-	readonly red: this;
-	readonly green: this;
-	readonly yellow: this;
-	readonly blue: this;
-	readonly magenta: this;
-	readonly cyan: this;
-	readonly white: this;
-	readonly gray: this;
-	readonly grey: this;
-	readonly blackBright: this;
-	readonly redBright: this;
-	readonly greenBright: this;
-	readonly yellowBright: this;
-	readonly blueBright: this;
-	readonly magentaBright: this;
-	readonly cyanBright: this;
-	readonly whiteBright: this;
-
-	readonly bgBlack: this;
-	readonly bgRed: this;
-	readonly bgGreen: this;
-	readonly bgYellow: this;
-	readonly bgBlue: this;
-	readonly bgMagenta: this;
-	readonly bgCyan: this;
-	readonly bgWhite: this;
-	readonly bgBlackBright: this;
-	readonly bgRedBright: this;
-	readonly bgGreenBright: this;
-	readonly bgYellowBright: this;
-	readonly bgBlueBright: this;
-	readonly bgMagentaBright: this;
-	readonly bgCyanBright: this;
-	readonly bgWhiteBright: this;
-}
-
-declare const chalk: Chalk & { supportsColor: ColorSupport };
-
-export default chalk
diff --git a/types/tsconfig.json b/types/tsconfig.json
deleted file mode 100644
index b73840f..0000000
--- a/types/tsconfig.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-	"compilerOptions": {
-		"module": "commonjs",
-		"target": "es6",
-		"noImplicitAny": true,
-		"noEmit": true,
-		"allowJs": true
-	}
-}


Test patch:
diff --git a/index.test-d.ts b/index.test-d.ts
new file mode 100644
index 0000000..fd19d04
--- /dev/null
+++ b/index.test-d.ts
@@ -0,0 +1,142 @@
+import {expectType, expectError} from 'tsd';
+import chalk = require('.');
+
+// - Helpers -
+type colorReturn = chalk.Chalk & {supportsColor?: never};
+
+// - Level -
+expectType<number>(chalk.Level.None);
+expectType<number>(chalk.Level.Basic);
+expectType<number>(chalk.Level.Ansi256);
+expectType<number>(chalk.Level.TrueColor);
+
+// - supportsColor -
+expectType<chalk.ColorSupport | false>(chalk.supportsColor);
+expectType<boolean>((chalk.supportsColor as chalk.ColorSupport).hasBasic);
+expectType<boolean>((chalk.supportsColor as chalk.ColorSupport).has256);
+expectType<boolean>((chalk.supportsColor as chalk.ColorSupport).has16m);
+
+// -- `supportsColor` is not a member of the Chalk interface --
+expectError(chalk.reset.supportsColor);
+
+// - Chalk -
+// -- Instance --
+expectType<chalk.Chalk>(new chalk.Instance({level: 1}));
+
+// -- Properties --
+expectType<boolean>(chalk.enabled);
+expectType<chalk.Level>(chalk.level);
+
+// -- Template literal --
+expectType<string>(chalk``);
+const name = 'John';
+expectType<string>(chalk`Hello {bold.red ${name}}`);
+expectType<string>(chalk`Works with numbers {bold.red ${1}}`);
+
+// -- Color methods --
+expectType<colorReturn>(chalk.hex('#DEADED'));
+expectType<colorReturn>(chalk.keyword('orange'));
+expectType<colorReturn>(chalk.rgb(0, 0, 0));
+expectType<colorReturn>(chalk.hsl(0, 0, 0));
+expectType<colorReturn>(chalk.hsv(0, 0, 0));
+expectType<colorReturn>(chalk.hwb(0, 0, 0));
+expectType<colorReturn>(chalk.bgHex('#DEADED'));
+expectType<colorReturn>(chalk.bgKeyword('orange'));
+expectType<colorReturn>(chalk.bgRgb(0, 0, 0));
+expectType<colorReturn>(chalk.bgHsl(0, 0, 0));
+expectType<colorReturn>(chalk.bgHsv(0, 0, 0));
+expectType<colorReturn>(chalk.bgHwb(0, 0, 0));
+
+// -- Modifiers --
+expectType<string>(chalk.reset('foo'));
+expectType<string>(chalk.bold('foo'));
+expectType<string>(chalk.dim('foo'));
+expectType<string>(chalk.italic('foo'));
+expectType<string>(chalk.underline('foo'));
+expectType<string>(chalk.inverse('foo'));
+expectType<string>(chalk.hidden('foo'));
+expectType<string>(chalk.strikethrough('foo'));
+expectType<string>(chalk.visible('foo'));
+expectType<string>(chalk.reset`foo`);
+expectType<string>(chalk.bold`foo`);
+expectType<string>(chalk.dim`foo`);
+expectType<string>(chalk.italic`foo`);
+expectType<string>(chalk.underline`foo`);
+expectType<string>(chalk.inverse`foo`);
+expectType<string>(chalk.hidden`foo`);
+expectType<string>(chalk.strikethrough`foo`);
+expectType<string>(chalk.visible`foo`);
+
+// -- Colors --
+expectType<string>(chalk.black('foo'));
+expectType<string>(chalk.red('foo'));
+expectType<string>(chalk.green('foo'));
+expectType<string>(chalk.yellow('foo'));
+expectType<string>(chalk.blue('foo'));
+expectType<string>(chalk.magenta('foo'));
+expectType<string>(chalk.cyan('foo'));
+expectType<string>(chalk.white('foo'));
+expectType<string>(chalk.gray('foo'));
+expectType<string>(chalk.grey('foo'));
+expectType<string>(chalk.blackBright('foo'));
+expectType<string>(chalk.redBright('foo'));
+expectType<string>(chalk.greenBright('foo'));
+expectType<string>(chalk.yellowBright('foo'));
+expectType<string>(chalk.blueBright('foo'));
+expectType<string>(chalk.magentaBright('foo'));
+expectType<string>(chalk.cyanBright('foo'));
+expectType<string>(chalk.whiteBright('foo'));
+expectType<string>(chalk.bgBlack('foo'));
+expectType<string>(chalk.bgRed('foo'));
+expectType<string>(chalk.bgGreen('foo'));
+expectType<string>(chalk.bgYellow('foo'));
+expectType<string>(chalk.bgBlue('foo'));
+expectType<string>(chalk.bgMagenta('foo'));
+expectType<string>(chalk.bgCyan('foo'));
+expectType<string>(chalk.bgWhite('foo'));
+expectType<string>(chalk.bgBlackBright('foo'));
+expectType<string>(chalk.bgRedBright('foo'));
+expectType<string>(chalk.bgGreenBright('foo'));
+expectType<string>(chalk.bgYellowBright('foo'));
+expectType<string>(chalk.bgBlueBright('foo'));
+expectType<string>(chalk.bgMagentaBright('foo'));
+expectType<string>(chalk.bgCyanBright('foo'));
+expectType<string>(chalk.bgWhiteBright('foo'));
+expectType<string>(chalk.black`foo`);
+expectType<string>(chalk.red`foo`);
+expectType<string>(chalk.green`foo`);
+expectType<string>(chalk.yellow`foo`);
+expectType<string>(chalk.blue`foo`);
+expectType<string>(chalk.magenta`foo`);
+expectType<string>(chalk.cyan`foo`);
+expectType<string>(chalk.white`foo`);
+expectType<string>(chalk.gray`foo`);
+expectType<string>(chalk.grey`foo`);
+expectType<string>(chalk.blackBright`foo`);
+expectType<string>(chalk.redBright`foo`);
+expectType<string>(chalk.greenBright`foo`);
+expectType<string>(chalk.yellowBright`foo`);
+expectType<string>(chalk.blueBright`foo`);
+expectType<string>(chalk.magentaBright`foo`);
+expectType<string>(chalk.cyanBright`foo`);
+expectType<string>(chalk.whiteBright`foo`);
+expectType<string>(chalk.bgBlack`foo`);
+expectType<string>(chalk.bgRed`foo`);
+expectType<string>(chalk.bgGreen`foo`);
+expectType<string>(chalk.bgYellow`foo`);
+expectType<string>(chalk.bgBlue`foo`);
+expectType<string>(chalk.bgMagenta`foo`);
+expectType<string>(chalk.bgCyan`foo`);
+expectType<string>(chalk.bgWhite`foo`);
+expectType<string>(chalk.bgBlackBright`foo`);
+expectType<string>(chalk.bgRedBright`foo`);
+expectType<string>(chalk.bgGreenBright`foo`);
+expectType<string>(chalk.bgYellowBright`foo`);
+expectType<string>(chalk.bgBlueBright`foo`);
+expectType<string>(chalk.bgMagentaBright`foo`);
+expectType<string>(chalk.bgCyanBright`foo`);
+expectType<string>(chalk.bgWhiteBright`foo`);
+
+// -- Complex --
+expectType<string>(chalk.red.bgGreen.underline('foo'));
+expectType<string>(chalk.underline.red.bgGreen('foo'));
diff --git a/test/_flow.js b/test/_flow.js
deleted file mode 100644
index 2cf3cf2..0000000
--- a/test/_flow.js
+++ /dev/null
@@ -1,94 +0,0 @@
-// @flow
-import chalk from '..';
-
-// $ExpectError (Can't have typo in option name)
-chalk.constructor({levl: 1});
-chalk.constructor({level: 1});
-
-// $ExpectError (Option must have proper type)
-new chalk.constructor({enabled: 'true'});
-new chalk.constructor({enabled: true});
-
-// $ExpectError (Can't pass in null)
-chalk.underline(null);
-chalk.underline('foo');
-
-// $ExpectError (Can't have typo in chalk method)
-chalk.rd('foo');
-chalk.red('foo');
-
-// $ExpectError (Can't have typo in chalk method)
-chalk.gren`foo`;
-chalk.green`foo`;
-
-// $ExpectError (Can't have typo in chalk method)
-chalk.red.bgBlu.underline('foo');
-chalk.red.bgBlue.underline('foo');
-
-// $ExpectError (Level must be 0, 1, 2, or 3)
-const badCtx = chalk.constructor({level: 4});
-const ctx = chalk.constructor({level: 3});
-
-// $ExpectError (Can't pass in null)
-ctx(null);
-ctx('foo');
-
-// $ExpectError (Can't have typo in method name)
-ctx.gry('foo');
-ctx.grey('foo');
-
-// $ExpectError (Can't have typo in method name)
-ctx`foo`.value();
-ctx`foo`.valueOf();
-
-// $ExpectError (Can't have typo in property name)
-chalk.abled = true;
-chalk.enabled = true;
-
-// $ExpectError (Can't use invalid Level for property setter)
-chalk.level = 10;
-chalk.level = 1;
-
-const chalkInstance = new chalk.constructor();
-
-// $ExpectError (Can't have typo in method name)
-chalkInstance.blu('foo');
-chalkInstance.blue('foo');
-chalkInstance`foo`;
-
-// $ExpectError (Can't have typo in method name)
-chalk.keywrd('orange').bgBlue('foo');
-chalk.keyword('orange').bgBlue('foo');
-
-// $ExpectError (rgb should take in 3 numbers)
-chalk.rgb(1, 14).bgBlue('foo');
-chalk.rgb(1, 14, 9).bgBlue('foo');
-
-// $ExpectError (hsl should take in 3 numbers)
-chalk.hsl(1, 14, '9').bgBlue('foo');
-chalk.hsl(1, 14, 9).bgBlue('foo');
-
-// $ExpectError (hsv should take in 3 numbers)
-chalk.hsv(1, 14).bgBlue('foo');
-chalk.hsv(1, 14, 9).bgBlue('foo');
-
-// $ExpectError (hwb should take in 3 numbers)
-chalk.hwb(1, 14).bgBlue('foo');
-chalk.hwb(1, 14, 9).bgBlue('foo');
-
-// $ExpectError (Can't have typo in method name)
-chalk.visibl('foo');
-chalk.visible('foo');
-
-// $ExpectError (Can't have typo in method name)
-chalk.red.visibl('foo');
-chalk.red.visible('foo');
-chalk.visible.red('foo');
-
-// $ExpectError (Can't write to readonly property)
-chalk.black = 'foo';
-chalk.black;
-
-// $ExpectError (Can't write to readonly property)
-chalk.reset = 'foo';
-console.log(chalk.reset);
diff --git a/test/chalk.js b/test/chalk.js
index a53b6f5..3f90ba6 100644
--- a/test/chalk.js
+++ b/test/chalk.js
@@ -82,18 +82,22 @@ test('line breaks should open and close colors', t => {
 	t.is(chalk.grey('hello\nworld'), '\u001B[90mhello\u001B[39m\n\u001B[90mworld\u001B[39m');
 });
 
+test('line breaks should open and close colors with CRLF', t => {
+	t.is(chalk.grey('hello\r\nworld'), '\u001B[90mhello\u001B[39m\r\n\u001B[90mworld\u001B[39m');
+});
+
 test('properly convert RGB to 16 colors on basic color terminals', t => {
-	t.is(new chalk.constructor({level: 1}).hex('#FF0000')('hello'), '\u001B[91mhello\u001B[39m');
-	t.is(new chalk.constructor({level: 1}).bgHex('#FF0000')('hello'), '\u001B[101mhello\u001B[49m');
+	t.is(new chalk.Instance({level: 1}).hex('#FF0000')('hello'), '\u001B[91mhello\u001B[39m');
+	t.is(new chalk.Instance({level: 1}).bgHex('#FF0000')('hello'), '\u001B[101mhello\u001B[49m');
 });
 
 test('properly convert RGB to 256 colors on basic color terminals', t => {
-	t.is(new chalk.constructor({level: 2}).hex('#FF0000')('hello'), '\u001B[38;5;196mhello\u001B[39m');
-	t.is(new chalk.constructor({level: 2}).bgHex('#FF0000')('hello'), '\u001B[48;5;196mhello\u001B[49m');
-	t.is(new chalk.constructor({level: 3}).bgHex('#FF0000')('hello'), '\u001B[48;2;255;0;0mhello\u001B[49m');
+	t.is(new chalk.Instance({level: 2}).hex('#FF0000')('hello'), '\u001B[38;5;196mhello\u001B[39m');
+	t.is(new chalk.Instance({level: 2}).bgHex('#FF0000')('hello'), '\u001B[48;5;196mhello\u001B[49m');
+	t.is(new chalk.Instance({level: 3}).bgHex('#FF0000')('hello'), '\u001B[48;2;255;0;0mhello\u001B[49m');
 });
 
 test('don\'t emit RGB codes if level is 0', t => {
-	t.is(new chalk.constructor({level: 0}).hex('#FF0000')('hello'), 'hello');
-	t.is(new chalk.constructor({level: 0}).bgHex('#FF0000')('hello'), 'hello');
+	t.is(new chalk.Instance({level: 0}).hex('#FF0000')('hello'), 'hello');
+	t.is(new chalk.Instance({level: 0}).bgHex('#FF0000')('hello'), 'hello');
 });
diff --git a/test/constructor.js b/test/constructor.js
index bda0137..188001a 100644
--- a/test/constructor.js
+++ b/test/constructor.js
@@ -1,34 +1,15 @@
 import test from 'ava';
 
-// Spoof supports-color
-require('./_supports-color')(__dirname);
-
 const chalk = require('..');
 
-test('create an isolated context where colors can be disabled (by level)', t => {
-	const instance = new chalk.constructor({level: 0, enabled: true});
-	t.is(instance.red('foo'), 'foo');
-	t.is(chalk.red('foo'), '\u001B[31mfoo\u001B[39m');
-	instance.level = 2;
-	t.is(instance.red('foo'), '\u001B[31mfoo\u001B[39m');
-});
+test('Chalk.constructor should throw an expected error', t => {
+	const expectedError = t.throws(() => {
+		chalk.constructor();
+	});
 
-test('create an isolated context where colors can be disabled (by enabled flag)', t => {
-	const instance = new chalk.constructor({enabled: false});
-	t.is(instance.red('foo'), 'foo');
-	t.is(chalk.red('foo'), '\u001B[31mfoo\u001B[39m');
-	instance.enabled = true;
-	t.is(instance.red('foo'), '\u001B[31mfoo\u001B[39m');
-});
-
-test('the `level` option should be a number from 0 to 3', t => {
-	/* eslint-disable no-new */
-	t.throws(() => {
-		new chalk.constructor({level: 10});
-	}, /should be an integer from 0 to 3/);
+	t.is(expectedError.message, '`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
 
 	t.throws(() => {
-		new chalk.constructor({level: -1});
-	}, /should be an integer from 0 to 3/);
-	/* eslint-enable no-new */
+		new chalk.constructor(); // eslint-disable-line no-new
+	});
 });
diff --git a/test/instance.js b/test/instance.js
new file mode 100644
index 0000000..e34bea7
--- /dev/null
+++ b/test/instance.js
@@ -0,0 +1,34 @@
+import test from 'ava';
+
+// Spoof supports-color
+require('./_supports-color')(__dirname);
+
+const chalk = require('..');
+
+test('create an isolated context where colors can be disabled (by level)', t => {
+	const instance = new chalk.Instance({level: 0, enabled: true});
+	t.is(instance.red('foo'), 'foo');
+	t.is(chalk.red('foo'), '\u001B[31mfoo\u001B[39m');
+	instance.level = 2;
+	t.is(instance.red('foo'), '\u001B[31mfoo\u001B[39m');
+});
+
+test('create an isolated context where colors can be disabled (by enabled flag)', t => {
+	const instance = new chalk.Instance({enabled: false});
+	t.is(instance.red('foo'), 'foo');
+	t.is(chalk.red('foo'), '\u001B[31mfoo\u001B[39m');
+	instance.enabled = true;
+	t.is(instance.red('foo'), '\u001B[31mfoo\u001B[39m');
+});
+
+test('the `level` option should be a number from 0 to 3', t => {
+	/* eslint-disable no-new */
+	t.throws(() => {
+		new chalk.Instance({level: 10});
+	}, /should be an integer from 0 to 3/);
+
+	t.throws(() => {
+		new chalk.Instance({level: -1});
+	}, /should be an integer from 0 to 3/);
+	/* eslint-enable no-new */
+});
diff --git a/test/template-literal.js b/test/template-literal.js
index 34588d2..ae4a0bc 100644
--- a/test/template-literal.js
+++ b/test/template-literal.js
@@ -7,23 +7,23 @@ require('./_supports-color')(__dirname);
 const chalk = require('..');
 
 test('return an empty string for an empty literal', t => {
-	const instance = chalk.constructor();
+	const instance = new chalk.Instance();
 	t.is(instance``, '');
 });
 
 test('return a regular string for a literal with no templates', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`hello`, 'hello');
 });
 
 test('correctly perform template parsing', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`{bold Hello, {cyan World!} This is a} test. {green Woo!}`,
 		instance.bold('Hello,', instance.cyan('World!'), 'This is a') + ' test. ' + instance.green('Woo!'));
 });
 
 test('correctly perform template substitutions', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	const name = 'Sindre';
 	const exclamation = 'Neat';
 	t.is(instance`{bold Hello, {cyan.inverse ${name}!} This is a} test. {green ${exclamation}!}`,
@@ -31,7 +31,7 @@ test('correctly perform template substitutions', t => {
 });
 
 test('correctly parse and evaluate color-convert functions', t => {
-	const instance = chalk.constructor({level: 3});
+	const instance = new chalk.Instance({level: 3});
 	t.is(instance`{bold.rgb(144,10,178).inverse Hello, {~inverse there!}}`,
 		'\u001B[1m\u001B[38;2;144;10;178m\u001B[7mHello, ' +
 		'\u001B[27m\u001B[39m\u001B[22m\u001B[1m' +
@@ -44,13 +44,13 @@ test('correctly parse and evaluate color-convert functions', t => {
 });
 
 test('properly handle escapes', t => {
-	const instance = chalk.constructor({level: 3});
+	const instance = new chalk.Instance({level: 3});
 	t.is(instance`{bold hello \{in brackets\}}`,
 		'\u001B[1mhello {in brackets}\u001B[22m');
 });
 
 test('throw if there is an unclosed block', t => {
-	const instance = chalk.constructor({level: 3});
+	const instance = new chalk.Instance({level: 3});
 	try {
 		console.log(instance`{bold this shouldn't appear ever\}`);
 		t.fail();
@@ -67,7 +67,7 @@ test('throw if there is an unclosed block', t => {
 });
 
 test('throw if there is an invalid style', t => {
-	const instance = chalk.constructor({level: 3});
+	const instance = new chalk.Instance({level: 3});
 	try {
 		console.log(instance`{abadstylethatdoesntexist this shouldn't appear ever}`);
 		t.fail();
@@ -77,7 +77,7 @@ test('throw if there is an invalid style', t => {
 });
 
 test('properly style multiline color blocks', t => {
-	const instance = chalk.constructor({level: 3});
+	const instance = new chalk.Instance({level: 3});
 	t.is(
 		instance`{bold
 			Hello! This is a
@@ -97,49 +97,49 @@ test('properly style multiline color blocks', t => {
 });
 
 test('escape interpolated values', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`Hello {bold hi}`, 'Hello hi');
 	t.is(instance`Hello ${'{bold hi}'}`, 'Hello {bold hi}');
 });
 
 test('allow custom colors (themes) on custom contexts', t => {
-	const instance = chalk.constructor({level: 3});
+	const instance = new chalk.Instance({level: 3});
 	instance.rose = instance.hex('#F6D9D9');
 	t.is(instance`Hello, {rose Rose}.`, 'Hello, \u001B[38;2;246;217;217mRose\u001B[39m.');
 });
 
 test('correctly parse newline literals (bug #184)', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`Hello
 {red there}`, 'Hello\nthere');
 });
 
 test('correctly parse newline escapes (bug #177)', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`Hello\nthere!`, 'Hello\nthere!');
 });
 
 test('correctly parse escape in parameters (bug #177 comment 318622809)', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	const str = '\\';
 	t.is(instance`{blue ${str}}`, '\\');
 });
 
 test('correctly parses unicode/hex escapes', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`\u0078ylophones are fo\x78y! {magenta.inverse \u0078ylophones are fo\x78y!}`,
 		'xylophones are foxy! xylophones are foxy!');
 });
 
 test('correctly parses string arguments', t => {
-	const instance = chalk.constructor({level: 3});
+	const instance = new chalk.Instance({level: 3});
 	t.is(instance`{keyword('black').bold can haz cheezburger}`, '\u001B[38;2;0;0;0m\u001B[1mcan haz cheezburger\u001B[22m\u001B[39m');
 	t.is(instance`{keyword('blac\x6B').bold can haz cheezburger}`, '\u001B[38;2;0;0;0m\u001B[1mcan haz cheezburger\u001B[22m\u001B[39m');
 	t.is(instance`{keyword('blac\u006B').bold can haz cheezburger}`, '\u001B[38;2;0;0;0m\u001B[1mcan haz cheezburger\u001B[22m\u001B[39m');
 });
 
 test('throws if a bad argument is encountered', t => {
-	const instance = chalk.constructor({level: 3}); // Keep level at least 1 in case we optimize for disabled chalk instances
+	const instance = new chalk.Instance({level: 3}); // Keep level at least 1 in case we optimize for disabled chalk instances
 	try {
 		console.log(instance`{keyword(????) hi}`);
 		t.fail();
@@ -149,7 +149,7 @@ test('throws if a bad argument is encountered', t => {
 });
 
 test('throws if an extra unescaped } is found', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	try {
 		console.log(instance`{red hi!}}`);
 		t.fail();
@@ -159,12 +159,19 @@ test('throws if an extra unescaped } is found', t => {
 });
 
 test('should not parse upper-case escapes', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`\N\n\T\t\X07\x07\U000A\u000A\U000a\u000a`, 'N\nT\tX07\x07U000A\u000AU000a\u000A');
 });
 
 test('should properly handle undefined template interpolated values', t => {
-	const instance = chalk.constructor({level: 0});
+	const instance = new chalk.Instance({level: 0});
 	t.is(instance`hello ${undefined}`, 'hello undefined');
 	t.is(instance`hello ${null}`, 'hello null');
 });
+
+test('should allow bracketed Unicode escapes', t => {
+	const instance = new chalk.Instance({level: 3});
+	t.is(instance`\u{AB}`, '\u{AB}');
+	t.is(instance`This is a {bold \u{AB681}} test`, 'This is a \u001B[1m\u{AB681}\u001B[22m test');
+	t.is(instance`This is a {bold \u{10FFFF}} test`, 'This is a \u001B[1m\u{10FFFF}\u001B[22m test');
+});
diff --git a/test/visible.js b/test/visible.js
index 3266295..01eb087 100644
--- a/test/visible.js
+++ b/test/visible.js
@@ -6,25 +6,25 @@ require('./_supports-color')(__dirname);
 const chalk = require('..');
 
 test('visible: normal output when enabled', t => {
-	const instance = new chalk.constructor({level: 3, enabled: true});
+	const instance = new chalk.Instance({level: 3, enabled: true});
 	t.is(instance.visible.red('foo'), '\u001B[31mfoo\u001B[39m');
 	t.is(instance.red.visible('foo'), '\u001B[31mfoo\u001B[39m');
 });
 
 test('visible: no output when disabled', t => {
-	const instance = new chalk.constructor({level: 3, enabled: false});
+	const instance = new chalk.Instance({level: 3, enabled: false});
 	t.is(instance.red.visible('foo'), '');
 	t.is(instance.visible.red('foo'), '');
 });
 
 test('visible: no output when level is too low', t => {
-	const instance = new chalk.constructor({level: 0, enabled: true});
+	const instance = new chalk.Instance({level: 0, enabled: true});
 	t.is(instance.visible.red('foo'), '');
 	t.is(instance.red.visible('foo'), '');
 });
 
 test('test switching back and forth between enabled and disabled', t => {
-	const instance = new chalk.constructor({level: 3, enabled: true});
+	const instance = new chalk.Instance({level: 3, enabled: true});
 	t.is(instance.red('foo'), '\u001B[31mfoo\u001B[39m');
 	t.is(instance.visible.red('foo'), '\u001B[31mfoo\u001B[39m');
 	t.is(instance.red.visible('foo'), '\u001B[31mfoo\u001B[39m');
diff --git a/test/windows.js b/test/windows.js
deleted file mode 100644
index 3ede386..0000000
--- a/test/windows.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import test from 'ava';
-import importFresh from 'import-fresh';
-import resolveFrom from 'resolve-from';
-
-// Spoof supports-color
-require('./_supports-color')(__dirname);
-
-let originalEnv;
-let originalPlatform;
-
-test.before(() => {
-	originalEnv = process.env;
-	originalPlatform = process.platform;
-});
-
-test.after(() => {
-	process.env = originalEnv;
-	Object.defineProperty(process, 'platform', {value: originalPlatform});
-});
-
-test.beforeEach(() => {
-	process.env = {};
-	Object.defineProperty(process, 'platform', {value: 'win32'});
-	// Since chalk internally modifies `ansiStyles.blue.open`, `ansi-styles` needs
-	// to be removed from the require cache for `require-uncached` to work
-	delete require.cache[resolveFrom(__dirname, 'ansi-styles')];
-});
-
-test('detect a simple term if TERM isn\'t set', t => {
-	delete process.env.TERM;
-	const chalk = importFresh('..');
-	t.is(chalk.blue('foo'), '\u001B[94mfoo\u001B[39m');
-});
-
-test('replace blue foreground color in cmd.exe', t => {
-	process.env.TERM = 'dumb';
-	const chalk = importFresh('..');
-	t.is(chalk.blue('foo'), '\u001B[94mfoo\u001B[39m');
-});
-
-test('don\'t replace blue foreground color in xterm based terminals', t => {
-	process.env.TERM = 'xterm-256color';
-	const chalk = importFresh('..');
-	t.is(chalk.blue('foo'), '\u001B[34mfoo\u001B[39m');
-});
-
-test('don\'t apply dimmed styling on gray strings, see https://github.com/chalk/chalk/issues/58', t => {
-	process.env.TERM = 'dumb';
-	const chalk = importFresh('..');
-	t.is(chalk.gray.dim('foo'), '\u001B[90mfoo\u001B[22m\u001B[39m');
-});
-
-test('apply dimmed styling on xterm compatible terminals', t => {
-	process.env.TERM = 'xterm';
-	const chalk = importFresh('..');
-	t.is(chalk.gray.dim('foo'), '\u001B[90m\u001B[2mfoo\u001B[22m\u001B[39m');
-});
-
-test('apply dimmed styling on strings of other colors', t => {
-	process.env.TERM = 'dumb';
-	const chalk = importFresh('..');
-	t.is(chalk.blue.dim('foo'), '\u001B[94m\u001B[2mfoo\u001B[22m\u001B[39m');
-});
diff --git a/types/test.ts b/types/test.ts
deleted file mode 100644
index cedb39a..0000000
--- a/types/test.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import chalk, {Level} from '..';
-
-chalk.underline('foo');
-chalk.red('foo');
-chalk.bgRed('foo');
-
-const name = 'Josh';
-chalk`Hello {bold.red ${name}}`;
-
-chalk.red`foo`;
-chalk.underline`foo`;
-chalk`foo`;
-
-chalk.red.bgGreen.underline('foo');
-chalk.underline.red.bgGreen('foo');
-
-chalk.grey('foo');
-
-chalk.constructor({level: 1});
-const ctx = chalk.constructor({level: Level.TrueColor });
-ctx('foo');
-ctx.red('foo');
-ctx`foo`;
-
-chalk.enabled = true;
-chalk.level = 1;
-chalk.level = Level.Ansi256;
-
-chalk.level === Level.Ansi256;
-
-let chalkInstance = new chalk.constructor();
-chalkInstance = chalk.constructor();
-
-chalkInstance.blue('foo');
-chalkInstance`foo`;
-
-let x = 'imastring';
-x = chalk();
-
-chalk.enabled;
-chalk.level;
-chalk.supportsColor.level;
-chalk.supportsColor.has16m;
-chalk.supportsColor.has256;
-chalk.supportsColor.hasBasic;
-
-chalk.keyword('orange').bgBlue('foo');
-chalk.hex('#123456').bgBlue('foo');
-chalk.rgb(1, 14, 9).bgBlue('foo');
-chalk.hsl(1, 14, 9).bgBlue('foo');
-chalk.hsv(1, 14, 9).bgBlue('foo');
-chalk.hwb(1, 14, 9).bgBlue('foo');
-
-chalk.visible('foo');
-chalk.red.visible('foo');
-chalk.visible.red('foo');