diff --git a/.codecov.yml b/.codecov.yml
index c346db7..8f1cab3 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -8,4 +8,4 @@ coverage:
target: 90%
ignore:
- - test/.*
+ - test/**/*
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 38700cf..cc00edd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -15,7 +15,9 @@ jobs:
strategy:
matrix:
os: [ ubuntu-latest ]
- node-version: [ 14, 16, 18, 20 ]
+ # rollup require node >= 18
+ #node-version: [ 14, 16, 18, 20 ]
+ node-version: [ 18, 20 ]
runs-on: ${{ matrix.os }}
steps:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5970855..bc865c8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,15 @@
# Change log
+## 2.0.1 (2023-11-03)
+
+- fix: missing exports of ansis.strip() and ansis.export() functions (issue was introduced in v2.0.0)
+- refactor: optimize code to reduce distributed size
+- test: add test for generated npm package in CJS and ESM mode
+- test: add test for env variables and CLI flags
+- test: add test to detect Deno
+- test: add test to detect Next.js runtime
+- docs: update readme
+
## 2.0.0 (2023-11-03)
- feat: add supports the Deno
diff --git a/README.md b/README.md
index e2f5df6..630f40a 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ and [benchmarks](https://github.com/webdiscus/ansis#benchmark) of most popular N
- supports both **ESM** and **CommonJS**
- supports **Deno**, **Next.JS** runtime
- up to **x3 faster** than **chalk**, [see benchmarks](#benchmark)
-- dist code is only **5 KB** incl. named import of all styles
+- 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') ```
@@ -132,6 +132,16 @@ import { red, hex, italic } from 'ansis';
red.bold('text');
```
+Default import and named import can be combined.
+
+```js
+// default and named import
+import ansis, { red } from 'ansis';
+
+const redText = red('text'); // colorized ANSI string
+const text = ansis.strip(redText); // pure string without ANSI codes
+```
+
## Template literals
@@ -454,61 +464,64 @@ Defaults, the output in terminal console is colored and output in a file is unco
### Environment variables
-_example.js_
+To force disable or enable colored output use environment variables `NO_COLOR` and `FORCE_COLOR`.
-```js
-import ansis from 'ansis';
+The `NO_COLOR` variable should be presents with any not empty value.
+The value is not important, e.g., `NO_COLOR=1` `NO_COLOR=true` disable colors.
+See standard description by [NO_COLOR](https://no-color.org/).
-console.log(ansis.red`COLOR`);
-```
+The `FORCE_COLOR` variable should be presents with one of values:\
+`FORCE_COLOR=0` force disable colors\
+`FORCE_COLOR=1` force enable colors
-```
-$ node example.js #=> color
-$ node example.js > log.txt #=> no color
+For example, _app.js_:
+
+```js
+import { red } from 'ansis';
+
+console.log(red`red color`);
```
-To force disable or enable colored output use environment variables `NO_COLOR` and `FORCE_COLOR`.
+Execute the script in a terminal:
```
-$ NO_COLOR=1 node example.js #=> force disable colors
-$ FORCE_COLOR=0 node example.js #=> force disable colors
-$ FORCE_COLOR=1 node example.js > log.txt #=> force enable colors
+$ node app.js # colored output in terminal
+$ node app.js > log.txt # output in file without ANSI codes
+
+$ NO_COLOR=1 node app.js # force disable colors, non colored output in terminal
+$ FORCE_COLOR=0 node app.js # force disable colors, non colored output in terminal
+$ FORCE_COLOR=1 node app.js > log.txt # force enable colors, output in file with ANSI codes
```
-> **Note**
->
-> The `NO_COLOR` variable should be presents with any not empty value.
-> The value is not important, see standard description by [NO_COLOR](https://no-color.org/).\
-> `NO_COLOR=1` `NO_COLOR=true` disable colors
->
-> The `FORCE_COLOR` variable should be presents with one of values:\
-> `FORCE_COLOR=0` force disable colors\
-> `FORCE_COLOR=1` force enable colors
+### CLI arguments
-### Arguments for executable script
+Use arguments `--no-color` or `--color=false` to disable colors and `--color` to enable ones.
-If you have an executable script.\
-_example.js_
+For example, an executable script _app.js_:
```js
#!/usr/bin/env node
-import ansis from 'ansis';
+import { red } from 'ansis';
-console.log(ansis.red`COLOR`);
+console.log(red`red color`);
```
-Use arguments `--no-color` or `--color=false` to disable colors and `--color` to enable ones.
+Execute the script in a terminal:
```
-$ ./example.js #=> color
-$ ./example.js --no-color #=> no color
-$ ./example.js --color=false #=> no color
+$ ./app.js # colored output in terminal
+$ ./app.js --no-color # non colored output in terminal
+$ ./app.js --color=false # non colored output in terminal
-$ ./example.js > log.txt #=> no color
-$ ./example.js --color > log.txt #=> color
-$ ./example.js --color=true > log.txt #=> color
+$ ./app.js > log.txt # output in file without ANSI codes
+$ ./app.js --color > log.txt # output in file with ANSI codes
+$ ./app.js --color=true > log.txt # output in file with ANSI codes
```
+> **Warning**
+>
+> The command line arguments have a higher priority than environment variable.
+
## Comparison of most popular libraries
@@ -523,7 +536,7 @@ $ ./example.js --color=true > log.txt #=> color
| [`picocolors`][picocolors]
**2.6KB**
`❌ named import` | **standard**
`8` colors | ❌ | ❌ | ❌ | ❌ | ❌ | `NO_COLOR`
`FORCE_COLOR`
`--no-color`
`--color` |
| [`kleur`][kleur]
**2.7KB**
`✅ named import` | **standard**
`8` colors | ❌ | ❌ | ✅ | ❌ | ❌ | only
`NO_COLOR`
`FORCE_COLOR` |
| [`chalk`][chalk]
**15KB**
`❌ named import` | **standard**
`16` colors | ✅ | ✅ | ✅ | ❌ | ✅ | `NO_COLOR`
`FORCE_COLOR`
`--no-color`
`--color` |
-| [`ansis`][ansis]
**5KB**
`✅ named import` | **standard**
`16` colors | ✅ | ✅ | ✅ | ✅ | ✅ | `NO_COLOR`
`FORCE_COLOR`
`--no-color`
`--color` |
+| [`ansis`][ansis]
**3.2KB**
`✅ named import` | **standard**
`16` colors | ✅ | ✅ | ✅ | ✅ | ✅ | `NO_COLOR`
`FORCE_COLOR`
`--no-color`
`--color` |
> **Note**
>
@@ -577,19 +590,12 @@ npm run demo
-## Benchmark
-
-### Setup
+## Run benchmark
```bash
git clone https://github.com/webdiscus/ansis.git
-cd ./ansis/bench
+cd ./ansis
npm i
-```
-
-### Run benchmark
-
-```bash
npm run bench
```
diff --git a/examples/ansi256.js b/examples/ansi256.js
index 2af6fd2..047b1d4 100755
--- a/examples/ansi256.js
+++ b/examples/ansi256.js
@@ -1,4 +1,4 @@
-import { fg, bg } from '../src/index.js';
+import { fg, bg } from 'ansis';
let out;
let n;
diff --git a/examples/ansis-logo.js b/examples/ansis-logo.js
index e3ca1b0..92e4f48 100644
--- a/examples/ansis-logo.js
+++ b/examples/ansis-logo.js
@@ -1,4 +1,4 @@
-import ansis from '../src/index.js';
+import ansis from 'ansis';
const colorizeASCII = ({ ascii, data }, paddingLeft = 5) => {
// start index in logo is 1, because first char is \n
diff --git a/examples/ansis-styles-demo.js b/examples/ansis-styles-demo.js
index 4cc1407..abbac8a 100644
--- a/examples/ansis-styles-demo.js
+++ b/examples/ansis-styles-demo.js
@@ -15,7 +15,7 @@ import {
underline,
white, whiteBright,
yellow, yellowBright,
-} from '../src/index.js';
+} from 'ansis';
const out = `${bold`bold`} ${dim`dim`} ${italic`italic`} ${underline`underline`} ${strikethrough`strikethrough`} ${inverse`inverse`} ${bold.italic.underline.strike`bold italic underline strike`}` +
'\n' +
diff --git a/examples/index.js b/examples/index.js
index 327dd29..1100f8e 100755
--- a/examples/index.js
+++ b/examples/index.js
@@ -3,7 +3,8 @@
import chalk from 'chalk';
import ansis, {
- Ansis, red,
+ Ansis,
+ red,
green,
blue,
cyan,
@@ -16,7 +17,7 @@ import ansis, {
inverse,
visible,
hex,
-} from '../src/index.js';
+} from 'ansis';
import { ansi256Table } from './ansi256.js';
import { ansisLogo } from './ansis-logo.js';
@@ -189,7 +190,7 @@ ansis.extend({
log(ansis.pink('pink'));
log(ansis.orange('orange'));
log(ansis.orange.bold('orange'));
-//log(ansis.bold.orange('orange')); // => error
+//log(ansis.bold.orange('orange')); // => error, but by 2nd extension it works, see the `side effect` below
/**
* Problem description
@@ -227,7 +228,8 @@ ansis2.extend({
});
log(ansis2.pink('pink'));
-log(ansis2.bold.orange('orange'));
+// SIDE EFFECT: here works only because the ansis is already extended: ansis.extend({orange:'..'}), see above
+log(ansis2.italic.orange('orange'));
/**
* Misc
diff --git a/examples/package.json b/examples/package.json
new file mode 100644
index 0000000..a1599b0
--- /dev/null
+++ b/examples/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "demo",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "demo": "node ./"
+ }
+}
diff --git a/package.json b/package.json
index d307bba..3892854 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ansis",
- "version": "2.0.0",
+ "version": "2.0.1",
"description": "Colorize text in terminal or console output with ANSI colors & styles",
"keywords": [
"ansi",
@@ -59,38 +59,46 @@
"types": "./src/index.d.ts",
"exports": {
".": {
- "import": "./index.js",
+ "import": "./index.mjs",
"require": "./index.js"
},
"./colors": {
- "import": "./index.js",
+ "import": "./index.mjs",
"require": "./index.js"
}
},
"scripts": {
- "demo": "node ./examples/index.js",
- "bench": "node ./bench/index.js",
"build": "rollup -c",
+ "postinstall": "npm run build && npm i ./dist -D",
+ "demo": "node --experimental-modules ./examples/index.js",
+ "bench": "(cd ./bench/ && npm install); node ./bench/index.js",
"test": "NODE_OPTIONS=--experimental-vm-modules jest --detectOpenHandles",
+ "test:unit": "NODE_OPTIONS=--experimental-vm-modules jest --detectOpenHandles --runTestsByPath ./test/unit.test.js",
+ "test:index": "NODE_OPTIONS=--experimental-vm-modules jest --detectOpenHandles --runTestsByPath ./test/index.test.js",
+ "test:flags": "NODE_OPTIONS=--experimental-vm-modules jest --detectOpenHandles --runTestsByPath ./test/flags.test.js",
+ "test:package": "NODE_OPTIONS=--experimental-vm-modules jest --detectOpenHandles --runTestsByPath ./test/package.test.js",
+ "test:cjs": "node ./test/package/cjs/test.cjs",
+ "test:esm": "node ./test/package/esm/test.mjs",
"test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --detectOpenHandles --collectCoverage",
- "publish:public": "rollup -c && npm publish ./dist --access public",
- "publish:beta": "rollup -c && npm publish ./dist --tag beta"
+ "publish:public": "(npm run build) && npm publish ./dist --access public",
+ "publish:beta": "(npm run build) && npm publish ./dist --tag beta"
},
- "files": [
- "dist"
- ],
"engines": {
"node": ">=12.13"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.23.2",
+ "@rollup/plugin-replace": "^5.0.5",
"@rollup/plugin-terser": "^0.4.4",
"@types/jest": "^29.5.7",
+ "@types/node": "^20.8.10",
+ "ansis": "file:dist",
"jest": "^29.7.0",
"prettier": "^3.0.3",
"rollup": "^4.2.0",
"rollup-plugin-copy": "^3.5.0",
- "rollup-plugin-dts": "^6.1.0"
+ "rollup-plugin-dts": "^6.1.0",
+ "terser": "^5.24.0"
}
}
diff --git a/package/package.json b/pkg/package.json
similarity index 88%
rename from package/package.json
rename to pkg/package.json
index 7dbf434..17c5620 100644
--- a/package/package.json
+++ b/pkg/package.json
@@ -1,6 +1,6 @@
{
"name": "ansis",
- "version": "2.0.0",
+ "version": "2.0.1",
"description": "Colorize text in terminal or console output with ANSI colors & styles",
"keywords": [
"ansi",
@@ -54,12 +54,12 @@
"types": "./index.d.ts",
"exports": {
".": {
- "import": "./index.js",
- "require": "./index.js"
+ "require": "./index.js",
+ "import": "./index.mjs"
},
"./colors": {
- "import": "./index.js",
- "require": "./index.js"
+ "require": "./index.js",
+ "import": "./index.mjs"
}
},
"engines": {
@@ -68,6 +68,7 @@
"files": [
"index.d.ts",
"index.js",
+ "index.mjs",
"package.json",
"LICENSE",
"README.md"
diff --git a/rollup.config.js b/rollup.config.js
index 44cf18e..4f89970 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,6 +1,8 @@
import terser from '@rollup/plugin-terser';
+import replace from '@rollup/plugin-replace';
import copy from 'rollup-plugin-copy';
import dts from 'rollup-plugin-dts';
+import { minify } from 'terser';
// last ECMA version compatible with node.js 12
const ecma = 2019;
@@ -17,6 +19,12 @@ export default [
},
],
plugins: [
+ replace({
+ preventAssignment: false, // allow modifying exports
+ // the order of exports is other than is needed
+ 'exports.Ansis = Ansis': 'module.exports = ansis', // firstly must be defined default export
+ 'exports.default = ansis': 'module.exports.Ansis = Ansis', // then on the next line can be named export
+ }),
terser({
ecma,
compress: {
@@ -27,7 +35,12 @@ export default [
}),
copy({
targets: [
- { src: 'package/package.json', dest: 'dist/' },
+ {
+ src: 'src/index.mjs',
+ dest: 'dist/',
+ transform: async (contents, name) => (await minify(contents.toString())).code,
+ },
+ { src: 'pkg/package.json', dest: 'dist/' },
{ src: 'README.md', dest: 'dist/' },
{ src: 'LICENSE', dest: 'dist/' },
],
diff --git a/src/index.js b/src/index.js
index e9e7fc7..893811a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -118,8 +118,8 @@ const wrap = (strings, values, props) => {
};
const styleMethods = {
- ansi: (code) => fnAnsi256(clamp(code, 0, 255)),
- bgAnsi: (code) => fnBgAnsi256(clamp(code, 0, 255)),
+ 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(
@@ -146,81 +146,15 @@ for (let name in styleMethods) {
};
}
+// TODO: DEPRECATE ansi and bgAnsi
// define method aliases for compatibility with chalk
-styles.ansi256 = styles.fg = styles.ansi;
-styles.bgAnsi256 = styles.bg = styles.bgAnsi;
+styles.ansi256 = styles.ansi = styles.fg;
+styles.bgAnsi256 = styles.bgAnsi = styles.bg;
const ansis = new Ansis();
-export { Ansis, ansis as default };
-
-export const {
- // color functions
- ansi256,
- ansi,
- fg,
- bgAnsi256,
- bgAnsi,
- bg,
- rgb,
- bgRgb,
- hex,
- bgHex,
-
- // misc
- reset,
- inverse,
- hidden,
- visible,
-
- // styles
- bold,
- dim,
- faint,
- italic,
- underline,
- doubleUnderline,
- strikethrough,
- strike,
- frame,
- encircle,
- overline,
-
- // foreground colors
- black,
- red,
- green,
- yellow,
- blue,
- magenta,
- cyan,
- white,
- gray,
- grey,
- blackBright,
- redBright,
- greenBright,
- yellowBright,
- blueBright,
- magentaBright,
- cyanBright,
- whiteBright,
-
- // background colors
- bgBlack,
- bgRed,
- bgGreen,
- bgYellow,
- bgBlue,
- bgMagenta,
- bgCyan,
- bgWhite,
- bgBlackBright,
- bgRedBright,
- bgGreenBright,
- bgYellowBright,
- bgBlueBright,
- bgMagentaBright,
- bgCyanBright,
- bgWhiteBright,
-} = ansis;
+// for distribution code, the export will be replaced (via @rollup/plugin-replace) with the following export:
+// module.exports = ansis;
+// module.exports.Ansis = Ansis;
+
+export { ansis as default, Ansis };
diff --git a/src/index.mjs b/src/index.mjs
new file mode 100644
index 0000000..e5cb236
--- /dev/null
+++ b/src/index.mjs
@@ -0,0 +1,74 @@
+import ansis, { Ansis } from './index.js';
+
+export { Ansis, ansis as default };
+
+export const {
+ // color functions
+ ansi256,
+ ansi,
+ fg,
+ bgAnsi256,
+ bgAnsi,
+ bg,
+ rgb,
+ bgRgb,
+ hex,
+ bgHex,
+
+ // misc
+ reset,
+ inverse,
+ hidden,
+ visible,
+
+ // styles
+ bold,
+ dim,
+ faint,
+ italic,
+ underline,
+ doubleUnderline,
+ strikethrough,
+ strike,
+ frame,
+ encircle,
+ overline,
+
+ // foreground colors
+ black,
+ red,
+ green,
+ yellow,
+ blue,
+ magenta,
+ cyan,
+ white,
+ gray,
+ grey,
+ blackBright,
+ redBright,
+ greenBright,
+ yellowBright,
+ blueBright,
+ magentaBright,
+ cyanBright,
+ whiteBright,
+
+ // background colors
+ bgBlack,
+ bgRed,
+ bgGreen,
+ bgYellow,
+ bgBlue,
+ bgMagenta,
+ bgCyan,
+ bgWhite,
+ bgBlackBright,
+ bgRedBright,
+ bgGreenBright,
+ bgYellowBright,
+ bgBlueBright,
+ bgMagentaBright,
+ bgCyanBright,
+ bgWhiteBright,
+} = ansis;
diff --git a/src/package.json b/src/package.json
new file mode 100644
index 0000000..79790cd
--- /dev/null
+++ b/src/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "ansis-src",
+ "description": "",
+ "sideEffects": false,
+ "type": "module"
+}
diff --git a/test/cli/output.js b/test/cli/output.js
index 2a9e25c..d1da2f7 100644
--- a/test/cli/output.js
+++ b/test/cli/output.js
@@ -1,14 +1,16 @@
-import ansis from '../../src/index.js';
-const c = ansis;
+#!/usr/bin/env node
+import { red, rgb, bgRgb, hex, bgHex } from '../../src/index.mjs';
+
+// test output into terminal, depends on flags (--no-color, --color) and environment variables (NO_COLOR, FORCE_COLOR)
console.log(
- c.red('red') +
- '|' +
- c.rgb(80, 80, 80)('rgb') +
- '|' +
- c.bgRgb(80, 80, 80)('bgRgb') +
- '|' +
- c.hex('#fff')('hex') +
- '|' +
- c.bgHex('#fff')('bgHex')
+ red('red') +
+ '|' +
+ rgb(80, 80, 80)('rgb') +
+ '|' +
+ bgRgb(80, 80, 80)('bgRgb') +
+ '|' +
+ hex('#fff')('hex') +
+ '|' +
+ bgHex('#fff')('bgHex'),
);
\ No newline at end of file
diff --git a/test/cli/package.json b/test/cli/package.json
new file mode 100644
index 0000000..1239544
--- /dev/null
+++ b/test/cli/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "ansis-esm",
+ "description": "ESM version",
+ "type": "module"
+}
diff --git a/test/flags.test.js b/test/flags.test.js
new file mode 100644
index 0000000..368d011
--- /dev/null
+++ b/test/flags.test.js
@@ -0,0 +1,88 @@
+import path from 'path';
+import { esc, execScriptSync } from './utils/helpers.js';
+
+const TEST_PATH = path.resolve('./test/');
+
+// CLI with flags and environment variables
+// Note: using child_process.execSync the stdout.isTTY is always false
+// TODO:
+// - test FORCE_COLOR=0
+// - test NO_COLOR=1
+
+describe('enable colors', () => {
+ test(`--color`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ const received = execScriptSync(filename, ['--color']);
+ const expected =
+ '\x1b[31mred\x1b[39m|\x1b[38;2;80;80;80mrgb\x1b[39m|\x1b[48;2;80;80;80mbgRgb\x1b[49m|\x1b[38;2;255;255;255mhex\x1b[39m|\x1b[48;2;255;255;255mbgHex\x1b[49m';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
+ test(`--color=true`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ const received = execScriptSync(filename, ['--color=true']);
+ const expected =
+ '\x1b[31mred\x1b[39m|\x1b[38;2;80;80;80mrgb\x1b[39m|\x1b[48;2;80;80;80mbgRgb\x1b[49m|\x1b[38;2;255;255;255mhex\x1b[39m|\x1b[48;2;255;255;255mbgHex\x1b[49m';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
+ test(`--color=always`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ const received = execScriptSync(filename, ['--color=always']);
+ const expected =
+ '\x1b[31mred\x1b[39m|\x1b[38;2;80;80;80mrgb\x1b[39m|\x1b[48;2;80;80;80mbgRgb\x1b[49m|\x1b[38;2;255;255;255mhex\x1b[39m|\x1b[48;2;255;255;255mbgHex\x1b[49m';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
+ test(`FORCE_COLOR=true`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ const received = execScriptSync(filename, [], ['FORCE_COLOR=true']);
+ const expected =
+ '\x1b[31mred\x1b[39m|\x1b[38;2;80;80;80mrgb\x1b[39m|\x1b[48;2;80;80;80mbgRgb\x1b[49m|\x1b[38;2;255;255;255mhex\x1b[39m|\x1b[48;2;255;255;255mbgHex\x1b[49m';
+
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
+ test(`FORCE_COLOR=1`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ const received = execScriptSync(filename, [], ['FORCE_COLOR=1']);
+ const expected =
+ '\x1b[31mred\x1b[39m|\x1b[38;2;80;80;80mrgb\x1b[39m|\x1b[48;2;80;80;80mbgRgb\x1b[49m|\x1b[38;2;255;255;255mhex\x1b[39m|\x1b[48;2;255;255;255mbgHex\x1b[49m';
+
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+});
+
+describe('disable colors', () => {
+ test(`--no-color`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ // flags has priority over env variable
+ const received = execScriptSync(filename, ['--no-color'], ['FORCE_COLOR=1']);
+ const expected = 'red|rgb|bgRgb|hex|bgHex';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
+ test(`--color=false`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ // flags has priority over env variable
+ const received = execScriptSync(filename, ['--color=false'], ['FORCE_COLOR=1']);
+ const expected = 'red|rgb|bgRgb|hex|bgHex';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
+ test(`--color=never`, (done) => {
+ const filename = path.join(TEST_PATH, './cli/output.js');
+ // flags has priority over env variable
+ const received = execScriptSync(filename, ['--color=never'], ['FORCE_COLOR=1']);
+ const expected = 'red|rgb|bgRgb|hex|bgHex';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+});
\ No newline at end of file
diff --git a/test/index.test.js b/test/index.test.js
index 0e5c02a..15f9e67 100644
--- a/test/index.test.js
+++ b/test/index.test.js
@@ -1,141 +1,5 @@
-import { execSync } from 'child_process';
-import path from 'path';
-
-// test distributed version
-import { hexToRgb, clamp } from '../src/utils.js';
-import { isSupported } from '../src/ansi-codes.js';
-import ansis, { Ansis, green, red, yellow } from '../src/index.js';
-
-const TEST_PATH = path.resolve('./test/');
-
-/**
- * Return output of javascript file.
- *
- * @param {string} file
- * @param {array} flags
- * @return {string}
- */
-const execScriptSync = (file, flags = []) => {
- const result = execSync('node ' + file + ' ' + flags.join(' '));
- // replace last newline in result
- return result.toString().replace(/\n$/, '');
-};
-
-/**
- * Escape the slash `\` in ESC-symbol.
- * Use it to show by an error the received ESC sequence string in console output.
- *
- * @param {string} str
- * @returns {string}
- */
-const esc = (str) => str.replace(/\x1b/g, '\\x1b');
-
-beforeAll(() => {
-});
-
-beforeEach(() => {
-});
-
-describe('default tests', () => {
- test(`self test`, (done) => {
- const received = 'OK';
- const expected = 'OK';
- expect(esc(received)).toEqual(esc(expected));
- done();
- });
-
- test(`ansis()`, (done) => {
- const received = ansis('OK');
- const expected = 'OK';
- expect(esc(received)).toEqual(esc(expected));
- done();
- });
-});
-
-describe('utils tests', () => {
- test(`strip()`, (done) => {
- const received = ansis.strip('\x1b[36m\x1b[1m\x1b[4m\x1b[3mfoo\x1b[23m\x1b[24m\x1b[22m\x1b[39m');
- const expected = 'foo';
- expect(esc(received)).toEqual(esc(expected));
- done();
- });
-
- test(`hexToRgb('FFAA99')`, (done) => {
- const received = hexToRgb('FFAA99');
- const expected = [255, 170, 153];
- expect(received).toEqual(expected);
- done();
- });
-
- test(`hexToRgb('#FFAA99')`, (done) => {
- const received = hexToRgb('#FFAA99');
- const expected = [255, 170, 153];
- expect(received).toEqual(expected);
- done();
- });
-
- test(`hexToRgb('#FA9')`, (done) => {
- const received = hexToRgb('#FA9');
- const expected = [255, 170, 153];
- expect(received).toEqual(expected);
- done();
- });
-
- test(`hexToRgb('#FF99')`, (done) => {
- const received = hexToRgb('#FF99');
- const expected = [0, 0, 0];
- expect(received).toEqual(expected);
- done();
- });
-
- test(`hexToRgb('something')`, (done) => {
- const received = hexToRgb('something');
- const expected = [0, 0, 0];
- expect(received).toEqual(expected);
- done();
- });
-
- test(`clamp(3, 0, 2)`, (done) => {
- const received = clamp(3, 0, 2);
- const expected = 2;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`clamp(0, 1, 2)`, (done) => {
- const received = clamp(0, 1, 2);
- const expected = 1;
- expect(received).toEqual(expected);
- done();
- });
-});
-
-describe('node script flags', () => {
- test(`flag --color`, (done) => {
- const filename = path.join(TEST_PATH, './cli/output.js');
- const received = execScriptSync(filename, ['--color']);
- const expected =
- '\x1b[31mred\x1b[39m|\x1b[38;2;80;80;80mrgb\x1b[39m|\x1b[48;2;80;80;80mbgRgb\x1b[49m|\x1b[38;2;255;255;255mhex\x1b[39m|\x1b[48;2;255;255;255mbgHex\x1b[49m';
- expect(esc(received)).toEqual(esc(expected));
- done();
- });
-
- test(`flag --color=false`, (done) => {
- const filename = path.join(TEST_PATH, './cli/output.js');
- const received = execScriptSync(filename, ['--color=false']);
- const expected = 'red|rgb|bgRgb|hex|bgHex';
- expect(esc(received)).toEqual(esc(expected));
- done();
- });
-
- test(`flag --no-color`, (done) => {
- const filename = path.join(TEST_PATH, './cli/output.js');
- const received = execScriptSync(filename, ['--no-color']);
- const expected = 'red|rgb|bgRgb|hex|bgHex';
- expect(esc(received)).toEqual(esc(expected));
- done();
- });
-});
+import { esc } from './utils/helpers.js';
+import ansis, { Ansis, red, yellow, green } from '../src/index.mjs';
describe('style tests', () => {
test(`ansis.visible('foo')`, (done) => {
@@ -242,6 +106,13 @@ describe('style tests', () => {
});
describe('functional tests', () => {
+ test(`ansis('OK')`, (done) => {
+ const received = ansis('OK');
+ const expected = 'OK';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
test(`nested styles`, (done) => {
const received = ansis.red('foo' + ansis.underline.bgBlue('bar') + '!');
const expected = '\x1b[31mfoo\x1b[4m\x1b[44mbar\x1b[49m\x1b[24m!\x1b[39m';
@@ -273,6 +144,13 @@ describe('functional tests', () => {
expect(esc(received)).toEqual(esc(expected));
done();
});
+
+ test(`strip()`, (done) => {
+ const received = ansis.strip('\x1b[36m\x1b[1m\x1b[4m\x1b[3mfoo\x1b[23m\x1b[24m\x1b[22m\x1b[39m');
+ const expected = 'foo';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
});
describe('alias tests', () => {
@@ -383,385 +261,4 @@ describe('extend base colors tests', () => {
expect(esc(received)).toEqual(esc(expected));
done();
});
-});
-
-// Node.JS
-describe('Node.JS isSupported', () => {
- test(`process undefined`, (done) => {
- // save original `process` object
- const processOriginal = process;
- process = undefined;
-
- const received = isSupported(undefined);
- const expected = false;
- expect(received).toEqual(expected);
-
- // restore original `process` object
- process = processOriginal;
- done();
- });
-
- test(`processMock undefined`, (done) => {
- const received = isSupported(undefined);
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`processMock {}`, (done) => {
- const received = isSupported({});
- const expected = false;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`colors in linux terminal`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { TERM: 'xterm' },
- argv: [],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`colors on windows platform`, (done) => {
- const received = isSupported({
- process: {
- platform: 'win32',
- env: {},
- argv: [],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`colors in any CI`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { CI: 'GITLAB_CI' },
- argv: [],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`no colors, unsupported terminal`, (done) => {
- const received = isSupported({
- process: {
- env: { TERM: 'dumb' },
- argv: [],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = false;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`no colors, simulate output in file > log.txt`, (done) => {
- const received = isSupported({
- process: {
- env: { TERM: 'xterm' },
- argv: [],
- },
-
- });
- const expected = false;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`enable colors via --color`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: {},
- argv: ['--color'],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`enable colors via -color`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: {},
- argv: ['-color'],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`enable colors via --color=true`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { TERM: 'dumb' },
- argv: ['--color=true'],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`enable colors via -color=true`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { TERM: 'dumb' },
- argv: ['-color=true'],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`disable colors via --color=false`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { TERM: 'xterm' },
- argv: ['--color=false'],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = false;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`disable colors via NO_COLOR=1`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { NO_COLOR: '1', TERM: 'xterm' },
- argv: [],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = false;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`disable colors via FORCE_COLOR=0`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { FORCE_COLOR: '0', TERM: 'xterm' },
- argv: [],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = false;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`disable colors via FORCE_COLOR=false`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { FORCE_COLOR: 'false', TERM: 'xterm' },
- argv: [],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = false;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`enable colors via FORCE_COLOR=1`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { FORCE_COLOR: '1' },
- argv: [],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`enable colors via FORCE_COLOR=true`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { FORCE_COLOR: 'true' },
- argv: [],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
-});
-
-// Deno
-describe('Deno isSupported', () => {
- test(`env TERM`, (done) => {
- const received = isSupported({
- Deno: {
- env: {
- toObject: () => ({ TERM: 'xterm-256color' }),
- },
- args: [],
- build: {
- os: 'linux', // win32
- },
- isatty: (rid) => rid === 1, // analog to process.stdout.isTTY in node
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`platform win`, (done) => {
- const received = isSupported({
- Deno: {
- env: {
- toObject: () => ({ TERM: '' }),
- },
- args: [],
- build: {
- os: 'win32',
- },
- isatty: (rid) => false, // analog to process.stdout.isTTY in node
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`FORCE_COLOR`, (done) => {
- const received = isSupported({
- Deno: {
- env: {
- toObject: () => ({ FORCE_COLOR: 1 }),
- },
- args: [],
- build: {
- os: 'linux',
- },
- isatty: (rid) => false, // analog to process.stdout.isTTY in node
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`flag '--color'`, (done) => {
- const received = isSupported({
- Deno: {
- env: {
- toObject: () => ({}),
- },
- args: ['--color'],
- build: {
- os: 'linux',
- },
- isatty: (rid) => false, // analog to process.stdout.isTTY in node
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-});
-
-// Next.JS
-describe('Next.JS isSupported', () => {
- test(`runtime experimental-edge`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { NEXT_RUNTIME: 'experimental-edge', TERM: 'xterm-256color' },
- argv: [],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`runtime edge`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { NEXT_RUNTIME: 'edge', TERM: 'xterm-256color' },
- argv: [],
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
-
- test(`runtime nodejs`, (done) => {
- const received = isSupported({
- process: {
- platform: 'linux',
- env: { NEXT_RUNTIME: 'nodejs', TERM: 'xterm-256color' },
- argv: [],
- stdout: { isTTY: true },
- stderr: { isTTY: true },
- },
-
- });
- const expected = true;
- expect(received).toEqual(expected);
- done();
- });
});
\ No newline at end of file
diff --git a/test/jest.config.js b/test/jest.config.js
index 73d2ba6..f80a5cf 100644
--- a/test/jest.config.js
+++ b/test/jest.config.js
@@ -21,7 +21,7 @@ module.exports = {
// collectCoverage: false,
// An array of glob patterns indicating a set of files for which coverage information should be collected
- // collectCoverageFrom: ['src/**/*.js'],
+ collectCoverageFrom: ['../src/**/*.js'],
// The directory where Jest should output its coverage files
// coverageDirectory: null,
diff --git a/test/package.test.js b/test/package.test.js
new file mode 100644
index 0000000..83d6e4a
--- /dev/null
+++ b/test/package.test.js
@@ -0,0 +1,56 @@
+import path from 'path';
+import { esc, execScriptSync } from './utils/helpers.js';
+
+const TEST_PATH = path.resolve('./test/');
+
+describe('Usage `ansis` npm package', () => {
+ test(`CommonJS mode`, (done) => {
+ const filename = path.join(TEST_PATH, './package/cjs/test.cjs');
+ const received = execScriptSync(filename, ['--color']);
+ const expected =
+ '\x1b[38;5;227m\x1b[7m -= [ansis package] CommonJS =- \x1b[27m\x1b[39m\n' +
+ '\x1b[31m\x1b[1m\x1b[4mred.bold.underline(\'red\')\x1b[24m\x1b[22m\x1b[39m\n' +
+ '\x1b[31m\x1b[1m\x1b[4mansis.red.bold.underline(red)\x1b[24m\x1b[22m\x1b[39m\n' +
+ '\x1b[38;2;250;255;99m\x1b[1mhex(\'#FFAB40\').bold(\'#63ffc6\')\x1b[22m\x1b[39m\n' +
+ '\x1b[38;2;250;255;99m\x1b[1mansis.hex(\'#FFAB40\').bold(#63ffc6)\x1b[22m\x1b[39m\n' +
+ '\x1b[38;2;255;117;209mansis.pink\x1b[39m\n' +
+ '\x1b[38;2;255;171;64mansis.orange\x1b[39m\n' +
+ '\x1b[38;2;255;171;64m\x1b[1mansis.orange.bold\x1b[22m\x1b[39m\n' +
+ '\x1b[1m\x1b[31mansis2.bold.red\x1b[39m\x1b[22m\n' +
+ '\x1b[38;2;255;117;209mextend: ansis2.pink\x1b[39m\n' +
+ '\x1b[3m\x1b[38;2;255;171;64mextend: ansis2.italic.orange\x1b[39m\x1b[23m\n' +
+ 'colored: \x1b[32mgreen text\x1b[39m\n' +
+ 'striped: green text\n' +
+ '--- OLD named import: \x1b[33mconst { magenta, cyan, blue } = require(\'ansis/colors\');\x1b[39m\n' +
+ '\x1b[35mmagenta\x1b[39m\n' +
+ '\x1b[36m\x1b[1mcyan bold\x1b[22m\x1b[39m\n' +
+ '\x1b[34m\x1b[3mblue italic\x1b[23m\x1b[39m';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+
+ test(`ESM mode`, (done) => {
+ const filename = path.join(TEST_PATH, './package/esm/test.mjs');
+ const received = execScriptSync(filename, ['--color']);
+ const expected =
+ '\x1b[38;5;208m\x1b[7m -= [ansis package] ESM =- \x1b[27m\x1b[39m\n' +
+ '\x1b[31m\x1b[1m\x1b[4mred.bold.underline(\'red\')\x1b[24m\x1b[22m\x1b[39m\n' +
+ '\x1b[31m\x1b[1m\x1b[4mansis.red.bold.underline(red)\x1b[24m\x1b[22m\x1b[39m\n' +
+ '\x1b[38;2;250;255;99m\x1b[1mhex(\'#FFAB40\').bold(\'#63ffc6\')\x1b[22m\x1b[39m\n' +
+ '\x1b[38;2;250;255;99m\x1b[1mansis.hex(\'#FFAB40\').bold(#63ffc6)\x1b[22m\x1b[39m\n' +
+ '\x1b[38;2;255;117;209mansis.pink\x1b[39m\n' +
+ '\x1b[38;2;255;171;64mansis.orange\x1b[39m\n' +
+ '\x1b[38;2;255;171;64m\x1b[1mansis.orange.bold\x1b[22m\x1b[39m\n' +
+ '\x1b[1m\x1b[31mansis2.bold.red\x1b[39m\x1b[22m\n' +
+ '\x1b[38;2;255;117;209mextend: ansis2.pink\x1b[39m\n' +
+ '\x1b[3m\x1b[38;2;255;171;64mextend: ansis2.italic.orange\x1b[39m\x1b[23m\n' +
+ 'colored: \x1b[32mgreen text\x1b[39m\n' +
+ 'striped: green text\n' +
+ '--- OLD named import: \x1b[33mimport { magenta, cyan, blue } from \'ansis/colors\';\x1b[39m\n' +
+ '\x1b[35mmagenta\x1b[39m\n' +
+ '\x1b[36m\x1b[1mcyan bold\x1b[22m\x1b[39m\n' +
+ '\x1b[34m\x1b[3mblue italic\x1b[23m\x1b[39m';
+ expect(esc(received)).toEqual(esc(expected));
+ done();
+ });
+});
\ No newline at end of file
diff --git a/test/package/README.md b/test/package/README.md
deleted file mode 100644
index 1874e4f..0000000
--- a/test/package/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-1. Build `ansis` package from source into `dist/` directory.
-
- Run from project directory:
- ```
- npm run build
- ```
-
-2. Install `ansis` as local `dist/` directory:
-
- ```
- cd ./test/package/
- npm i
- ```
-
-3. Test in CommonJS mode:
- ```
- npm run test:cjs
- ```
-
-4. Test in ESM mode:
- ```
- npm run test:esm
- ```
\ No newline at end of file
diff --git a/test/package/cjs/index.js b/test/package/cjs/index.js
deleted file mode 100644
index c947c78..0000000
--- a/test/package/cjs/index.js
+++ /dev/null
@@ -1,24 +0,0 @@
-const ansis = require('ansis');
-
-// test new named import
-const { Ansis, red, yellow, green } = require('ansis');
-
-// test old named import
-const { magenta, cyan, blue } = require('ansis/colors');
-
-const log = console.log;
-
-const ansis2 = new Ansis();
-
-log(ansis.green.inverse(' CommonJS '));
-log(ansis2.bgCyanBright('const ansis = new Ansis();'));
-
-log(`--- NEW named import: ${yellow`const { red, yellow, green } = require('ansis');`}`);
-log(red('red'));
-log(green.bold('green bold'));
-log(yellow.italic`yellow italic`);
-
-log(`--- OLD named import: ${yellow`const { magenta, cyan, blue } = require('ansis/colors');`}`);
-log(magenta`magenta`);
-log(cyan.bold`cyan bold`);
-log(blue.italic`blue italic`);
\ No newline at end of file
diff --git a/test/package/cjs/package.json b/test/package/cjs/package.json
index ba0dde7..8562c81 100644
--- a/test/package/cjs/package.json
+++ b/test/package/cjs/package.json
@@ -1,5 +1,5 @@
{
- "name": "ansis",
+ "name": "package-ansis-cjs",
"description": "CommonJS version",
"type": "commonjs"
-}
+}
\ No newline at end of file
diff --git a/test/package/cjs/test.cjs b/test/package/cjs/test.cjs
new file mode 100644
index 0000000..049071e
--- /dev/null
+++ b/test/package/cjs/test.cjs
@@ -0,0 +1,49 @@
+const ansis = require('ansis');
+
+// test new named import
+const { Ansis, red, green, yellow, hex } = require('ansis');
+
+// test old named import
+const { magenta, cyan, blue } = require('ansis/colors');
+
+const log = console.log;
+
+log(ansis.ansi256(227).inverse(' -= [ansis package] CommonJS =- '));
+
+// styles
+log(red.bold.underline(`red.bold.underline('red')`));
+log(ansis.red.bold.underline(`ansis.red.bold.underline(red)`));
+
+log(hex('#faff63').bold(`hex('#FFAB40').bold('#63ffc6')`));
+log(ansis.hex('#faff63').bold(`ansis.hex('#FFAB40').bold(#63ffc6)`));
+
+// extend
+ansis.extend({
+ pink: '#FF75D1',
+ orange: '#FFAB40',
+});
+
+log(ansis.pink('ansis.pink'));
+log(ansis.orange('ansis.orange'));
+log(ansis.orange.bold('ansis.orange.bold'));
+
+const ansis2 = new Ansis();
+log(ansis2.bold.red('ansis2.bold.red'));
+
+ansis2.extend({
+ pink: '#FF75D1',
+ orange: '#FFAB40',
+});
+
+log(ansis2.pink('extend: ansis2.pink'));
+log(ansis2.italic.orange('extend: ansis2.italic.orange'));
+
+// strip
+const greenText = green`green text`;
+log('colored: ', greenText);
+log('striped: ', ansis.strip(greenText));
+
+log(`--- OLD named import: ${yellow`const { magenta, cyan, blue } = require('ansis/colors');`}`);
+log(magenta`magenta`);
+log(cyan.bold`cyan bold`);
+log(blue.italic`blue italic`);
\ No newline at end of file
diff --git a/test/package/esm/index.js b/test/package/esm/index.js
deleted file mode 100644
index 0be9710..0000000
--- a/test/package/esm/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// test new named import
-import ansis, { Ansis, red, yellow, green } from 'ansis';
-
-// test old named import
-import { magenta, cyan, blue } from 'ansis/colors';
-
-const log = console.log;
-
-const ansis2 = new Ansis();
-
-log(ansis.green.inverse(' ESM '));
-log(ansis2.bgCyanBright('const ansis = new Ansis();'));
-
-log(`--- NEW named import: ${yellow`import { red, yellow, green } from 'ansis';`}`);
-log(red('red'));
-log(green.bold('green bold'));
-log(yellow.italic`yellow italic`);
-
-log(`--- OLD named import: ${yellow`import { magenta, cyan, blue } from 'ansis/colors';`}`);
-log(magenta`magenta`);
-log(cyan.bold`cyan bold`);
-log(blue.italic`blue italic`);
\ No newline at end of file
diff --git a/test/package/esm/package.json b/test/package/esm/package.json
index 9fe733c..12b9be9 100644
--- a/test/package/esm/package.json
+++ b/test/package/esm/package.json
@@ -1,5 +1,5 @@
{
- "name": "ansis",
+ "name": "package-ansis-esm",
"description": "ESM version",
"type": "module"
-}
+}
\ No newline at end of file
diff --git a/test/package/esm/test.mjs b/test/package/esm/test.mjs
new file mode 100644
index 0000000..a90618c
--- /dev/null
+++ b/test/package/esm/test.mjs
@@ -0,0 +1,47 @@
+// test new named import
+import ansis, { Ansis, red, green, yellow, hex } from 'ansis';
+
+// test old named import
+import { magenta, cyan, blue } from 'ansis/colors';
+
+const log = console.log;
+
+log(ansis.ansi256(208).inverse(' -= [ansis package] ESM =- '));
+
+// styles
+log(red.bold.underline(`red.bold.underline('red')`));
+log(ansis.red.bold.underline(`ansis.red.bold.underline(red)`));
+
+log(hex('#faff63').bold(`hex('#FFAB40').bold('#63ffc6')`));
+log(ansis.hex('#faff63').bold(`ansis.hex('#FFAB40').bold(#63ffc6)`));
+
+// extend
+ansis.extend({
+ pink: '#FF75D1',
+ orange: '#FFAB40',
+});
+
+log(ansis.pink('ansis.pink'));
+log(ansis.orange('ansis.orange'));
+log(ansis.orange.bold('ansis.orange.bold'));
+
+const ansis2 = new Ansis();
+log(ansis2.bold.red('ansis2.bold.red'));
+
+ansis2.extend({
+ pink: '#FF75D1',
+ orange: '#FFAB40',
+});
+
+log(ansis2.pink('extend: ansis2.pink'));
+log(ansis2.italic.orange('extend: ansis2.italic.orange'));
+
+// strip
+const greenText = green`green text`;
+log('colored: ', greenText);
+log('striped: ', ansis.strip(greenText));
+
+log(`--- OLD named import: ${yellow`import { magenta, cyan, blue } from 'ansis/colors';`}`);
+log(magenta`magenta`);
+log(cyan.bold`cyan bold`);
+log(blue.italic`blue italic`);
\ No newline at end of file
diff --git a/test/package/package.json b/test/package/package.json
deleted file mode 100644
index 08a4286..0000000
--- a/test/package/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "@webdiscus/ansis-test",
- "version": "1.0.0",
- "description": "Test npm package in CJS and ESM modes.",
- "main": "index.js",
- "scripts": {
- "test:cjs": "node ./cjs/index.js",
- "test:esm": "node ./esm/index.js"
- },
- "devDependencies": {
- "@types/node": "^18.7.15",
- "ansis": "file:../../dist"
- }
-}
\ No newline at end of file
diff --git a/test/package/ts/index.ts b/test/package/ts/index.ts
index 90e6371..a97dbc2 100644
--- a/test/package/ts/index.ts
+++ b/test/package/ts/index.ts
@@ -14,7 +14,7 @@ ansis.extend({
orange: '#FFAB40',
});
-// `AnsiColorsExtend` is extendable type for TS to add a custom color
+// `AnsiColorsExtend` is an extendable type for TS to add a custom color
const write = (style: AnsiColorsExtend<'pink' | 'orange'>, message: string) => {
console.log(ansis[style](message));
};
diff --git a/test/unit.test.js b/test/unit.test.js
new file mode 100644
index 0000000..f6a6d7d
--- /dev/null
+++ b/test/unit.test.js
@@ -0,0 +1,434 @@
+import { hexToRgb, clamp } from '../src/utils.js';
+import { isSupported } from '../src/ansi-codes.js';
+
+describe('utils tests', () => {
+ test(`hexToRgb('FFAA99')`, (done) => {
+ const received = hexToRgb('FFAA99');
+ const expected = [255, 170, 153];
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`hexToRgb('#FFAA99')`, (done) => {
+ const received = hexToRgb('#FFAA99');
+ const expected = [255, 170, 153];
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`hexToRgb('#FA9')`, (done) => {
+ const received = hexToRgb('#FA9');
+ const expected = [255, 170, 153];
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`hexToRgb('#FF99')`, (done) => {
+ const received = hexToRgb('#FF99');
+ const expected = [0, 0, 0];
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`hexToRgb('something')`, (done) => {
+ const received = hexToRgb('something');
+ const expected = [0, 0, 0];
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`clamp(3, 0, 2)`, (done) => {
+ const received = clamp(3, 0, 2);
+ const expected = 2;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`clamp(0, 1, 2)`, (done) => {
+ const received = clamp(0, 1, 2);
+ const expected = 1;
+ expect(received).toEqual(expected);
+ done();
+ });
+});
+
+// Node.JS
+describe('Node.JS isSupported', () => {
+ test(`process undefined`, (done) => {
+ // save original `process` object
+ const processOriginal = process;
+ process = undefined;
+
+ const received = isSupported(undefined);
+ const expected = false;
+ expect(received).toEqual(expected);
+
+ // restore original `process` object
+ process = processOriginal;
+ done();
+ });
+
+ test(`processMock undefined`, (done) => {
+ const received = isSupported(undefined);
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`processMock {}`, (done) => {
+ const received = isSupported({});
+ const expected = false;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`colors in linux terminal`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { TERM: 'xterm' },
+ argv: [],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`colors on windows platform`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'win32',
+ env: {},
+ argv: [],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`colors in any CI`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { CI: 'GITLAB_CI' },
+ argv: [],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`no colors, unsupported terminal`, (done) => {
+ const received = isSupported({
+ process: {
+ env: { TERM: 'dumb' },
+ argv: [],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = false;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`no colors, simulate output in file > log.txt`, (done) => {
+ const received = isSupported({
+ process: {
+ env: { TERM: 'xterm' },
+ argv: [],
+ },
+
+ });
+ const expected = false;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`enable colors via --color`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: {},
+ argv: ['--color'],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`enable colors via -color`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: {},
+ argv: ['-color'],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`enable colors via --color=true`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { TERM: 'dumb' },
+ argv: ['--color=true'],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`enable colors via -color=true`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { TERM: 'dumb' },
+ argv: ['-color=true'],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`disable colors via --color=false`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { TERM: 'xterm' },
+ argv: ['--color=false'],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = false;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`disable colors via NO_COLOR=1`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { NO_COLOR: '1', TERM: 'xterm' },
+ argv: [],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = false;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`disable colors via FORCE_COLOR=0`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { FORCE_COLOR: '0', TERM: 'xterm' },
+ argv: [],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = false;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`disable colors via FORCE_COLOR=false`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { FORCE_COLOR: 'false', TERM: 'xterm' },
+ argv: [],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = false;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`enable colors via FORCE_COLOR=1`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { FORCE_COLOR: '1' },
+ argv: [],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`enable colors via FORCE_COLOR=true`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { FORCE_COLOR: 'true' },
+ argv: [],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+});
+
+// Deno
+describe('Deno isSupported', () => {
+ test(`env TERM`, (done) => {
+ const received = isSupported({
+ Deno: {
+ env: {
+ toObject: () => ({ TERM: 'xterm-256color' }),
+ },
+ args: [],
+ build: {
+ os: 'linux', // win32
+ },
+ isatty: (rid) => rid === 1, // analog to process.stdout.isTTY in node
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`platform win`, (done) => {
+ const received = isSupported({
+ Deno: {
+ env: {
+ toObject: () => ({ TERM: '' }),
+ },
+ args: [],
+ build: {
+ os: 'win32',
+ },
+ isatty: (rid) => false, // analog to process.stdout.isTTY in node
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`FORCE_COLOR`, (done) => {
+ const received = isSupported({
+ Deno: {
+ env: {
+ toObject: () => ({ FORCE_COLOR: 1 }),
+ },
+ args: [],
+ build: {
+ os: 'linux',
+ },
+ isatty: (rid) => false, // analog to process.stdout.isTTY in node
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`flag '--color'`, (done) => {
+ const received = isSupported({
+ Deno: {
+ env: {
+ toObject: () => ({}),
+ },
+ args: ['--color'],
+ build: {
+ os: 'linux',
+ },
+ isatty: (rid) => false, // analog to process.stdout.isTTY in node
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+});
+
+// Next.JS
+describe('Next.JS isSupported', () => {
+ test(`runtime experimental-edge`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { NEXT_RUNTIME: 'experimental-edge', TERM: 'xterm-256color' },
+ argv: [],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`runtime edge`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { NEXT_RUNTIME: 'edge', TERM: 'xterm-256color' },
+ argv: [],
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+
+ test(`runtime nodejs`, (done) => {
+ const received = isSupported({
+ process: {
+ platform: 'linux',
+ env: { NEXT_RUNTIME: 'nodejs', TERM: 'xterm-256color' },
+ argv: [],
+ stdout: { isTTY: true },
+ stderr: { isTTY: true },
+ },
+
+ });
+ const expected = true;
+ expect(received).toEqual(expected);
+ done();
+ });
+});
\ No newline at end of file
diff --git a/test/utils/helpers.js b/test/utils/helpers.js
new file mode 100644
index 0000000..e038a87
--- /dev/null
+++ b/test/utils/helpers.js
@@ -0,0 +1,54 @@
+import { execSync } from 'child_process';
+
+/**
+ * Escape the slash `\` in ESC-symbol.
+ * Use it to show by an error the received ESC sequence string in console output.
+ *
+ * @param {string} str
+ * @returns {string}
+ */
+export const esc = (str) => str.replace(/\x1b/g, '\\x1b');
+
+/**
+ * Return output of javascript file.
+ *
+ * @param {string} file
+ * @param {Array} flags
+ * @param {Array} env
+ * @return {string}
+ */
+export const execScriptSync = (file, flags = [], env = []) => {
+ const envVars = env.length ? '' + env.join(' ') + ' ' : '';
+ const cmd = envVars + 'node ' + file + ' ' + flags.join(' ');
+ const result = execSync(cmd);
+
+ // replace last newline in result
+ return result.toString().replace(/\n$/, '');
+};
+
+// TODO: get colorized output in process.stdout using child_process.execSync
+// export const execScriptOutSync = (file, flags = [], env = []) => {
+// const envVars = env.length ? '' + env.join(' ') + ' ' : '';
+// const cmd = envVars + 'node ' + file + ' ' + flags.join(' ');
+//
+// //const stdout = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});
+// const stdout = jest.spyOn(process.stdout, 'write').mockImplementation(() => {});
+//
+// const result = execSync(
+// cmd,
+// // reset stdio to enable isTTY for colorized output
+// { stdio: 'inherit' },
+// //{ stdio: [0, process.stdout, process.stderr] },
+// //{ stdio: [1] },
+// );
+//
+// const { calls } = stdout.mock;
+// let output = calls.length > 0 ? calls[0][0] : '';
+//
+// stdout.mockClear();
+// stdout.mockRestore();
+// console.log('--> ', { cmd, output, calls, stdout: stdout.mock }, stdout);
+// //console.log('--> ', result.toString());
+//
+// return output;
+// };
\ No newline at end of file