Comparing version 1.1.0 to 1.1.1
# Change log | ||
## 1.1.1 (2021-12-27) | ||
- add the class Ansis to create more independent instances to increase the performance by benchmark | ||
- improve performance | ||
- code refactoring | ||
- update readme | ||
## 1.1.0 (2021-12-25) | ||
@@ -4,0 +10,0 @@ - add supports the use of `open` and `close` properties for each style |
{ | ||
"name": "ansis", | ||
"version": "1.1.0", | ||
"version": "1.1.1", | ||
"description": "Color styling of text for ANSI terminals using the SGR codes defined in the ECMA-48 standard.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
100
README.md
@@ -70,3 +70,3 @@ <h1 align="center"> | ||
info: ansis.cyan.italic, | ||
warning: ansis.bgYellowBright, | ||
warning: ansis.black.bgYellowBright, | ||
ruby: ansis.hex('#E0115F'), | ||
@@ -198,12 +198,12 @@ bgAmber: ansis.bgHex('#FFBF00'), | ||
```diff | ||
colors-js 1,119,016 ops/sec | ||
colorette 4,537,603 ops/sec | ||
picocolors 3,818,885 ops/sec | ||
cli-color 470,921 ops/sec | ||
color-cli 109,666 ops/sec | ||
ansi-colors 1,267,504 ops/sec | ||
kleur/colors 2,265,820 ops/sec | ||
kleur 2,216,547 ops/sec | ||
chalk 2,272,601 ops/sec | ||
+ ansis 1,910,873 ops/sec | ||
colors-js 1,152,114 ops/sec | ||
colorette 4,548,418 ops/sec | ||
picocolors 3,832,593 ops/sec | ||
cli-color 471,929 ops/sec | ||
color-cli 110,282 ops/sec | ||
ansi-colors 1,272,164 ops/sec | ||
kleur/colors 2,278,569 ops/sec | ||
kleur 2,223,929 ops/sec | ||
chalk 2,255,589 ops/sec | ||
+ ansis 2,674,316 ops/sec | ||
``` | ||
@@ -216,12 +216,12 @@ | ||
```diff | ||
colors-js 462,720 ops/sec | ||
colorette 1,492,260 ops/sec | ||
picocolors 5,736,444 ops/sec | ||
cli-color 222,377 ops/sec | ||
color-cli 73,354 ops/sec | ||
ansi-colors 719,913 ops/sec | ||
kleur/colors 1,446,799 ops/sec | ||
kleur 3,822,845 ops/sec | ||
chalk 3,151,919 ops/sec | ||
+ ansis 4,248,414 ops/sec | ||
colors-js 475,774 ops/sec | ||
colorette 1,174,392 ops/sec | ||
picocolors 5,724,714 ops/sec | ||
cli-color 220,577 ops/sec | ||
color-cli 73,535 ops/sec | ||
ansi-colors 727,414 ops/sec | ||
kleur/colors 1,275,337 ops/sec | ||
kleur 3,843,212 ops/sec | ||
chalk 3,144,045 ops/sec | ||
+ ansis 4,360,629 ops/sec | ||
``` | ||
@@ -234,12 +234,12 @@ | ||
```diff | ||
colors-js 136,976 ops/sec | ||
colors-js 138,219 | ||
colorette (not supported) | ||
picocolors (not supported) | ||
cli-color 142,024 ops/sec | ||
color-cli 52,604 ops/sec | ||
ansi-colors 159,209 ops/sec | ||
cli-color 144,837 | ||
color-cli 52,732 | ||
ansi-colors 158,921 | ||
kleur/colors (not supported) | ||
kleur 511,077 ops/sec | ||
chalk 1,613,521 ops/sec | ||
+ ansis 5,126,060 ops/sec | ||
kleur 514,035 | ||
chalk 1,234,573 | ||
+ ansis 5,515,868 | ||
@@ -253,12 +253,12 @@ ``` | ||
```diff | ||
colors-js 165,526 ops/sec | ||
colorette 750,531 ops/sec | ||
picocolors 940,217 ops/sec | ||
cli-color 64,927 ops/sec | ||
color-cli 13,764 ops/sec | ||
ansi-colors 258,639 ops/sec | ||
kleur/colors 566,145 ops/sec | ||
kleur 645,191 ops/sec | ||
chalk 493,049 ops/sec | ||
+ ansis 354,148 ops/sec | ||
colors-js 165,202 ops/sec | ||
colorette 712,604 ops/sec | ||
picocolors 939,536 ops/sec | ||
cli-color 64,758 ops/sec | ||
color-cli 13,833 ops/sec | ||
ansi-colors 258,930 ops/sec | ||
kleur/colors 563,266 ops/sec | ||
kleur 646,985 ops/sec | ||
chalk 385,590 ops/sec | ||
+ ansis 554,813 ops/sec | ||
@@ -272,12 +272,12 @@ ``` | ||
```diff | ||
colors-js 91,036 ops/sec | ||
colorette 247,359 ops/sec | ||
picocolors 246,168 ops/sec | ||
cli-color 42,756 ops/sec | ||
color-cli 14,343 ops/sec | ||
ansi-colors 122,972 ops/sec | ||
kleur/colors 241,366 ops/sec | ||
kleur 228,477 ops/sec | ||
chalk 195,446 ops/sec | ||
+ ansis 210,382 ops/sec | ||
colors-js 89,529 ops/sec | ||
colorette 243,237 ops/sec | ||
picocolors 242,528 ops/sec | ||
cli-color 41,897 ops/sec | ||
color-cli 14,245 ops/sec | ||
ansi-colors 120,991 ops/sec | ||
kleur/colors 233,875 ops/sec | ||
kleur 220,233 ops/sec | ||
chalk 157,450 ops/sec | ||
+ ansis 205,393 ops/sec | ||
@@ -300,4 +300,4 @@ ``` | ||
kleur (not supported) | ||
chalk 2,935,616 ops/sec | ||
+ ansis 4,612,085 ops/sec | ||
chalk 2,746,362 ops/sec | ||
+ ansis 4,584,357 ops/sec | ||
``` | ||
@@ -304,0 +304,0 @@ |
@@ -1,2 +0,4 @@ | ||
const codes = { | ||
const esc = ([open, close]) => ({ open: `\x1b[${open}m`, close: `\x1b[${close}m` }); | ||
export const codes = { | ||
// commands | ||
@@ -58,2 +60,57 @@ reset: [0, 0], | ||
export default codes; | ||
export const ansiCodes = { | ||
// commands | ||
reset: esc([0, 0]), | ||
inverse: esc([7, 27]), | ||
hidden: esc([8, 28]), | ||
// styles | ||
bold: esc([1, 22]), | ||
dim: esc([2, 22]), // alias for faint | ||
faint: esc([2, 22]), | ||
italic: esc([3, 23]), | ||
underline: esc([4, 24]), | ||
doubleUnderline: esc([21, 24]), | ||
strikethrough: esc([9, 29]), | ||
strike: esc([9, 29]), // alias for strikethrough | ||
frame: esc([51, 54]), | ||
encircle: esc([52, 54]), | ||
overline: esc([53, 55]), | ||
// foreground colors | ||
black: esc([30, 39]), | ||
red: esc([31, 39]), | ||
green: esc([32, 39]), | ||
yellow: esc([33, 39]), | ||
blue: esc([34, 39]), | ||
magenta: esc([35, 39]), | ||
cyan: esc([36, 39]), | ||
white: esc([37, 39]), | ||
gray: esc([90, 39]), // alias for blackBright | ||
blackBright: esc([90, 39]), | ||
redBright: esc([91, 39]), | ||
greenBright: esc([92, 39]), | ||
yellowBright: esc([93, 39]), | ||
blueBright: esc([94, 39]), | ||
magentaBright: esc([95, 39]), | ||
cyanBright: esc([96, 39]), | ||
whiteBright: esc([97, 39]), | ||
// background colors | ||
bgBlack: esc([40, 49]), | ||
bgRed: esc([41, 49]), | ||
bgGreen: esc([42, 49]), | ||
bgYellow: esc([43, 49]), | ||
bgBlue: esc([44, 49]), | ||
bgMagenta: esc([45, 49]), | ||
bgCyan: esc([46, 49]), | ||
bgWhite: esc([47, 49]), | ||
bgBlackBright: esc([100, 49]), | ||
bgRedBright: esc([101, 49]), | ||
bgGreenBright: esc([102, 49]), | ||
bgYellowBright: esc([103, 49]), | ||
bgBlueBright: esc([104, 49]), | ||
bgMagentaBright: esc([105, 49]), | ||
bgCyanBright: esc([106, 49]), | ||
bgWhiteBright: esc([107, 49]), | ||
}; |
@@ -257,1 +257,3 @@ interface StyleProperties { | ||
export default ansis; | ||
export const Ansis: new (str: string) => AnsisInstance; |
127
src/index.js
import { clamp, hexToRgb, strReplaceAll } from './utils.js'; | ||
import ansiCodes from './ansi-codes.js'; | ||
import { ansiCodes } from './ansi-codes.js'; | ||
/** | ||
* All methods are implemented in prototype of the `styleProxy` object. | ||
* @implements {AnsisInstance} | ||
*/ | ||
export class Ansis { | ||
constructor() { | ||
const self = (str) => str; | ||
Object.setPrototypeOf(self, styleProxy); | ||
return self; | ||
} | ||
} | ||
const styles = {}; | ||
const ESC = '\x1b'; | ||
const regexLF = /(\r*\n)/g; | ||
const colorCloseRegex = /\x1B\[39m/g; | ||
const bgCloseRegex = /\x1B\[49m/g; | ||
/** | ||
* The ANSI string (ansis). | ||
* | ||
* @param {string | string[]} str | ||
* @returns {string} | ||
*/ | ||
const ansis = (...str) => str.join(' '); | ||
/** | ||
* @typedef {StyleProperties} AnsisProps | ||
* @property {string?} openStack | ||
* @property {string?} closeStack | ||
* @property {RegExp?} closeRe The regexp pattern to match the ANSI escape sequences of ending the style. | ||
* @property {null | AnsisProps} parent | ||
@@ -29,17 +30,17 @@ */ | ||
* | ||
* @param {string | string[]} strings | ||
* @param {string | string[]} str | ||
* @param {AnsisProps} props | ||
* @returns {string} | ||
*/ | ||
const wrap = (strings, props) => { | ||
let str = strings.length === 1 ? '' + strings[0] : strings.join(' '); | ||
const wrap = (str, props) => { | ||
if (!str) return ''; | ||
const { openStack, closeStack } = props; | ||
if (str.indexOf(ESC) > -1) { | ||
if (str.indexOf('\x1b') > -1) { | ||
while (props !== undefined) { | ||
str = strReplaceAll(str, props); | ||
str = strReplaceAll(str, props.close, props.open); | ||
props = props.parent; | ||
} | ||
} | ||
if (str.indexOf('\n') > -1) str = str.replace(regexLF, closeStack + '$1' + openStack); | ||
@@ -51,20 +52,20 @@ | ||
/** | ||
* @param {AnsisProps} props | ||
* @param {string} open | ||
* @param {string} close | ||
* @param {AnsisProps} parent | ||
* @returns {AnsisInstance} | ||
*/ | ||
const createStyle = (props) => { | ||
const { open, close, parent } = props; | ||
const createStyle = (open, close, parent) => { | ||
let openStack = open; | ||
let closeStack = close; | ||
if (parent !== undefined) { | ||
props.openStack = parent.openStack + open; | ||
props.closeStack = close + parent.closeStack; | ||
} else { | ||
props.openStack = open; | ||
props.closeStack = close; | ||
openStack = parent.openStack + open; | ||
closeStack = close + parent.closeStack; | ||
} | ||
const style = (...strings) => wrap(strings, style.props); | ||
const style = (str) => wrap(str, style.props); | ||
Object.setPrototypeOf(style, styleProxy); | ||
style.props = props; | ||
style.open = props.openStack; | ||
style.close = props.closeStack; | ||
style.props = { open, close, openStack, closeStack, parent }; | ||
style.open = openStack; | ||
style.close = closeStack; | ||
@@ -78,11 +79,6 @@ return style; | ||
for (let name in ansiCodes) { | ||
const [open, close] = ansiCodes[name]; | ||
const { open, close } = ansiCodes[name]; | ||
styles[name] = { | ||
get() { | ||
const style = createStyle({ | ||
open: `\x1B[${open}m`, | ||
close: `\x1B[${close}m`, | ||
closeRe: new RegExp(`\\x1B\\[${close}m`, 'g'), | ||
parent: this.props, | ||
}); | ||
const style = createStyle(open, close, this.props); | ||
Object.defineProperty(this, name, { value: style }); | ||
@@ -99,8 +95,3 @@ return style; | ||
get() { | ||
return createStyle({ | ||
open: '', | ||
close: '', | ||
closeRe: null, | ||
parent: this.props, | ||
}); | ||
return createStyle('', '', this.props); | ||
}, | ||
@@ -116,8 +107,3 @@ }; | ||
num = clamp(num, 0, 255); | ||
return createStyle({ | ||
open: `\x1B[38;5;${num}m`, | ||
close: '\x1B[39m', | ||
closeRe: colorCloseRegex, | ||
parent: this.props, | ||
}); | ||
return createStyle(`\x1B[38;5;${num}m`, '\x1B[39m', this.props); | ||
}; | ||
@@ -134,9 +120,3 @@ }, | ||
num = clamp(num, 0, 255); | ||
return createStyle({ | ||
open: `\x1B[48;5;${num}m`, | ||
close: '\x1B[49m', | ||
closeRe: bgCloseRegex, | ||
parent: this.props, | ||
}); | ||
return createStyle(`\x1B[48;5;${num}m`, '\x1B[49m', this.props); | ||
}; | ||
@@ -155,9 +135,3 @@ }, | ||
b = clamp(b, 0, 255); | ||
return createStyle({ | ||
open: `\x1B[38;2;${r};${g};${b}m`, | ||
close: '\x1B[39m', | ||
closeRe: colorCloseRegex, | ||
parent: this.props, | ||
}); | ||
return createStyle(`\x1B[38;2;${r};${g};${b}m`, '\x1B[39m', this.props); | ||
}; | ||
@@ -174,9 +148,3 @@ }, | ||
const [r, g, b] = hexToRgb(hex); | ||
return createStyle({ | ||
open: `\x1B[38;2;${r};${g};${b}m`, | ||
close: '\x1B[39m', | ||
closeRe: colorCloseRegex, | ||
parent: this.props, | ||
}); | ||
return createStyle(`\x1B[38;2;${r};${g};${b}m`, '\x1B[39m', this.props); | ||
}; | ||
@@ -195,9 +163,3 @@ }, | ||
b = clamp(b, 0, 255); | ||
return createStyle({ | ||
open: `\x1B[48;2;${r};${g};${b}m`, | ||
close: '\x1B[49m', | ||
closeRe: bgCloseRegex, | ||
parent: this.props, | ||
}); | ||
return createStyle(`\x1B[48;2;${r};${g};${b}m`, '\x1B[49m', this.props); | ||
}; | ||
@@ -214,9 +176,3 @@ }, | ||
const [r, g, b] = hexToRgb(hex); | ||
return createStyle({ | ||
open: `\x1B[48;2;${r};${g};${b}m`, | ||
close: '\x1B[49m', | ||
closeRe: bgCloseRegex, | ||
parent: this.props, | ||
}); | ||
return createStyle(`\x1B[48;2;${r};${g};${b}m`, '\x1B[49m', this.props); | ||
}; | ||
@@ -227,4 +183,3 @@ }, | ||
const styleProxy = Object.defineProperties(() => {}, styles); | ||
Object.setPrototypeOf(ansis, styleProxy); | ||
export default ansis; | ||
export default new Ansis(); |
import tty from 'tty'; | ||
// todo Add supports NO_COLOR | ||
export const isSupported = () => { | ||
if (!process) return false; | ||
// export const isSupported = () => { | ||
// if (!process) return false; | ||
// | ||
// const env = process.env || {}; | ||
// const argv = process.argv || []; | ||
// const isDisabled = 'NO_COLOR' in env || argv.includes('--no-color'); | ||
// const isForced = 'FORCE_COLOR' in env || argv.includes('--color'); | ||
// | ||
// const isCompatibleTerminal = (tty.isatty(1) && env.TERM && env.TERM !== 'dumb') || process.platform === 'win32'; | ||
// const isCI = 'CI' in env; | ||
// | ||
// return !isDisabled && (isForced || isCompatibleTerminal || isCI); | ||
// }; | ||
const env = process.env || {}; | ||
const argv = process.argv || []; | ||
const isDisabled = 'NO_COLOR' in env || argv.includes('--no-color'); | ||
const isForced = 'FORCE_COLOR' in env || argv.includes('--color'); | ||
const isCompatibleTerminal = (tty.isatty(1) && env.TERM && env.TERM !== 'dumb') || process.platform === 'win32'; | ||
const isCI = 'CI' in env; | ||
return !isDisabled && (isForced || isCompatibleTerminal || isCI); | ||
}; | ||
/** | ||
@@ -59,12 +59,27 @@ * Convert hex color string to RGB values. | ||
/** | ||
* Replace all matched strings. | ||
* Note: this implementation is over 30% faster than String.replaceAll(). | ||
* | ||
* @param {string} str | ||
* @param {{open: string, close: string} | {open: string, closeRe: RegExp}} props | ||
* @param {string} searchValue | ||
* @param {string} replaceValue | ||
* @returns {string} | ||
*/ | ||
export const strReplaceAll = | ||
String.prototype.replaceAll != null | ||
? // node >= 15 | ||
(str, { close, open }) => str.replaceAll(close, open) | ||
: // node < 15 | ||
(str, { closeRe, open }) => str.replace(closeRe, open); | ||
export const strReplaceAll = function (str, searchValue, replaceValue) { | ||
let pos = str.indexOf(searchValue); | ||
if (pos < 0) return str; | ||
const substringLength = searchValue.length; | ||
let lastPos = 0; | ||
let result = ''; | ||
while (pos > -1) { | ||
result += str.substr(lastPos, pos - lastPos) + replaceValue; | ||
lastPos = pos + substringLength; | ||
pos = str.indexOf(searchValue, lastPos); | ||
} | ||
return result + str.substr(lastPos); | ||
}; | ||
/** | ||
@@ -71,0 +86,0 @@ * The style must be break at the end of the line and continued on a new line. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
28643
561
0