diff --git a/.prettierrc b/.prettierrc index f74c6aa..9ea329e 100644 --- a/.prettierrc +++ b/.prettierrc @@ -11,7 +11,9 @@ "bracketSameLine": true, "overrides": [ { - "files": ["*.html"], + "files": [ + "*.html" + ], "options": { "tabWidth": 4 } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4355eb4..2508a68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Change log +## 1.6.0-beta.0 (2023-11-01) + +- feat: add supports the Deno +- feat: add supports the Next.js `edge` runtime +- test: add tests for isSupported() function +- chore: update dev dependencies + ## 1.5.6 (2023-09-21) + - chore: update dev dependencies - chore: add SECURITY.md - chore: add PULL_REQUEST_TEMPLATE.md @@ -8,106 +16,127 @@ - docs: update readme ## 1.5.5 (2022-09-22) + - refactor: optimize code to reduce size by 120 bytes -- test: added test for isSupported() function +- test: add test for isSupported() function - docs: update readme, add example screenshots ## 1.5.4 (2022-09-14) + - fix: visible style with nested template strings ## 1.5.3 (2022-09-14) + - fix: set correct aliases for bgAnsi and fg methods by named export - chore: refactor examples - docs: update readme ## 1.5.2 (2022-09-10) + - fix: regard the value of the environment variable FORCE_COLOR=0 to force disable colors -- test: added tests for FORCE_COLOR +- test: add tests for FORCE_COLOR - docs: update readme ## 1.5.1 (2022-09-08) -- fix: added missing export for CJS mode in package.json -- test: added manual tests for CJS and ESM mode + +- fix: add missing export for CJS mode in package.json +- test: add manual tests for CJS and ESM mode ## 1.5.0 (2022-09-08) + - DEPRECATE v1.5.0, because missing exports main for CJS mode, fixed in v1.5.1 ## 1.5.0 (2022-09-08) -- feat: added supports the nested template literal syntax: + +- feat: add supports the nested template literal syntax: ```js console.log(red`red ${yellow`yellow ${green`green`} yellow`} red`) ``` -- feat: added named export of colors with supports for chained syntax: +- feat: add named export of colors with supports for chained syntax: ```js import { red, green, yellow } from 'ansis/colors'; console.log(red.bold.underline`text`); ``` -- feat: added extending of base colors with named custom truecolor +- feat: add extending of base colors with named custom truecolor ```js import ansis from 'ansis'; ansis.extend({ orange: '#FFAB40' }); console.log(ansis.orange.bold('text')); ``` - fix: corrected declarations in `index.d.ts` -- chore: added `AnsiStyles`, `AnsiColors` and AnsiColorsExtend types in `index.d.ts` +- chore: add `AnsiStyles`, `AnsiColors` and AnsiColorsExtend types in `index.d.ts` - refactor: optimize size of distributed bundle from 3.7KB to 3.1KB -- docs: added usage in CLI +- docs: add usage in CLI ## 1.4.0 (2022-07-02) + - feat: add method strip() to remove all ANSI codes from string ## 1.3.6 (2022-04-27) + - build: properly generated distribution package, bump to last stable version 1.3.6 - chore: update dev packages ## 1.3.5 (2022-04-27) + - DEPRECATED: this version is broken ## 1.3.4 (2022-01-30) -- optimize distributed code size to smaller than `4 KB` + +- feat: optimize distributed code size to smaller than `4 KB` ## 1.3.3 (2022-01-24) -- added UK spelling alias `grey` for `gray` -- update dev dependencies -- update readme + +- feat: add UK spelling alias `grey` for `gray` +- chore: update dev dependencies +- docs: update readme ## 1.3.2 (2021-12-30) -- added bundle generation for ESM -- auto generate bundles for ESM and CommonJS at npm publish + +- feat: add bundle generation for ESM +- build: auto generate bundles for ESM and CommonJS at npm publish ## 1.3.1 (2021-12-29) -- fixed usage for CommonJS: `const ansis = require('ansis').default;` --> `const ansis = require('ansis');` + +- fix: usage for CommonJS: `const ansis = require('ansis').default;` --> `const ansis = require('ansis');` ## 1.3.0 (2021-12-29) -- added support CommonJS (now supported ESM and CommonJS) -- added aliases: `.fg()` for `.ansi256()` and `.bg()` for `.bgAnsi256()` methods -- fixed some inner param types -- remove examples from NPM package (it can be cloned und run local) + +- feat: add support CommonJS (now supported ESM and CommonJS) +- feat: add aliases: `.fg()` for `.ansi256()` and `.bg()` for `.bgAnsi256()` methods +- fix: some inner param types +- chore: remove examples from NPM package (it can be cloned und run local) ## 1.2.2 (2021-12-28) -- fixed the path of examples in package.json + +- fix: the path of examples in package.json ## 1.2.1 (2021-12-28) -- update examples: added demo of all features -- update readme + +- chore: add demo examples of all features +- docs: update readme ## 1.2.0 (2021-12-27) -- added supports the environment variables `NO_COLOR` `FORCE_COLOR` and flags `--no-color` `--color` -- added aliases `ansi` for `ansi256` and `bgAnsi` for `bgAnsi256` -- added to readme the compare of most popular ANSI libraries + +- feat: add supports the environment variables `NO_COLOR` `FORCE_COLOR` and flags `--no-color` `--color` +- feat: add aliases `ansi` for `ansi256` and `bgAnsi` for `bgAnsi256` +- docs: add to readme the compare of most popular ANSI libraries ## 1.1.1 (2021-12-27) -- added the class Ansis to create more independent instances to increase the performance by benchmark -- improve performance -- code refactoring -- update readme + +- feat: add the class Ansis to create more independent instances to increase the performance by benchmark +- feat: improve performance +- refactor: code refactoring +- docs: update readme ## 1.1.0 (2021-12-25) -- added supports the use of `open` and `close` properties for each style -- added demo to npm package -- fixed codes for methods ansi256() and bgAnsi256() -- update package.json -- update readme + +- feat: add supports the use of `open` and `close` properties for each style +- fix: codes for methods ansi256() and bgAnsi256() +- chore: added demo to npm package +- chore: update package.json +- docs: update readme ## 1.0.0 (2021-12-24) + First release diff --git a/README.md b/README.md index e616730..acafbc3 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,12 @@ [![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!` ```. +Colorize your output in a terminal with clean syntax, +e.g., ``` green`Hello World!` ``` ``` red`Error!` ``` ``` black.bgYellow`Warning!` ```. **Why yet one lib?**\ -See [comparison](https://github.com/webdiscus/ansis#compare-most-popular-ansi-libraries) and [benchmarks](https://github.com/webdiscus/ansis#benchmark) of most popular Node.js libraries:\ +See [comparison](https://github.com/webdiscus/ansis#compare-most-popular-ansi-libraries) +and [benchmarks](https://github.com/webdiscus/ansis#benchmark) of most popular Node.js libraries:\ [`chalk`][chalk], [`colors.js`][colors.js], [`colorette`][colorette], [`picocolors`][picocolors], [`kleur`][kleur], [`ansi-colors`][ansi-colors], [`cli-color`][cli-color], [`colors-cli`][colors-cli].
@@ -30,19 +32,20 @@ See [comparison](https://github.com/webdiscus/ansis#compare-most-popular-ansi-li [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/edit/stackblitz-starters-gs2gve?file=index.js) - ## Highlights - supports both **ESM** and **CommonJS** +- supports **Deno**, **Next.JS** runtime - up to **x3.5 faster** than **chalk**, [see benchmarks](#benchmark) -- dist code is **3 KB** only +- dist code is only **5 KB** incl. named import for ESM and CommonJS - [standard API](#base-colors) like **chalk** - default and [named import](#named-import) `import { red, bold, rgb } from 'ansis/colors'` - [chained syntax](#chained-syntax) `red.bold('text')` - [nested **template strings**](#nested-syntax) ``` red`R ${green`G`} R` ``` - [ANSI 256 colors](#256-colors) and [Truecolor](#truecolor) (**RGB**, **HEX**) - [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}!` ``` +- [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` @@ -50,15 +53,14 @@ See [comparison](https://github.com/webdiscus/ansis#compare-most-popular-ansi-li - **TypeScript** friendly - zero dependencies - + ## Install ```bash npm install ansis ``` - ## Usage You can import module and named colors with ESM or CommonJS syntax. @@ -103,13 +105,12 @@ Output:\ [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/edit/stackblitz-starters-sx74bl?file=index.js) - + ## Named import The `ansis` supports both the `default import` and `named import`. - ```js // default import import ansis from 'ansis'; @@ -127,6 +128,7 @@ red.bold('text'); ``` + ## Template literals The `ansis` supports both the function syntax `red('error')` and template literals ``` red`error` ```. @@ -144,8 +146,8 @@ red`text`; red`text ${message} text`; ``` - + ## Chained syntax All colors, styles and functions are chainable. Each color or style can be combined in any order. @@ -159,14 +161,15 @@ bold.bgHex('#FF75D1').cyan`text`; italic.bold.yellow.bgMagentaBright`text`; ``` - + ## Nested syntax You can nest functions and template strings within each other. None of the other libraries (chalk, kleur, colorette, colors.js etc.) support nested template strings. Nested template strings: + ```js import { red, green } from 'ansis/colors'; @@ -174,6 +177,7 @@ red`red ${green`green`} red`; ``` Deep nested chained styles: + ```js import { red, green, cyan, magenta, yellow, italic, underline } from 'ansis/colors'; @@ -195,6 +199,7 @@ Output:\ ![screenshot nested styles](docs/img/ansis-nested.png?raw=true) Multiline nested template strings: + ```js import { red, green, hex, visible, inverse } from 'ansis/colors'; @@ -223,11 +228,12 @@ DISK: ${orange`${disk}%`} Output:\ ![screenshot multiline nested](docs/img/ansis-multiline-nested.png?raw=true) - + ## Base colors and styles -Colors and styles have standard names used by many popular libraries, such as [chalk][chalk], [colorette][colorette], [kleur][kleur]. +Colors and styles have standard names used by many popular libraries, such +as [chalk][chalk], [colorette][colorette], [kleur][kleur]. | Foreground colors | Background colors | Styles | |:----------------------|:------------------|--------------------------------------------| @@ -249,8 +255,8 @@ Colors and styles have standard names used by many popular libraries, such as [c | `cyanBright` | `bgCyanBright` | | | `whiteBright` | `bgWhiteBright` | | - + ## Extend base colors Defaults, the imported `ansis` instance contains [base styles and colors](#base-colors). @@ -271,6 +277,7 @@ ansis.orange('text'); ``` Usage example with TypeScript: + ```ts import ansis, { AnsiColorsExtend } from 'ansis'; @@ -290,8 +297,8 @@ write('orange', 'message'); // extended color OK write('unknown', 'message'); // TypeScript Error ``` - + ## ANSI 256 colors The pre-defined set of 256 colors. @@ -338,8 +345,8 @@ bgAnsi256(105).ansi256(96)`cyan text on magenta background` bg(105).fg(96)`cyan text on magenta background` ``` - + ## Truecolor You can use the `hex` or `rgb` format. @@ -348,7 +355,7 @@ Foreground function: `hex()` `rgb()`\ Background function: `bgHex()` `bgRgb()` ```js -import { bold, hex, rgb, bgHex, bgRgb} from 'ansis/colors'; +import { bold, hex, rgb, bgHex, bgRgb } from 'ansis/colors'; // foreground color hex('#E0115F').bold`bold Ruby`; @@ -365,9 +372,11 @@ bold.hex('#E0115F').bgHex('#96C')`ruby bold text on amethyst background` ``` + ## Use ANSI codes -You can use the [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) with `open` and `close` properties for each style. +You can use the [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) with `open` +and `close` properties for each style. ```js import { red, bold } from 'ansis/colors'; @@ -382,6 +391,7 @@ console.log(`Hello ${myStyle.open}ANSI${myStyle.close} World!`); ``` + ## Strip ANSI codes The Ansis class contains the method `strip()` to remove all ANSI codes from string. @@ -395,8 +405,8 @@ const string = ansis.strip(ansiString); The variable `string` will contain the pure string without ANSI codes. - + ## New lines Supports correct style break at the `end of line`. @@ -409,8 +419,8 @@ console.log(bgGreen`\nAnsis\nNew Line\nNext New Line\n`); ![output](docs/img/break-style-nl.png?raw=true "break styles at EOL") - + ## Shortcuts / Themes Define your own themes: @@ -431,14 +441,16 @@ theme.warning('warning'); theme.ruby('Ruby color'); ``` - + ## CLI Defaults, the output in terminal console is colored and output in a file is uncolored. ### Environment variables + _example.js_ + ```js import ansis from 'ansis'; @@ -468,10 +480,11 @@ $ FORCE_COLOR=1 node example.js > log.txt #=> force enable colors > `FORCE_COLOR=0` force disable colors\ > `FORCE_COLOR=1` force enable colors - ### Arguments for executable script + If you have an executable script.\ _example.js_ + ```js #!/usr/bin/env node import ansis from 'ansis'; @@ -480,6 +493,7 @@ console.log(ansis.red`COLOR`); ``` Use arguments `--no-color` or `--color=false` to disable colors and `--color` to enable ones. + ``` $ ./example.js #=> color $ ./example.js --no-color #=> no color @@ -490,8 +504,8 @@ $ ./example.js --color > log.txt #=> color $ ./example.js --color=true > log.txt #=> color ``` - + ## Comparison of most popular libraries | Library
______________
- name
- code size
- named import | Naming colors | ANSI 256
colors | True-
color | Chained
syntax | Nested
template strings | New
Line | Supports
CLI params | @@ -504,8 +518,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]
**3.2KB**
`✅ 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` | > **Note** > @@ -548,7 +561,6 @@ $ ./example.js --color=true > log.txt #=> color > Next Line`); > ``` - ## Show ANSI demo ```bash @@ -774,11 +786,19 @@ Most popular ANSI libraries for `Node.js`: [ISC](https://github.com/webdiscus/ansis/blob/master/LICENSE) [colors.js]: https://github.com/Marak/colors.js + [colorette]: https://github.com/jorgebucaran/colorette + [picocolors]: https://github.com/alexeyraspopov/picocolors + [cli-color]: https://github.com/medikoo/cli-color + [colors-cli]: https://github.com/jaywcjlove/colors-cli + [ansi-colors]: https://github.com/doowb/ansi-colors + [kleur]: https://github.com/lukeed/kleur + [chalk]: https://github.com/chalk/chalk + [ansis]: https://github.com/webdiscus/ansis diff --git a/package.json b/package.json index 5e42c38..20e2727 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ansis", - "version": "1.5.6", - "description": "Colorize text in terminal", + "version": "1.6.0-beta.0", + "description": "Colorize text in terminal or console output with ANSI colors & styles", "keywords": [ "ansi", "colour", @@ -9,6 +9,7 @@ "colors", "styles", "terminal", + "xterm", "console", "cli", "log", @@ -16,8 +17,15 @@ "strip-color", "truecolor", "rgb", + "red", + "green", + "yellow", + "blue", + "magenta", + "cyan", "FORCE_COLOR", "NO_COLOR", + "ansi-colors", "chalk", "colorette", "colors.js", @@ -77,10 +85,10 @@ "node": ">=12.13" }, "devDependencies": { - "@babel/core": "^7.22.20", - "@babel/preset-env": "^7.22.20", - "@types/jest": "^29.5.5", - "jest": "^28.1.3", + "@babel/core": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@types/jest": "^29.5.7", + "jest": "^29.7.0", "prettier": "^3.0.3", "rollup": "^2.79.0", "rollup-plugin-cleanup": "^3.2.1", diff --git a/package/index.js b/package/index.js index ed6950d..8bad743 100644 --- a/package/index.js +++ b/package/index.js @@ -3,8 +3,8 @@ // This is the generic module loader for both ESM and CommonJS. // Note: // - the file will be coped to ./dist directory as index.js via rollup. -// - the `./dist/bundle.js` file will be auto generated via rollup at `npm publish`. +// - the `./dist/colors.js` file will be auto generated via rollup at `npm publish`. -const bundle = require('./bundle.js'); -module.exports = bundle.default; -module.exports.Ansis = bundle.Ansis; +const colors = require('./colors.js'); +module.exports = colors.default; +module.exports.Ansis = colors.Ansis; diff --git a/package/package.json b/package/package.json index 6838527..50e2001 100644 --- a/package/package.json +++ b/package/package.json @@ -1,16 +1,13 @@ { "name": "ansis", - "version": "1.5.6", - "description": "Formatting text in terminal with ANSI colors & styles.", + "version": "1.6.0-beta.0", + "description": "Colorize text in terminal or console output with ANSI colors & styles", "keywords": [ - "256", - "256color", "ansi", "colour", "color", "colors", "styles", - "formatting", "terminal", "xterm", "console", @@ -18,39 +15,22 @@ "log", "logging", "strip-color", - "strip", "truecolor", - "foreground", - "background", "rgb", - "hex", - "black", "red", "green", "yellow", "blue", "magenta", "cyan", - "white", - "gray", - "grey", - "bgRed", - "inverse", - "visible", - "inverse", - "bold", - "italic", - "underline", - "strikethrough", + "FORCE_COLOR", + "NO_COLOR", "ansi-colors", "chalk", "colorette", "colors.js", "kleur", - "nanocolors", - "picocolors", - "FORCE_COLOR", - "NO_COLOR" + "picocolors" ], "license": "ISC", "author": "webdiscus (https://github.com/webdiscus)", @@ -80,20 +60,18 @@ }, "./colors": { "types": "./colors.d.ts", - "import": "./colors.mjs", - "require": "./colors.cjs" + "import": "./colors.js", + "require": "./colors.js" } }, "engines": { "node": ">=12.13" }, "files": [ - "bundle.js", "index.d.ts", "index.js", "colors.d.ts", - "colors.cjs", - "colors.mjs", + "colors.js", "package.json", "LICENSE", "README.md" diff --git a/rollup.config.js b/rollup.config.js index 36132cd..3472096 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,6 @@ import copy from 'rollup-plugin-copy'; import cleanup from 'rollup-plugin-cleanup'; -import dts from "rollup-plugin-dts"; +import dts from 'rollup-plugin-dts'; import { terser } from 'rollup-plugin-terser'; // last ECMA version compatible with node.js 12 @@ -14,7 +14,7 @@ export default [ intro: '/* Auto generated by rollup.\nUse `npm run build` to create new version. */', exports: 'named', // note: this bundle needs the wrapper `./dist/index.js` to properly export defaults - file: './dist/bundle.js', + file: './dist/colors.js', format: 'cjs', }, ], @@ -23,17 +23,11 @@ export default [ ecma, compress: { ecma, - } - }), - copy({ - targets: [ - { src: 'package/package.json', dest: 'dist/' }, - { src: 'src/colors.cjs', dest: 'dist/' }, - { src: 'src/colors.mjs', dest: 'dist/' }, - { src: 'README.md', dest: 'dist/' }, - { src: 'LICENSE', dest: 'dist/' }, - ], + passes: 2, + }, + toplevel: true, }), + ], }, @@ -46,9 +40,6 @@ export default [ }, ], plugins: [ - cleanup({ - extensions: ['ts'] - }), dts(), ], }, @@ -62,9 +53,6 @@ export default [ }, ], plugins: [ - cleanup({ - extensions: ['ts'] - }), dts(), ], }, @@ -78,8 +66,15 @@ export default [ }, ], plugins: [ + copy({ + targets: [ + { src: 'package/package.json', dest: 'dist/' }, + { src: 'README.md', dest: 'dist/' }, + { src: 'LICENSE', dest: 'dist/' }, + ], + }), cleanup({ - extensions: ['js'] + extensions: ['js', 'ts', 'mjs', 'cjs'], }), ], }, diff --git a/src/ansi-codes.js b/src/ansi-codes.js index da4ac3e..060d8e6 100644 --- a/src/ansi-codes.js +++ b/src/ansi-codes.js @@ -1,8 +1,8 @@ /** - * @param {Object?} processMock The mock of process object, used by unit test only. + * @param {Object?} mockThis The mock object of globalThis, used by unit test only. * @returns {boolean} */ -export const isSupported = (processMock) => { +export const isSupported = (mockThis) => { /** * Detect whether flags exist with `-` or `--` prefix in command-line arguments. * @@ -11,14 +11,25 @@ export const isSupported = (processMock) => { */ const oneOfFlags = (regex) => !!argv.find((value) => regex.test(value)); - const proc = processMock ? processMock : typeof process !== 'undefined' ? process : {}; - const { stdout, platform } = proc; - const env = proc.env || {}; - const argv = proc.argv || []; + 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 hasForceColor = 'FORCE_COLOR' in env; const forceColorValue = env.FORCE_COLOR; - const forceColor = forceColorValue === 'true' || parseInt(forceColorValue) > 0; + const forceColor = forceColorValue === 'true' || parseInt(forceColorValue, 10) > 0; const isForceDisabled = 'NO_COLOR' in env || (hasForceColor && !forceColor) @@ -26,19 +37,26 @@ export const isSupported = (processMock) => { const isForceEnabled = (hasForceColor && forceColor) || oneOfFlags(/^-{1,2}(color|color=true|color=always)$/); - const isTerm = stdout && 'isTTY' in stdout && + 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 || platform === 'win32' || 'CI' in env); + return !isForceDisabled && (isForceEnabled || isTerm || isWin || 'CI' in env); }; const noColor = { open: '', close: '' }; const esc = isSupported() ? (open, close) => ({ open: `\x1b[${open}m`, close: `\x1b[${close}m` }) : () => noColor; -export const ansi256 = (code) => esc(`38;5;${code}`, 39); -export const bgAnsi256 = (code) => esc(`48;5;${code}`, 49); -export const rgb = (r, g, b) => esc(`38;2;${r};${g};${b}`, 39); -export const bgRgb = (r, g, b) => esc(`48;2;${r};${g};${b}`, 49); +export const fnAnsi256 = (code) => esc(`38;5;${code}`, 39); +export const fnBgAnsi256 = (code) => esc(`48;5;${code}`, 49); +export const fnRgb = (r, g, b) => esc(`38;2;${r};${g};${b}`, 39); +export const fnBgRgb = (r, g, b) => esc(`48;2;${r};${g};${b}`, 49); export const baseStyles = { // misc diff --git a/src/index.js b/src/index.js index a4e2afb..c3e4fa6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ import { hexToRgb, clamp, strReplaceAll } from './utils.js'; -import { baseStyles, ansi256, bgAnsi256, rgb, bgRgb } from './ansi-codes.js'; +import { baseStyles, fnAnsi256, fnBgAnsi256, fnRgb, fnBgRgb } from './ansi-codes.js'; /** * @typedef {Object} AnsisProps @@ -10,13 +10,15 @@ import { baseStyles, ansi256, bgAnsi256, rgb, bgRgb } from './ansi-codes.js'; * @property {null | AnsisProps} parent */ +//Object.defineProperty(exports, '__esModule', { value: !0 }); + const { defineProperty, defineProperties, setPrototypeOf } = Object; const stripANSIRegEx = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; const regexLF = /(\r*\n)/g; -const Ansis = function () { +const Ansis = function() { const self = (str) => str; /** @@ -42,10 +44,10 @@ const Ansis = function () { let value = colors[name]; // detect whether the value is style property Object {open, close} or a string with hex code of color '#FF0000' let hasProperty = value.open != null; - let styleCodes = hasProperty ? value : rgb(...hexToRgb(value)); + let styleCodes = hasProperty ? value : fnRgb(...hexToRgb(value)); styles[name] = { - get () { + get() { const style = createStyle(this, styleCodes); defineProperty(this, name, { value: style }); return style; @@ -93,7 +95,7 @@ const createStyle = ({ props }, { open, close }) => { * Wrap the string with styling and reset codes. * * @param {string | Array} strings A string or template literals. - * @param {Array} values The values of template literals. + * @param {Array} values The values of the template literals. * @param {AnsisProps} props * @returns {string} */ @@ -118,16 +120,16 @@ const wrap = (strings, values, props) => { }; const styleMethods = { - ansi: (code) => ansi256(clamp(code, 0, 255)), - bgAnsi: (code) => bgAnsi256(clamp(code, 0, 255)), - hex: (hex) => rgb(...hexToRgb(hex)), - bgHex: (hex) => bgRgb(...hexToRgb(hex)), - rgb: (r, g, b) => rgb( + ansi: (code) => fnAnsi256(clamp(code, 0, 255)), + bgAnsi: (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) => bgRgb( + bgRgb: (r, g, b) => fnBgRgb( clamp(r, 0, 255), clamp(g, 0, 255), clamp(b, 0, 255), @@ -140,7 +142,7 @@ let stylePrototype; // extend styles with methods: rgb(), hex(), etc. for (let name in styleMethods) { styles[name] = { - get () { + get() { return (...args) => createStyle(this, styleMethods[name](...args)); }, }; @@ -153,3 +155,71 @@ styles.bgAnsi256 = styles.bg = styles.bgAnsi; const ansis = new Ansis(); export { Ansis, ansis as default }; + +export const ansi256 = ansis.ansi256; +export const ansi = ansis.ansi; +export const fg = ansis.fg; +export const bgAnsi256 = ansis.bgAnsi256; +export const bgAnsi = ansis.bgAnsi; +export const bg = ansis.bg; +export const rgb = ansis.rgb; +export const bgRgb = ansis.bgRgb; +export const hex = ansis.hex; +export const bgHex = ansis.bgHex; + +// misc +export const reset = ansis.reset; +export const inverse = ansis.inverse; +export const hidden = ansis.hidden; +export const visible = ansis.visible; + +// styles +export const bold = ansis.bold; +export const dim = ansis.dim; +export const faint = ansis.faint; +export const italic = ansis.italic; +export const underline = ansis.underline; +export const doubleUnderline = ansis.doubleUnderline; +export const strikethrough = ansis.strikethrough; +export const strike = ansis.strike; +export const frame = ansis.frame; +export const encircle = ansis.encircle; +export const overline = ansis.overline; + +// foreground colors +export const black = ansis.black; +export const red = ansis.red; +export const green = ansis.green; +export const yellow = ansis.yellow; +export const blue = ansis.blue; +export const magenta = ansis.magenta; +export const cyan = ansis.cyan; +export const white = ansis.white; +export const gray = ansis.gray; +export const grey = ansis.grey; +export const blackBright = ansis.blackBright; +export const redBright = ansis.redBright; +export const greenBright = ansis.greenBright; +export const yellowBright = ansis.yellowBright; +export const blueBright = ansis.blueBright; +export const magentaBright = ansis.magentaBright; +export const cyanBright = ansis.cyanBright; +export const whiteBright = ansis.whiteBright; + +// background colors +export const bgBlack = ansis.bgBlack; +export const bgRed = ansis.bgRed; +export const bgGreen = ansis.bgGreen; +export const bgYellow = ansis.bgYellow; +export const bgBlue = ansis.bgBlue; +export const bgMagenta = ansis.bgMagenta; +export const bgCyan = ansis.bgCyan; +export const bgWhite = ansis.bgWhite; +export const bgBlackBright = ansis.bgBlackBright; +export const bgRedBright = ansis.bgRedBright; +export const bgGreenBright = ansis.bgGreenBright; +export const bgYellowBright = ansis.bgYellowBright; +export const bgBlueBright = ansis.bgBlueBright; +export const bgMagentaBright = ansis.bgMagentaBright; +export const bgCyanBright = ansis.bgCyanBright; +export const bgWhiteBright = ansis.bgWhiteBright; diff --git a/test/index.test.js b/test/index.test.js index 2048978..a60630d 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,11 +1,11 @@ -import { execSync } from 'child_process'; +import {execSync} from 'child_process'; import path from 'path'; // test distributed version -import ansis, { Ansis } from '../src/index.js'; -import { hexToRgb, clamp } from '../src/utils.js'; -import { isSupported } from '../src/ansi-codes.js'; -import { green, red, yellow } from '../src/colors.mjs'; +import ansis, {Ansis} from '../src/index.js'; +import {hexToRgb, clamp} from '../src/utils.js'; +import {isSupported} from '../src/ansi-codes.js'; +import {green, red, yellow} from '../src/colors.mjs'; const TEST_PATH = path.resolve('./test/'); @@ -53,217 +53,6 @@ describe('default tests', () => { }); }); -describe('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({ - 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({ - platform: 'win32', - env: {}, - argv: [], - }); - const expected = true; - expect(received).toEqual(expected); - done(); - }); - - test(`colors in any CI`, (done) => { - const received = isSupported({ - platform: 'linux', - env: { CI: 'GITLAB_CI' }, - argv: [], - }); - const expected = true; - expect(received).toEqual(expected); - done(); - }); - - test(`no colors, unsupported terminal`, (done) => { - const received = isSupported({ - 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({ - env: { TERM: 'xterm' }, - argv: [], - }); - const expected = false; - expect(received).toEqual(expected); - done(); - }); - - test(`enable colors via --color`, (done) => { - const received = isSupported({ - platform: 'linux', - env: {}, - argv: ['--color'], - }); - const expected = true; - expect(received).toEqual(expected); - done(); - }); - - test(`enable colors via -color`, (done) => { - const received = isSupported({ - platform: 'linux', - env: {}, - argv: ['-color'], - }); - const expected = true; - expect(received).toEqual(expected); - done(); - }); - - - test(`enable colors via --color=true`, (done) => { - const received = isSupported({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - 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({ - platform: 'linux', - env: { FORCE_COLOR: 'true' }, - argv: [], - }); - const expected = true; - expect(received).toEqual(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'); @@ -488,10 +277,10 @@ describe('functional tests', () => { const rgb = ansis.rgb(100, 80, 155); const received = ansis.red( `begin ${rgb.bold('RGB')} ${ansis.yellow('yellow')} red ${ansis.italic.cyan('italic cyan')} red ${ansis.red( - 'red' + 'red', )} red ${ansis.underline.green.italic( - `underline italic green ${ansis.rgb(80, 120, 200)('underline italic blue')} underline italic green` - )} red ${ansis.cyan('cyan')} red ${ansis.bold.yellow('bold yellow')} red ${ansis.green('green')} end` + `underline italic green ${ansis.rgb(80, 120, 200)('underline italic blue')} underline italic green`, + )} red ${ansis.cyan('cyan')} red ${ansis.bold.yellow('bold yellow')} red ${ansis.green('green')} end`, ); const expected = @@ -591,7 +380,7 @@ describe('template literals tests', () => { describe('extend base colors tests', () => { test('imported ansis`', (done) => { - ansis.extend({ orange: '#FFAB40' }); + ansis.extend({orange: '#FFAB40'}); const received = ansis.orange.bold('text'); const expected = '\x1b[38;2;255;171;64m\x1b[1mtext\x1b[22m\x1b[39m'; @@ -601,7 +390,7 @@ describe('extend base colors tests', () => { test('new ansis`', (done) => { const ansis = new Ansis(); - ansis.extend({ orange: '#FFAB40' }); + ansis.extend({orange: '#FFAB40'}); // test the order bold > orange const received = ansis.bold.orange('text'); @@ -609,4 +398,385 @@ 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/package/README.md b/test/package/README.md index 7180a6d..1874e4f 100644 --- a/test/package/README.md +++ b/test/package/README.md @@ -1,6 +1,6 @@ 1. Build `ansis` package from source into `dist/` directory. - Run from project directory: + Run from project directory: ``` npm run build ``` @@ -14,12 +14,10 @@ 3. Test in CommonJS mode: ``` - cd ./cjs - node ./index.js + npm run test:cjs ``` 4. Test in ESM mode: ``` - cd ./esm - node ./index.js + npm run test:esm ``` \ No newline at end of file diff --git a/test/package/cjs/index.js b/test/package/cjs/index.js index 44169f6..9307cca 100644 --- a/test/package/cjs/index.js +++ b/test/package/cjs/index.js @@ -1,11 +1,9 @@ const ansis = require('ansis'); -const { red, green, blue, yellow, magenta } = require('ansis/colors'); +const { red, yellow, green } = require('ansis/colors'); const log = console.log; log(ansis.green.inverse('CommonJS')); log(red('red')); -log(green.bold('green')); -log(blue.underline.italic('blue')); -log(yellow.italic(`yellow using ${'some'} variable`)); -log(magenta.underline`magenta using template literal`); \ No newline at end of file +log(green.bold('green bold')); +log(yellow.italic`yellow italic`); \ No newline at end of file diff --git a/test/package/esm/index.js b/test/package/esm/index.js index d3eeb2a..1821bdb 100644 --- a/test/package/esm/index.js +++ b/test/package/esm/index.js @@ -1,11 +1,9 @@ import ansis from 'ansis'; -import { red, green, blue, yellow, magenta } from 'ansis/colors'; +import { red, yellow, green } from 'ansis/colors'; const log = console.log; log(ansis.green.inverse('ESM')); log(red('red')); -log(green.bold('green')); -log(blue.underline.italic('blue')); -log(yellow.italic(`yellow using ${'some'} variable`)); -log(magenta.underline`magenta using template literal`); \ No newline at end of file +log(green.bold('green bold')); +log(yellow.italic`yellow italic`); \ No newline at end of file diff --git a/test/package/package.json b/test/package/package.json index 8cad909..08a4286 100644 --- a/test/package/package.json +++ b/test/package/package.json @@ -3,6 +3,10 @@ "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"