Skip to content

Commit

Permalink
chore: optimize code to reduce the size and improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
webdiscus committed Jul 18, 2024
1 parent d700050 commit 84bb0e3
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 158 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change log

## 3.3.1 (2024-07-18)

- chore: optimize code to reduce the size by ~600 bytes,
- chore: minify `index.d.ts` to reduce the size by ~200 bytes,
- chore: increase performance, e.g. using chained styles, 70.000.000 -> 80.000.000 ops/sec

## 3.3.0 (2024-07-14)

- feat(BREAKING CHANGE): remove `old` named import DEPRECATED in `v2.0.0` (2023-11-03).
Expand Down
55 changes: 55 additions & 0 deletions README.npm-src.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<p align="center">
<a href="https://github.com/webdiscus/ansis">
<img width="323" src="https://github.com/webdiscus/ansis/raw/master/docs/img/ansis-logo.png"><br>
ANSI Styling
</a>
</p>

---
[![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)
[![size](https://img.shields.io/bundlephobia/minzip/ansis)](https://bundlephobia.com/package/ansis)

Colorize terminal with ANSI colors & styles, smaller and faster alternative to Chalk.

🚀 [Install and Quick Start](https://github.com/webdiscus/ansis#install)

[Compare features](https://github.com/webdiscus/ansis#compare) with similar packages

📊 [Benchmarks](https://github.com/webdiscus/ansis#benchmark)

📖 [Read full docs on GitHub](https://github.com/webdiscus/ansis)

## Usage

```js
import ansis, { red, green, black, ansi256, hex } from 'ansis';

ansis.cyan('file')
green('Ok')
red`Error`
black.bgYellow`Warning`
ansi256(214)`Orange`
hex('#E0115F').bold('TrueColor')
```

## Highlights

![ANSI demo](https://github.com/webdiscus/ansis/raw/master/docs/img/ansis-demo.png)

- Supports ESM, CJS, TypeScript, Bun, Deno, Next.JS
- Named import: `import ansis, { red, bold, hex } from 'ansis'`
- Chained syntax: `red.bold.underline('text')`
- Nested template strings: ``` red`RED ${green`GREEN`} RED` ```
- ANSI styles: `dim` **`bold`** _`italic`_ <u>`underline`</u> <s>`strikethrough`</s>
- ANSI 16 colors: ``` red`Error!` ``` ``` redBright`Error!` ``` ``` bgRed`Error!` ``` ``` bgRedBright`Error!` ```
- ANSI 256 colors: ``` fg(56)`violet` ``` ``` bg(208)`orange` ```
- TrueColor: ``` rgb(224, 17, 95)`Ruby` ``` ``` hex('#96C')`Amethyst` ```
- Color fallback: TrueColor → 256 colors → 16 colors → no colors
- Raw ANSI codes: ``` `foo ${red.open}bar{red.close} foo` ```
- Strip ANSI codes: `ansis.strip()`
- Detect color support: `ansis.isSupported()`
- Supports CLI: `NO_COLOR` `FORCE_COLOR` `--no-color` `--color`
- Correct style break at the `end of line` when used `\n`
- Doesn't extend `String.prototype`
- No dependencies
36 changes: 3 additions & 33 deletions README.npm.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,6 @@ Colorize terminal with ANSI colors & styles, smaller and faster alternative to C

📖 [Read full docs on GitHub](https://github.com/webdiscus/ansis)

## Usage

```js
import ansis, { red, green, black, ansi256, hex } from 'ansis';

ansis.cyan('file')
green('Ok')
red`Error`
black.bgYellow`Warning`
ansi256(214)`Orange`
hex('#E0115F').bold('TrueColor')
```

## Highlights

![ANSI demo](https://github.com/webdiscus/ansis/raw/master/docs/img/ansis-demo.png)

- Supports ESM, CJS, TypeScript, Bun, Deno, Next.JS
- Named import: `import ansis, { red, bold, hex } from 'ansis'`
- Chained syntax: `red.bold.underline('text')`
- Nested template strings: ``` red`RED ${green`GREEN`} RED` ```
- ANSI styles: `dim` **`bold`** _`italic`_ <u>`underline`</u> <s>`strikethrough`</s>
- ANSI 16 colors: ``` red`Error!` ``` ``` redBright`Error!` ``` ``` bgRed`Error!` ``` ``` bgRedBright`Error!` ```
- ANSI 256 colors: ``` fg(56)`violet` ``` ``` bg(208)`orange` ```
- TrueColor: ``` rgb(224, 17, 95)`Ruby` ``` ``` hex('#96C')`Amethyst` ```
- Color fallback: TrueColor → 256 colors → 16 colors → no colors
- Raw ANSI codes: ``` `foo ${red.open}bar{red.close} foo` ```
- Strip ANSI codes: `ansis.strip()`
- Detect color support: `ansis.isSupported()`
- Supports CLI: `NO_COLOR` `FORCE_COLOR` `--no-color` `--color`
- Correct style break at the `end of line` when used `\n`
- Doesn't extend `String.prototype`
- No dependencies
---

![ANSI demo](https://github.com/webdiscus/ansis/raw/master/docs/img/screenshot-readme-npm.png)
60 changes: 30 additions & 30 deletions bench/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ let fixture;
log(hex('#F88').inverse.bold` -= Benchmark =- `);

bench('Using 1 style (red)').
add(packages['chalk'], () => chalk.red('foo')).
add(packages['ansis'], () => ansis.red('foo')).
add(packages['colors'], () => colorsJs.red('foo')).
add(packages['colorette'], () => colorette.red('foo')).
add(packages['picocolors'], () => picocolors.red('foo')).
Expand All @@ -99,11 +101,11 @@ bench('Using 1 style (red)').
add(packages['ansi-colors'], () => ansiColors.red('foo')).
add(packages['kleur'], () => kleur.red('foo')).
add(packages['kolorist'], () => kolorist.red('foo')).
add(packages['chalk'], () => chalk.red('foo')).
add(packages['ansis'], () => ansis.red('foo')).
run();

bench(`Using 2 styles (red, bold)`).
add(packages['chalk'], () => chalk.red.bold('foo')).
add(packages['ansis'], () => ansis.red.bold('foo')).
add(packages['colors'], () => colorsJs.red.bold('foo')).
add(packages['colorette'], () => colorette.red(colorette.bold('foo'))).
add(packages['picocolors'], () => picocolors.red(picocolors.bold('foo'))).
Expand All @@ -112,11 +114,11 @@ bench(`Using 2 styles (red, bold)`).
add(packages['ansi-colors'], () => ansiColors.red.bold('foo')).
add(packages['kleur'], () => kleur.red().bold('foo')).
add(packages['kolorist'], () => kolorist.red(kolorist.bold('foo'))).
add(packages['chalk'], () => chalk.red.bold('foo')).
add(packages['ansis'], () => ansis.red.bold('foo')).
run();

bench(`Using 3 styles (red, bold, underline)`).
add(packages['chalk'], () => chalk.red.bold.underline('foo')).
add(packages['ansis'], () => ansis.red.bold.underline('foo')).
add(packages['colors'], () => colorsJs.red.bold.underline('foo')).
add(packages['colorette'], () => colorette.red(colorette.bold(colorette.underline('foo')))).
add(packages['picocolors'], () => picocolors.red(picocolors.bold(picocolors.underline('foo')))).
Expand All @@ -125,27 +127,27 @@ bench(`Using 3 styles (red, bold, underline)`).
add(packages['ansi-colors'], () => ansiColors.red.bold.underline('foo')).
add(packages['kleur'], () => kleur.red().bold().underline('foo')).
add(packages['kolorist'], () => kolorist.red(kolorist.bold(kolorist.underline('foo')))).
add(packages['chalk'], () => chalk.red.bold.underline('foo')).
add(packages['ansis'], () => ansis.red.bold.underline('foo')).
run();

bench(`Using 5 styles (bgWhite red, bold, italic, underline)`).
add(packages['colors'], () => colorsJs.bgWhite.red.bold.italic.underline('foo')).
add(packages['colorette'], () => colorette.bgWhite(colorette.red(colorette.bold(colorette.italic(colorette.underline('foo')))))).
add(packages['picocolors'], () => picocolors.bgWhite(picocolors.red(picocolors.bold(picocolors.italic(picocolors.underline('foo')))))).
add(packages['cli-color'], () => cliColor.bgWhite.red.bold.italic.underline('foo')).
add(packages['colors-cli'], () => colorCli.white_b.red.bold.italic.underline('foo')).
add(packages['ansi-colors'], () => ansiColors.bgWhite.red.bold.italic.underline('foo')).
add(packages['kleur'], () => kleur.bgWhite().red().bold().italic().underline()('foo')).
add(packages['kolorist'], () => kolorist.bgWhite(kolorist.red(kolorist.bold(kolorist.italic(kolorist.underline('foo')))))).
add(packages['chalk'], () => chalk.bgWhite.red.bold.italic.underline('foo')).
add(packages['ansis'], () => ansis.bgWhite.red.bold.italic.underline('foo')).
bench(`Using 4 styles (bgWhite red, bold, underline)`).
add(packages['chalk'], () => chalk.bgWhite.red.bold.underline('foo')).
add(packages['ansis'], () => ansis.bgWhite.red.bold.underline('foo')).
add(packages['colors'], () => colorsJs.bgWhite.red.bold.underline('foo')).
add(packages['colorette'], () => colorette.bgWhite(colorette.red(colorette.bold(colorette.underline('foo'))))).
add(packages['picocolors'], () => picocolors.bgWhite(picocolors.red(picocolors.bold(picocolors.underline('foo'))))).
add(packages['cli-color'], () => cliColor.bgWhite.red.bold.underline('foo')).
add(packages['colors-cli'], () => colorCli.white_b.red.bold.underline('foo')).
add(packages['ansi-colors'], () => ansiColors.bgWhite.red.bold.underline('foo')).
add(packages['kleur'], () => kleur.bgWhite().red().bold().underline()('foo')).
add(packages['kolorist'], () => kolorist.bgWhite(kolorist.red(kolorist.bold(kolorist.underline('foo'))))).
run();

// Colorette bench
// https://github.com/jorgebucaran/colorette/blob/main/bench/index.js
fixture = createFixture(vendors, coloretteBench);
bench('Colorette bench').
add(vendors[8].name, () => fixture[8](vendors[8].lib)).
add(vendors[9].name, () => fixture[9](vendors[9].lib)).
add(vendors[0].name, () => fixture[0](vendors[0].lib)).
add(vendors[1].name, () => fixture[1](vendors[1].lib)).
add(vendors[2].name, () => fixture[2](vendors[2].lib)).
Expand All @@ -154,12 +156,12 @@ bench('Colorette bench').
add(vendors[5].name, () => fixture[5](vendors[5].lib)).
add(vendors[6].name, () => fixture[6](vendors[6].lib)).
add(vendors[7].name, () => fixture[7](vendors[7].lib)).
add(vendors[8].name, () => fixture[8](vendors[8].lib)).
add(vendors[9].name, () => fixture[9](vendors[9].lib)).
run();

// Base colors
bench('Base colors').
add(packages['chalk'], () => baseColors.forEach((style) => chalk[style]('foo'))).
add(packages['ansis'], () => baseColors.forEach((style) => ansis[style]('foo'))).
add(packages['colors'], () => baseColors.forEach((style) => colorsJs[style]('foo'))).
add(packages['colorette'], () => baseColors.forEach((style) => colorette[style]('foo'))).
add(packages['picocolors'], () => baseColors.forEach((style) => picocolors[style]('foo'))).
Expand All @@ -168,12 +170,12 @@ bench('Base colors').
add(packages['ansi-colors'], () => baseColors.forEach((style) => ansiColors[style]('foo'))).
add('kleur/colors', () => baseColors.forEach((style) => kleurColors[style]('foo'))).
add(packages['kleur'], () => baseColors.forEach((style) => kleur[style]('foo'))).
add(packages['chalk'], () => baseColors.forEach((style) => chalk[style]('foo'))).
add(packages['ansis'], () => baseColors.forEach((style) => ansis[style]('foo'))).
run();

// Chained styles
bench('Chained styles').
add(packages['chalk'], () => baseColors.forEach((style) => chalk[style].bold.underline.italic('foo'))).
add(packages['ansis'], () => baseColors.forEach((style) => ansis[style].bold.underline.italic('foo'))).
add(packages['colors'], () => baseColors.forEach((style) => colorsJs[style].bold.underline.italic('foo'))).
add('colorette (not supported)', () => baseColors.forEach((style) => colorette[style].bold.underline.italic('foo'))).
add('picocolors (not supported)', () =>
Expand All @@ -185,13 +187,13 @@ bench('Chained styles').
add('kleur/colors (not supported)', () =>
baseColors.forEach((style) => kleurColors[style].bold.underline.italic('foo')),
).
// add(packages['kleur'], () => baseColors.forEach((style) => kleur[style]().bold().underline().italic('foo'))). // alternate syntax
add(packages['chalk'], () => baseColors.forEach((style) => chalk[style].bold.underline.italic('foo'))).
add(packages['ansis'], () => baseColors.forEach((style) => ansis[style].bold.underline.italic('foo'))).
add(packages['kleur'], () => baseColors.forEach((style) => kleur[style]().bold().underline().italic('foo'))). // alternate syntax
run();

// Nested calls
bench('Nested calls').
add(packages['chalk'], () => baseColors.forEach((style) => chalk[style](chalk.bold(chalk.underline(chalk.italic('foo')))))).
add(packages['ansis'], () => baseColors.forEach((style) => ansis[style](ansis.bold(ansis.underline(ansis.italic('foo')))))).
add(packages['colors'], () =>
baseColors.forEach((style) => colorsJs[style](colorsJs.bold(colorsJs.underline(colorsJs.italic('foo'))))),
).
Expand All @@ -216,13 +218,13 @@ bench('Nested calls').
),
).
add(packages['kleur'], () => baseColors.forEach((style) => kleur[style](kleur.bold(kleur.underline(kleur.italic('foo')))))).
add(packages['chalk'], () => baseColors.forEach((style) => chalk[style](chalk.bold(chalk.underline(chalk.italic('foo')))))).
add(packages['ansis'], () => baseColors.forEach((style) => ansis[style](ansis.bold(ansis.underline(ansis.italic('foo')))))).
run();

// Nested styles
fixture = createFixture(vendors, nestedFixture);
bench('Nested styles').
add(packages['chalk'], () => fixture[7](chalk)).
add(packages['ansis'], () => fixture[8](ansis)).
add(packages['colors'], () => fixture[9](colorsJs)).
add(packages['colorette'], () => fixture[0](colorette)).
add(packages['picocolors'], () => fixture[1](picocolors)).
Expand All @@ -231,13 +233,13 @@ bench('Nested styles').
add(packages['ansi-colors'], () => fixture[4](ansiColors)).
add('kleur/colors', () => fixture[5](kleurColors)).
add(packages['kleur'], () => fixture[6](kleur)).
add(packages['chalk'], () => fixture[7](chalk)).
add(packages['ansis'], () => fixture[8](ansis)).
run();

// Deep nested styles
fixture = createFixture(vendors, deepNestedFixture);
bench('Deep nested styles').
add(packages['chalk'], () => fixture[7](chalk)).
add(packages['ansis'], () => fixture[8](ansis)).
add(packages['colors'], () => fixture[9](colorsJs)).
add(packages['colorette'], () => fixture[0](colorette)).
add(packages['picocolors'], () => fixture[1](picocolors)).
Expand All @@ -246,8 +248,6 @@ bench('Deep nested styles').
add(packages['ansi-colors'], () => fixture[4](ansiColors)).
add('kleur/colors', () => fixture[5](kleurColors)).
add(packages['kleur'], () => fixture[6](kleur)).
add(packages['chalk'], () => fixture[7](chalk)).
add(packages['ansis'], () => fixture[8](ansis)).
run();

// Check support of correct break style at new line
Expand Down
Binary file added docs/img/screenshot-readme-npm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ansis",
"version": "3.3.0",
"version": "3.3.1",
"description": "Colorize terminal output with ANSI colors & styles",
"keywords": [
"ansi",
Expand Down
2 changes: 1 addition & 1 deletion package.npm.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ansis",
"version": "3.3.0",
"version": "3.3.1",
"description": "Colorize terminal output with ANSI colors & styles",
"keywords": [
"ansi",
Expand Down
39 changes: 24 additions & 15 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ import { minify } from 'terser';
const ecma = 2019;

export default [
// remove comments from d.ts file
{
input: 'src/index.d.ts',
output: [
{
file: 'dist/index.d.ts',
format: 'es',
},
],
plugins: [
cleanup({ extensions: ['ts'] }),
dts(),
],
},

{
input: 'src/index.js',
output: [
Expand Down Expand Up @@ -39,27 +54,21 @@ export default [
{
src: 'src/index.mjs',
dest: 'dist/',
transform: async (contents, name) => (await minify(contents.toString())).code,
transform: async (contents, name) => (await minify(contents.toString(), { ecma: 2015 })).code,
},

// minify d.ts file generated after cleanup
{
src: 'dist/index.d.ts',
dest: 'dist/',
transform: (contents, name) => { return contents.toString().replaceAll(/\n/g, '');},
},

{ src: 'package.npm.json', dest: 'dist/', rename: 'package.json' },
{ src: 'README.npm.md', dest: 'dist/', rename: 'README.md' },
{ src: 'LICENSE', dest: 'dist/' },
],
}),
],
},

{
input: 'src/index.d.ts',
output: [
{
file: 'dist/index.d.ts',
format: 'es',
},
],
plugins: [
cleanup({ extensions: ['ts'] }),
dts(),
],
},
];
9 changes: 0 additions & 9 deletions src/ansi-codes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ const esc = isSupported ? (open, close) => ({ open: `\x1b[${open}m`, close: `\x1
const closeCode = 39;
const bgCloseCode = 49;

const ESC = '\x1b';
const BEL = '\x07';
const ZWSP = '\u200B';

// defaults, true color
let fnAnsi256 = (code) => esc(`38;5;${code}`, closeCode);
let fnBgAnsi256 = (code) => esc(`48;5;${code}`, bgCloseCode);
Expand Down Expand Up @@ -122,11 +118,6 @@ export const styleMethods = {
// note: the `...` operator is too slow
//bgHex: (hex) => fnBgRgb(...hexToRgb(hex)),
bgHex: createHexFn(fnBgRgb),

// reserved for future: hyperlink (OSC 8) is not widely supported (works in iTerm)
// link: hasColor
// ? (url) => ({ open: ESC + ']8;;' + url + BEL, close: ESC + ']8;;' + BEL })
// : (url) => ({ open: '', close: `(${ZWSP}${url}${ZWSP})` }),
};

export const rgb = fnRgb;
2 changes: 1 addition & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type ColorExtend = Record<string, string | { open: string, close: string }>
type ColorExtend = Record<string, string | { open: string, close: string }>;

interface Ansis {
/**
Expand Down
Loading

0 comments on commit 84bb0e3

Please sign in to comment.