Skip to content

Commit

Permalink
feat: add bgGrey and bgGray aliases for bgBlackBright
Browse files Browse the repository at this point in the history
  • Loading branch information
webdiscus committed Jan 30, 2024
1 parent 008a358 commit c4cab1b
Show file tree
Hide file tree
Showing 15 changed files with 298 additions and 368 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change log

## 2.1.0 (2024-01-30)

- feat: add `bgGrey` and `bgGray` aliases for `bgBlackBright`
- refactor: optimize source code
- test: refactor tests
- docs: update readme

## 2.0.3 (2023-12-14)

- fix(index.d.ts): use function overload to make the tagged template have the correct type, #16
Expand Down
90 changes: 51 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
ANSI Styling
</a>
</h1>
<div>The Node.js library for formatting text in terminal with ANSI colors & styles</div>
<div>The Node.js library for formatting Terminal and Console output with ANSI colors & styles</div>
</div>

---
Expand All @@ -15,9 +15,8 @@
[![codecov](https://codecov.io/gh/webdiscus/ansis/branch/master/graph/badge.svg?token=H7SFJONX1X)](https://codecov.io/gh/webdiscus/ansis)
[![node](https://img.shields.io/npm/dm/ansis)](https://www.npmjs.com/package/ansis)

Ansis is the tiny and faster compatible alternative to [Chalk][chalk] with even more useful features.
Colorize your output in a terminal with clean syntax,
e.g., ``` green`Hello World!` ``` ``` red`Error!` ``` ``` black.bgYellow`Warning!` ```.
**Ansis** is a **smaller** and **faster** alternative to [Chalk][chalk] with additional useful features and **clean syntax**.\
For example: ``` green`Succeful!` ``` ``` red`Error!` ``` ``` black.bgYellow`Warning!` ``` ``` hex('#E0115F').bold`Ruby` ```.

**Why yet one lib?**\
See [comparison](https://github.com/webdiscus/ansis#compare)
Expand All @@ -34,25 +33,32 @@ and [benchmarks](https://github.com/webdiscus/ansis#benchmark) of most popular N

## 💡 Highlights

- supports both **ESM** and **CommonJS**
- supports **Deno**, **Next.JS** runtime
- up to **x3 faster** than **chalk**, [see benchmarks](#benchmark)
- only **3 KB** dist code
- [standard API](#base-colors) like **chalk**
- default import `import ansis from 'ansis'`, usage `ansis.red('error')`
- [named import](#named-import) `import { red } from 'ansis'`, usage ``` red('error') ```
- [chained syntax](#chained-syntax) `red.bold.underline('text')`
- [nested **template strings**](#nested-syntax) ``` red`R ${green`G`} R` ```
- Supports both **ESM** and **CommonJS**
- Supports **TypeScript**
- Supports **Deno**, **Next.JS** runtimes
- [Standard API](#base-colors) compatible with **Chalk**, switch from **Chalk** to **Ansis** without changing your code
```diff
- import chalk from 'chalk';
+ import chalk, { red } from 'ansis';

chalk.red.bold('Error!'); // <- the original Chalk code works fine
red.bold`Error!`; // <- the same result with Ansis
```
- Default import `import ansis from 'ansis'` or `const ansis = require('ansis')`
- [Named import](#named-import) `import { red } from 'ansis'` or `const { red } = require('ansis')`
- [Chained syntax](#chained-syntax) `red.bold.underline('text')`
- [Nested **template strings**](#nested-syntax) ``` red`R ${green`G`} R` ```
- [ANSI 256 colors](#256-colors) and [Truecolor](#truecolor) (**RGB**, **HEX**) ``` rgb(224, 17, 95)`Ruby` ```, ``` hex('#96C')`Amethyst` ```
- [extending of base colors](#extend-colors) with named **truecolors**
- [Extending of base colors](#extend-colors) with named **truecolors**
- [ANSI codes](#escape-codes) as `open` and `close` property for each
style ``` `Hello ${red.open}World${red.close}!` ```
- [strip ANSI codes](#strip) method `ansis.strip()`
- [correct style break](#new-line) at the `end of line` when used `\n` in string
- supports the [environment variables](#cli-vars) `NO_COLOR` `FORCE_COLOR` and flags `--no-color` `--color`
- **auto detects** color support
- **TypeScript** friendly
- zero dependencies
- [Strip ANSI codes](#strip) method `ansis.strip()`
- [Correct style break](#new-line) at the `end of line` when used `\n` in string
- Supports the [environment variables](#cli-vars) `NO_COLOR` `FORCE_COLOR` and flags `--no-color` `--color`
- **Auto detects** color support
- Up to **x3 faster** than **Chalk**, [see benchmarks](#benchmark) and only **3 KB** dist code
- Doesn't extend `String.prototype`
- Zero dependencies

## ❓Question / Feature Request / Bug

Expand All @@ -76,12 +82,18 @@ You can import default module or named colors with ESM or CommonJS syntax.
import ansis from 'ansis';
// ESM named import
import { red, green, blue } from 'ansis';
```

or

```js
// CommonJS default import
const ansis = require('ansis');
// CommonJS named import
const { red, green, blue } = require('ansis');
```

```js
console.log(ansis.green('Success!'));
console.log(green('Success!'));

Expand Down Expand Up @@ -250,25 +262,25 @@ Output:\
Colors and styles have standard names used by many popular libraries, such
as [chalk][chalk], [colorette][colorette], [kleur][kleur].

| Foreground colors | Background colors | Styles |
|:----------------------|:------------------|--------------------------------------------|
| `black` | `bgBlack` | `dim` (alias`faint`) |
| `red` | `bgRed` | **`bold`** |
| `green` | `bgGreen` | _`italic`_ |
| `yellow` | `bgYellow` | <u>`underline`</u> |
| `blue` | `bgBlue` | <s>`strikethrough`</s> (alias `strike`) |
| `magenta` | `bgMagenta` | `doubleUnderline` (_not widely supported_) |
| `cyan` | `bgCyan` | `overline` (_not widely supported_) |
| `white` | `bgWhite` | `frame` (_not widely supported_) |
| `gray` (alias `grey`) | `bgGray` | `encircle` (_not widely supported_) |
| `blackBright` | `bgBlackBright` | `inverse` |
| `redBright` | `bgRedBright` | `visible` |
| `greenBright` | `bgGreenBright` | `hidden` |
| `yellowBright` | `bgYellowBright` | `reset` |
| `blueBright` | `bgBlueBright` | |
| `magentaBright` | `bgMagentaBright` | |
| `cyanBright` | `bgCyanBright` | |
| `whiteBright` | `bgWhiteBright` | |
| Foreground colors | Background colors | Styles |
|:----------------------|:--------------------------|--------------------------------------------|
| `black` | `bgBlack` | `dim` (alias`faint`) |
| `red` | `bgRed` | **`bold`** |
| `green` | `bgGreen` | _`italic`_ |
| `yellow` | `bgYellow` | <u>`underline`</u> |
| `blue` | `bgBlue` | <s>`strikethrough`</s> (alias `strike`) |
| `magenta` | `bgMagenta` | `doubleUnderline` (_not widely supported_) |
| `cyan` | `bgCyan` | `overline` (_not widely supported_) |
| `white` | `bgWhite` | `frame` (_not widely supported_) |
| `gray` (alias `grey`) | `bgGray` (alias `bgGrey`) | `encircle` (_not widely supported_) |
| `blackBright` | `bgBlackBright` | `inverse` |
| `redBright` | `bgRedBright` | `visible` |
| `greenBright` | `bgGreenBright` | `hidden` |
| `yellowBright` | `bgYellowBright` | `reset` |
| `blueBright` | `bgBlueBright` | |
| `magentaBright` | `bgMagentaBright` | |
| `cyanBright` | `bgCyanBright` | |
| `whiteBright` | `bgWhiteBright` | |

<a id="extend-colors" name="extend-colors" href="#extend-colors"></a>

Expand Down
1 change: 1 addition & 0 deletions bench/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import kleur from 'kleur';
import * as kleurColors from 'kleur/colors';
import picocolors from 'picocolors';
import { Ansis, green, red, yellow, hex } from 'ansis';
//import { Ansis, green, red, yellow, hex } from '../_ignored/index-2.0.3.min.js';

const log = console.log;

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ansis",
"version": "2.0.3",
"description": "Colorize text in terminal or console output with ANSI colors & styles",
"version": "2.1.0",
"description": "Node.js library to colorize text in terminal or console output with ANSI colors & styles",
"keywords": [
"ansi",
"colour",
Expand Down
2 changes: 1 addition & 1 deletion pkg/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ansis",
"version": "2.0.3",
"version": "2.1.0",
"description": "Colorize text in terminal or console output with ANSI colors & styles",
"keywords": [
"ansi",
Expand Down
73 changes: 21 additions & 52 deletions src/ansi-codes.js
Original file line number Diff line number Diff line change
@@ -1,55 +1,5 @@
/**
* @param {Object?} mockThis The mock object of globalThis, used by unit test only.
* @returns {boolean}
*/
export const isSupported = (mockThis) => {
/**
* Detect whether flags exist with `-` or `--` prefix in command-line arguments.
*
* @param {RegExp} regex The RegEx to match all possible flags.
* @return {boolean}
*/
const oneOfFlags = (regex) => !!argv.find((value) => regex.test(value));

const _this = mockThis || globalThis;
const isDeno = _this.Deno != null;
const proc = _this.process || _this.Deno || {};

// Node -> `argv`, Deno -> `args`
const argv = proc.argv || proc.args || [];

let env = {};

try {
// Deno requires the permission for the access to env, use the `--allow-env` flag: deno run --allow-env ./app.js
env = isDeno ? proc.env.toObject() : proc.env || {};
} catch (e) {
// Deno: if interactive permission is not granted, do nothing, no colors
}

const FORCE_COLOR = 'FORCE_COLOR';
const hasForceColor = FORCE_COLOR in env;
const forceColorValue = env[FORCE_COLOR];
const forceColor = forceColorValue === 'true' || parseInt(forceColorValue, 10) > 0;

const isForceDisabled = 'NO_COLOR' in env
|| (hasForceColor && !forceColor)
|| oneOfFlags(/^-{1,2}(no-color|color=false|color=never)$/);

const isForceEnabled = (hasForceColor && forceColor) || oneOfFlags(/^-{1,2}(color|color=true|color=always)$/);

const isWin = (isDeno ? _this.Deno.build.os : proc.platform) === 'win32';
const isTTY = isDeno ? _this.Deno.isatty(1) : proc.stdout && 'isTTY' in proc.stdout;

// when Next.JS runtime is `edge`, process.stdout is undefined, but colors output is supported
// runtime values supported colors: `nodejs`, `edge`, `experimental-edge`
const isNextJS = (env.NEXT_RUNTIME || '').indexOf('edge') > -1;

const isTerm = (isTTY || isNextJS) &&
/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM);

return !isForceDisabled && (isForceEnabled || isTerm || isWin || 'CI' in env);
};
import { clamp, hexToRgb } from './utils.js';
import { isSupported } from './color-support.js';

const noColor = { open: '', close: '' };
const esc = isSupported() ? (open, close) => ({ open: `\x1b[${open}m`, close: `\x1b[${close}m` }) : () => noColor;
Expand Down Expand Up @@ -108,6 +58,8 @@ export const baseStyles = {
bgMagenta: esc(45, 49),
bgCyan: esc(46, 49),
bgWhite: esc(47, 49),
bgGrey: esc(100, 49), // UK spelling alias for bgBlackBright
bgGray: esc(100, 49), // US spelling alias for bgBlackBright
bgBlackBright: esc(100, 49),
bgRedBright: esc(101, 49),
bgGreenBright: esc(102, 49),
Expand All @@ -117,3 +69,20 @@ export const baseStyles = {
bgCyanBright: esc(106, 49),
bgWhiteBright: esc(107, 49),
};

export const styleMethods = {
fg: (code) => fnAnsi256(clamp(code, 0, 255)),
bg: (code) => fnBgAnsi256(clamp(code, 0, 255)),
hex: (hex) => fnRgb(...hexToRgb(hex)),
bgHex: (hex) => fnBgRgb(...hexToRgb(hex)),
rgb: (r, g, b) => fnRgb(
clamp(r, 0, 255),
clamp(g, 0, 255),
clamp(b, 0, 255),
),
bgRgb: (r, g, b) => fnBgRgb(
clamp(r, 0, 255),
clamp(g, 0, 255),
clamp(b, 0, 255),
),
};
52 changes: 52 additions & 0 deletions src/color-support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @param {Object?} mockThis The mock object of globalThis, used by unit test only.
* @returns {boolean}
*/
export const isSupported = (mockThis) => {
/**
* Detect whether flags exist with `-` or `--` prefix in command-line arguments.
*
* @param {RegExp} regex The RegEx to match all possible flags.
* @return {boolean}
*/
const oneOfFlags = (regex) => !!argv.find((value) => regex.test(value));

const _this = mockThis || globalThis;
const isDeno = _this.Deno != null;
const proc = _this.process || _this.Deno || {};

// Node -> `argv`, Deno -> `args`
const argv = proc.argv || proc.args || [];

let env = {};

try {
// Deno requires the permission for the access to env, use the `--allow-env` flag: deno run --allow-env ./app.js
env = isDeno ? proc.env.toObject() : proc.env || {};
} catch (e) {
// Deno: if interactive permission is not granted, do nothing, no colors
}

const FORCE_COLOR = 'FORCE_COLOR';
const hasForceColor = FORCE_COLOR in env;
const forceColorValue = env[FORCE_COLOR];
const forceColor = forceColorValue === 'true' || parseInt(forceColorValue, 10) > 0;

const isForceDisabled = 'NO_COLOR' in env
|| (hasForceColor && !forceColor)
|| oneOfFlags(/^-{1,2}(no-color|color=false|color=never)$/);

const isForceEnabled = (hasForceColor && forceColor) || oneOfFlags(/^-{1,2}(color|color=true|color=always)$/);

const isWin = (isDeno ? _this.Deno.build.os : proc.platform) === 'win32';
const isTTY = isDeno ? _this.Deno.isatty(1) : proc.stdout && 'isTTY' in proc.stdout;

// when Next.JS runtime is `edge`, process.stdout is undefined, but colors output is supported
// runtime values supported colors: `nodejs`, `edge`, `experimental-edge`
const isNextJS = (env.NEXT_RUNTIME || '').indexOf('edge') > -1;

const isTerm = (isTTY || isNextJS) &&
/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM);

return !isForceDisabled && (isForceEnabled || isTerm || isWin || 'CI' in env);
};
7 changes: 5 additions & 2 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface Ansis {
* @param {string | TemplateStringsArray} string
*/
(string: string): string;

(string: TemplateStringsArray, ...parameters: string[]): string;

/**
Expand Down Expand Up @@ -174,8 +175,8 @@ interface Ansis {
readonly magenta: this;
readonly cyan: this;
readonly white: this;
readonly gray: this;
readonly grey: this;
readonly gray: this;
readonly blackBright: this;
readonly redBright: this;
readonly greenBright: this;
Expand All @@ -192,6 +193,7 @@ interface Ansis {
readonly bgMagenta: this;
readonly bgCyan: this;
readonly bgWhite: this;
readonly bgGrey: this;
readonly bgGray: this;
readonly bgBlackBright: this;
readonly bgRedBright: this;
Expand Down Expand Up @@ -239,8 +241,8 @@ type AnsiColors = (
| 'magenta'
| 'cyan'
| 'white'
| 'gray'
| 'grey'
| 'gray'
| 'blackBright'
| 'redBright'
| 'greenBright'
Expand All @@ -257,6 +259,7 @@ type AnsiColors = (
| 'bgMagenta'
| 'bgCyan'
| 'bgWhite'
| 'bgGrey'
| 'bgGray'
| 'bgBlackBright'
| 'bgRedBright'
Expand Down
Loading

0 comments on commit c4cab1b

Please sign in to comment.