printstyle 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +163 -0
- package/index.d.ts +124 -0
- package/index.js +190 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Stamat
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# PrintStyle 🌈
|
|
2
|
+
|
|
3
|
+
ANSI terminal styling with a built-in micro template language.
|
|
4
|
+
|
|
5
|
+
Most color libraries make you chain function calls or concatenate escape codes by hand. PrintStyle gives you `paint()` — a template syntax that reads like markup and just works.
|
|
6
|
+
|
|
7
|
+
```js
|
|
8
|
+
import PrintStyle from "printstyle";
|
|
9
|
+
const ps = new PrintStyle();
|
|
10
|
+
|
|
11
|
+
ps.paint("{red|Error:} Woops something went wrong!");
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Why PrintStyle?
|
|
15
|
+
|
|
16
|
+
- **Template syntax** — `paint()` lets you style strings inline without concatenation chains or nested calls. No other terminal color package has this built in.
|
|
17
|
+
- **Tiny** — ~9 KB unpacked, zero dependencies.
|
|
18
|
+
- **Hex colors** — use any color, not just the 16 built-in ANSI names.
|
|
19
|
+
- **NO_COLOR / FORCE_COLOR** — follows the standard out of the box.
|
|
20
|
+
- **No magic** — plain class with string properties. No Proxy, no prototype tricks, no chaining API. Easy to debug, easy to understand.
|
|
21
|
+
|
|
22
|
+
**Note:** Legacy Windows CMD (before Windows 10) does not support ANSI escape codes. Use Windows Terminal, PowerShell, or WSL instead.
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install printstyle
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Template Syntax — `paint()`
|
|
31
|
+
|
|
32
|
+
### Wrap mode (auto-reset)
|
|
33
|
+
|
|
34
|
+
Style is applied and automatically reset after the content:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
ps.paint("{red|error message}"); // red text, then reset
|
|
38
|
+
ps.paint("{bold.red|ERROR}"); // bold + red, then reset
|
|
39
|
+
ps.paint("{bgRed.white| FAIL }"); // red background, white text
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Spanning mode (manual reset)
|
|
43
|
+
|
|
44
|
+
Style stays active until you close with `{/}`:
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
ps.paint("{red}all of this is red{/}");
|
|
48
|
+
ps.paint("{dim}prefix {bold|inner} still dim{/}");
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Dot-chaining
|
|
52
|
+
|
|
53
|
+
Combine multiple styles with `.`:
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
ps.paint("{bgRed.white.bold|FAIL}"); // background + foreground + style
|
|
57
|
+
ps.paint("{green.bold|✓} {dim|file.jpg}"); // multiple wraps in one string
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Hex colors
|
|
61
|
+
|
|
62
|
+
Use any hex color for foreground or background:
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
ps.paint("{#2e8b57|sea green text}");
|
|
66
|
+
ps.paint("{bg#ff5500.white|orange background}");
|
|
67
|
+
ps.paint("{#f00|shorthand red}"); // 3-char hex supported
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Direct Property Access
|
|
71
|
+
|
|
72
|
+
Every ANSI code is also available as a string property for manual concatenation:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
console.log(ps.red + "error" + ps.reset);
|
|
76
|
+
console.log(ps.bold + ps.blue + "title" + ps.reset);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Available properties
|
|
80
|
+
|
|
81
|
+
**Styles:** `reset` `bold` `dim` `italic` `underline` `blink` `inverse` `hidden` `strikethrough`
|
|
82
|
+
|
|
83
|
+
**Colors:** `black` `red` `green` `yellow` `blue` `magenta` `cyan` `white` `gray`
|
|
84
|
+
|
|
85
|
+
**Bright colors:** `redBright` `greenBright` `yellowBright` `blueBright` `magentaBright` `cyanBright` `whiteBright`
|
|
86
|
+
|
|
87
|
+
**Backgrounds:** `bgBlack` `bgRed` `bgGreen` `bgYellow` `bgBlue` `bgMagenta` `bgCyan` `bgWhite` `bgGray`
|
|
88
|
+
|
|
89
|
+
**Bright backgrounds:** `bgRedBright` `bgGreenBright` `bgYellowBright` `bgBlueBright` `bgMagentaBright` `bgCyanBright` `bgWhiteBright`
|
|
90
|
+
|
|
91
|
+
**Other:** `bell`
|
|
92
|
+
|
|
93
|
+
## Custom Styles — `extend()`
|
|
94
|
+
|
|
95
|
+
Register your own named styles built from any combination of built-in codes or hex colors:
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
const ps = new PrintStyle();
|
|
99
|
+
|
|
100
|
+
ps.extend({
|
|
101
|
+
error: ps.bold + ps.red,
|
|
102
|
+
success: ps.bold + ps.green,
|
|
103
|
+
warning: ps.yellow,
|
|
104
|
+
brand: ps.color("#ff6600"),
|
|
105
|
+
link: ps.blue + ps.underline + ps.italic,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
console.log(ps.paint("{error|Something failed}"));
|
|
109
|
+
console.log(ps.paint("{success|All good}"));
|
|
110
|
+
console.log(ps.paint("{brand|Acme Corp}"));
|
|
111
|
+
console.log(ps.paint("{link|https://github.com/stamat/printstyle}"));
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Custom styles work everywhere built-in styles do — in `paint()` templates, dot-chaining, direct property access, and they integrate with `disable()` / `enable()`.
|
|
115
|
+
|
|
116
|
+
## Hex Color Methods
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
ps.color("#ff0000"); // foreground escape sequence for hex
|
|
120
|
+
ps.background("#00ff00"); // background escape sequence for hex
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Both accept 6-char (`#ff0000`) or 3-char (`#f00`) hex, with or without `#`.
|
|
124
|
+
|
|
125
|
+
## NO_COLOR / FORCE_COLOR
|
|
126
|
+
|
|
127
|
+
PrintStyle respects the [NO_COLOR](https://no-color.org/) and [FORCE_COLOR](https://force-color.org/) environment variables automatically:
|
|
128
|
+
|
|
129
|
+
- `NO_COLOR` (any value) — disables all color output
|
|
130
|
+
- `FORCE_COLOR=1` — forces color output regardless of `NO_COLOR`
|
|
131
|
+
- `FORCE_COLOR=0` — disables color output
|
|
132
|
+
|
|
133
|
+
You can also control it programmatically:
|
|
134
|
+
|
|
135
|
+
```js
|
|
136
|
+
ps.disable(); // turn off all codes
|
|
137
|
+
ps.enable(); // restore all codes
|
|
138
|
+
ps.enabled; // check current state
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Comparison
|
|
142
|
+
|
|
143
|
+
| | printstyle | chalk | ansis | picocolors | kleur | ansi-colors | yoctocolors |
|
|
144
|
+
| ------------------- | ---------- | ------------ | --------- | ---------- | --------- | ----------- | ----------- |
|
|
145
|
+
| **Unpacked size** | ~9 KB | ~44 KB | ~6 KB | ~6 KB | ~20 KB | ~26 KB | ~10 KB |
|
|
146
|
+
| **Runtime deps** | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
|
|
147
|
+
| **Template syntax** | Built-in | Separate pkg | No | No | No | No | No |
|
|
148
|
+
| **Hex colors** | Yes | Yes | Yes | No | No | No | No |
|
|
149
|
+
| **NO_COLOR** | Yes | No | Yes | Yes | Yes | No | Yes |
|
|
150
|
+
| **FORCE_COLOR** | Yes | Yes | Yes | Yes | Yes | Partial | Yes |
|
|
151
|
+
| **TypeScript** | Built-in | Built-in | Built-in | Built-in | Built-in | Built-in | Built-in |
|
|
152
|
+
| **Module type** | ESM | ESM | CJS + ESM | CJS + ESM | CJS + ESM | CJS | ESM |
|
|
153
|
+
| **Legacy Win CMD** | No | Yes | No | No | No | No | No |
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
[MIT](LICENSE)
|
|
158
|
+
|
|
159
|
+
## P.S.
|
|
160
|
+
|
|
161
|
+
> Another one - DJ Khaled
|
|
162
|
+
|
|
163
|
+
❤️, @stamat
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal ANSI terminal styling with a built-in micro template language.
|
|
3
|
+
*/
|
|
4
|
+
export default class PrintStyle {
|
|
5
|
+
/** Whether ANSI codes are currently active. */
|
|
6
|
+
enabled: boolean
|
|
7
|
+
|
|
8
|
+
// Styles
|
|
9
|
+
reset: string
|
|
10
|
+
bold: string
|
|
11
|
+
dim: string
|
|
12
|
+
italic: string
|
|
13
|
+
underline: string
|
|
14
|
+
blink: string
|
|
15
|
+
inverse: string
|
|
16
|
+
hidden: string
|
|
17
|
+
strikethrough: string
|
|
18
|
+
|
|
19
|
+
// Foreground colors
|
|
20
|
+
black: string
|
|
21
|
+
red: string
|
|
22
|
+
redBright: string
|
|
23
|
+
green: string
|
|
24
|
+
greenBright: string
|
|
25
|
+
yellow: string
|
|
26
|
+
yellowBright: string
|
|
27
|
+
blue: string
|
|
28
|
+
blueBright: string
|
|
29
|
+
magenta: string
|
|
30
|
+
magentaBright: string
|
|
31
|
+
cyan: string
|
|
32
|
+
cyanBright: string
|
|
33
|
+
white: string
|
|
34
|
+
whiteBright: string
|
|
35
|
+
gray: string
|
|
36
|
+
|
|
37
|
+
// Background colors
|
|
38
|
+
bgBlack: string
|
|
39
|
+
bgRed: string
|
|
40
|
+
bgRedBright: string
|
|
41
|
+
bgGreen: string
|
|
42
|
+
bgGreenBright: string
|
|
43
|
+
bgYellow: string
|
|
44
|
+
bgYellowBright: string
|
|
45
|
+
bgBlue: string
|
|
46
|
+
bgBlueBright: string
|
|
47
|
+
bgMagenta: string
|
|
48
|
+
bgMagentaBright: string
|
|
49
|
+
bgCyan: string
|
|
50
|
+
bgCyanBright: string
|
|
51
|
+
bgWhite: string
|
|
52
|
+
bgWhiteBright: string
|
|
53
|
+
bgGray: string
|
|
54
|
+
|
|
55
|
+
// Other
|
|
56
|
+
bell: string
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Disable all ANSI codes. Properties become empty strings.
|
|
60
|
+
* The `bell` property is preserved.
|
|
61
|
+
*/
|
|
62
|
+
disable(): void
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Re-enable all ANSI codes, restoring their original values.
|
|
66
|
+
*/
|
|
67
|
+
enable(): void
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Register custom named styles.
|
|
71
|
+
* Extended styles integrate with `disable()` and `enable()` and are usable in `paint()` templates.
|
|
72
|
+
* @param styles An object mapping style names to ANSI escape strings.
|
|
73
|
+
*/
|
|
74
|
+
extend(styles: Record<string, string>): void
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Parse a hex color string into an [R, G, B] array.
|
|
78
|
+
* @param hex Hex color string (e.g. `'#ff0000'`, `'f00'`).
|
|
79
|
+
* @returns An array of [red, green, blue] values (0–255).
|
|
80
|
+
*/
|
|
81
|
+
hexToRgb(hex: string): [number, number, number]
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Convert RGB values to a 256-color terminal index.
|
|
85
|
+
* @param red Red channel (0–255).
|
|
86
|
+
* @param green Green channel (0–255).
|
|
87
|
+
* @param blue Blue channel (0–255).
|
|
88
|
+
* @returns The terminal color index (16–231).
|
|
89
|
+
*/
|
|
90
|
+
terminalColorIndex(red: number, green: number, blue: number): number
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get a 256-color foreground escape sequence for a hex color.
|
|
94
|
+
* @param hex Hex color string (e.g. `'#ff0000'`, `'f00'`).
|
|
95
|
+
* @returns The ANSI escape sequence, or `''` if disabled.
|
|
96
|
+
*/
|
|
97
|
+
color(hex: string): string
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get a 256-color background escape sequence for a hex color.
|
|
101
|
+
* @param hex Hex color string (e.g. `'#ff0000'`, `'f00'`).
|
|
102
|
+
* @returns The ANSI escape sequence, or `''` if disabled.
|
|
103
|
+
*/
|
|
104
|
+
background(hex: string): string
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Apply styles to a string using a micro template syntax.
|
|
108
|
+
*
|
|
109
|
+
* **Wrap mode** (auto-reset): `{style|content}` — e.g. `'{red|error}'`
|
|
110
|
+
*
|
|
111
|
+
* **Spanning mode** (manual reset): `{style}...{/}` — e.g. `'{red}error{/}'`
|
|
112
|
+
*
|
|
113
|
+
* Styles can be dot-chained: `'{bold.red|ERROR}'`
|
|
114
|
+
*
|
|
115
|
+
* Hex colors: `'{#2e8b57|text}'`, `'{bg#ff5500|text}'`
|
|
116
|
+
*
|
|
117
|
+
* @param str The template string to process.
|
|
118
|
+
* @returns The string with ANSI escape sequences applied.
|
|
119
|
+
*/
|
|
120
|
+
paint(str: string): string
|
|
121
|
+
|
|
122
|
+
/** Allow custom styles added via `extend()`. */
|
|
123
|
+
[key: string]: string | boolean | ((...args: any[]) => any)
|
|
124
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal ANSI terminal styling with a built-in micro template language.
|
|
3
|
+
*/
|
|
4
|
+
export default class PrintStyle {
|
|
5
|
+
enabled = true
|
|
6
|
+
reset = '\x1b[0m'
|
|
7
|
+
bold = '\x1b[1m'
|
|
8
|
+
dim = '\x1b[2m'
|
|
9
|
+
italic = '\x1b[3m'
|
|
10
|
+
underline = '\x1b[4m'
|
|
11
|
+
blink = '\x1b[5m'
|
|
12
|
+
inverse = '\x1b[7m'
|
|
13
|
+
hidden = '\x1b[8m'
|
|
14
|
+
strikethrough = '\x1b[9m'
|
|
15
|
+
black = '\x1b[30m'
|
|
16
|
+
red = '\x1b[31m'
|
|
17
|
+
redBright = '\x1b[91m'
|
|
18
|
+
green = '\x1b[32m'
|
|
19
|
+
greenBright = '\x1b[92m'
|
|
20
|
+
yellow = '\x1b[33m'
|
|
21
|
+
yellowBright = '\x1b[93m'
|
|
22
|
+
blue = '\x1b[34m'
|
|
23
|
+
blueBright = '\x1b[94m'
|
|
24
|
+
magenta = '\x1b[35m'
|
|
25
|
+
magentaBright = '\x1b[95m'
|
|
26
|
+
cyan = '\x1b[36m'
|
|
27
|
+
cyanBright = '\x1b[96m'
|
|
28
|
+
white = '\x1b[37m'
|
|
29
|
+
whiteBright = '\x1b[97m'
|
|
30
|
+
gray = '\x1b[90m'
|
|
31
|
+
bgBlack = '\x1b[40m'
|
|
32
|
+
bgRed = '\x1b[41m'
|
|
33
|
+
bgRedBright = '\x1b[101m'
|
|
34
|
+
bgGreen = '\x1b[42m'
|
|
35
|
+
bgGreenBright = '\x1b[102m'
|
|
36
|
+
bgYellow = '\x1b[43m'
|
|
37
|
+
bgYellowBright = '\x1b[103m'
|
|
38
|
+
bgBlue = '\x1b[44m'
|
|
39
|
+
bgBlueBright = '\x1b[104m'
|
|
40
|
+
bgMagenta = '\x1b[45m'
|
|
41
|
+
bgMagentaBright = '\x1b[105m'
|
|
42
|
+
bgCyan = '\x1b[46m'
|
|
43
|
+
bgCyanBright = '\x1b[106m'
|
|
44
|
+
bgWhite = '\x1b[47m'
|
|
45
|
+
bgWhiteBright = '\x1b[107m'
|
|
46
|
+
bgGray = '\x1b[100m'
|
|
47
|
+
bell = '\x07'
|
|
48
|
+
|
|
49
|
+
constructor() {
|
|
50
|
+
this._defaults = {}
|
|
51
|
+
for (const key of Object.keys(this)) {
|
|
52
|
+
if (typeof this[key] === 'string') this._defaults[key] = this[key]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const env = typeof process !== 'undefined' && process.env ? process.env : {}
|
|
56
|
+
if ('FORCE_COLOR' in env) {
|
|
57
|
+
if (env.FORCE_COLOR === '0') this.disable()
|
|
58
|
+
} else if ('NO_COLOR' in env) {
|
|
59
|
+
this.disable()
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Disable all ANSI codes. Properties become empty strings.
|
|
65
|
+
* The `bell` property is preserved.
|
|
66
|
+
*/
|
|
67
|
+
disable() {
|
|
68
|
+
this.enabled = false
|
|
69
|
+
for (const key of Object.keys(this._defaults)) {
|
|
70
|
+
if (key === 'bell') continue
|
|
71
|
+
this[key] = ''
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Re-enable all ANSI codes, restoring their original values.
|
|
77
|
+
*/
|
|
78
|
+
enable() {
|
|
79
|
+
this.enabled = true
|
|
80
|
+
for (const [key, value] of Object.entries(this._defaults)) {
|
|
81
|
+
this[key] = value
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Register custom named styles.
|
|
87
|
+
* Extended styles integrate with `disable()` and `enable()` and are usable in `paint()` templates.
|
|
88
|
+
* @param {Record<string, string>} styles - An object mapping style names to ANSI escape strings.
|
|
89
|
+
* @example
|
|
90
|
+
* ps.extend({
|
|
91
|
+
* error: ps.bold + ps.red,
|
|
92
|
+
* brand: ps.color('#ff6600'),
|
|
93
|
+
* })
|
|
94
|
+
* ps.paint('{error|Something failed}')
|
|
95
|
+
*/
|
|
96
|
+
extend(styles) {
|
|
97
|
+
for (const [key, value] of Object.entries(styles)) {
|
|
98
|
+
this[key] = value
|
|
99
|
+
this._defaults[key] = value
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Parse a hex color string into an [R, G, B] array.
|
|
105
|
+
* @param {string} hex - Hex color string (e.g. `'#ff0000'`, `'f00'`).
|
|
106
|
+
* @returns {number[]} An array of [red, green, blue] values (0–255).
|
|
107
|
+
*/
|
|
108
|
+
hexToRgb(hex) {
|
|
109
|
+
let h = hex.replace('#', '')
|
|
110
|
+
if (h.length === 3) h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2]
|
|
111
|
+
const red = parseInt(h.substring(0, 2), 16)
|
|
112
|
+
const green = parseInt(h.substring(2, 4), 16)
|
|
113
|
+
const blue = parseInt(h.substring(4, 6), 16)
|
|
114
|
+
|
|
115
|
+
return [
|
|
116
|
+
isNaN(red) ? 0 : red,
|
|
117
|
+
isNaN(green) ? 0 : green,
|
|
118
|
+
isNaN(blue) ? 0 : blue
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Convert RGB values to a 256-color terminal index.
|
|
124
|
+
* @param {number} red - Red channel (0–255).
|
|
125
|
+
* @param {number} green - Green channel (0–255).
|
|
126
|
+
* @param {number} blue - Blue channel (0–255).
|
|
127
|
+
* @returns {number} The terminal color index (16–231).
|
|
128
|
+
*/
|
|
129
|
+
terminalColorIndex(red, green, blue) {
|
|
130
|
+
return 16 +
|
|
131
|
+
Math.round(red / 255 * 5) * 36 +
|
|
132
|
+
Math.round(green / 255 * 5) * 6 +
|
|
133
|
+
Math.round(blue / 255 * 5)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get a 256-color foreground escape sequence for a hex color.
|
|
138
|
+
* @param {string} hex - Hex color string (e.g. `'#ff0000'`, `'f00'`).
|
|
139
|
+
* @returns {string} The ANSI escape sequence, or `''` if disabled.
|
|
140
|
+
*/
|
|
141
|
+
color(hex) {
|
|
142
|
+
if (!this.enabled) return ''
|
|
143
|
+
const [red, green, blue] = this.hexToRgb(hex)
|
|
144
|
+
|
|
145
|
+
return `\x1b[38;5;${this.terminalColorIndex(red, green, blue)}m`
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get a 256-color background escape sequence for a hex color.
|
|
150
|
+
* @param {string} hex - Hex color string (e.g. `'#ff0000'`, `'f00'`).
|
|
151
|
+
* @returns {string} The ANSI escape sequence, or `''` if disabled.
|
|
152
|
+
*/
|
|
153
|
+
background(hex) {
|
|
154
|
+
if (!this.enabled) return ''
|
|
155
|
+
const [red, green, blue] = this.hexToRgb(hex)
|
|
156
|
+
|
|
157
|
+
return `\x1b[48;5;${this.terminalColorIndex(red, green, blue)}m`
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** @private */
|
|
161
|
+
_resolveToken(token) {
|
|
162
|
+
if (token === '/') return this.reset
|
|
163
|
+
if (token.startsWith('bg#')) return this.background(token.slice(2))
|
|
164
|
+
if (token.startsWith('#')) return this.color(token)
|
|
165
|
+
return (typeof this[token] === 'string') ? this[token] : ''
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Apply styles to a string using a micro template syntax.
|
|
170
|
+
*
|
|
171
|
+
* **Wrap mode** (auto-reset): `{style|content}` — e.g. `'{red|error}'`
|
|
172
|
+
*
|
|
173
|
+
* **Spanning mode** (manual reset): `{style}...{/}` — e.g. `'{red}error{/}'`
|
|
174
|
+
*
|
|
175
|
+
* Styles can be dot-chained: `'{bold.red|ERROR}'`
|
|
176
|
+
*
|
|
177
|
+
* Hex colors: `'{#2e8b57|text}'`, `'{bg#ff5500|text}'`
|
|
178
|
+
*
|
|
179
|
+
* @param {string} str - The template string to process.
|
|
180
|
+
* @returns {string} The string with ANSI escape sequences applied.
|
|
181
|
+
*/
|
|
182
|
+
paint(str) {
|
|
183
|
+
return str.replace(/\{([^}]+?)(?:\|([^}]*))?\}/g, (_, style, content) => {
|
|
184
|
+
if (style === '/') return this.reset
|
|
185
|
+
const codes = style.split('.').map(t => this._resolveToken(t)).join('')
|
|
186
|
+
if (content !== undefined) return codes + content + this.reset
|
|
187
|
+
return codes
|
|
188
|
+
})
|
|
189
|
+
}
|
|
190
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "printstyle",
|
|
3
|
+
"description": "Minimal, zero-dependency ANSI terminal styling with a micro template language.",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./index.d.ts",
|
|
12
|
+
"default": "./index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"index.js",
|
|
17
|
+
"index.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"author": "Stamat <@stamat> (http://stamat.info)",
|
|
20
|
+
"homepage": "https://github.com/stamat/printstyle",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/stamat/printstyle.git"
|
|
24
|
+
},
|
|
25
|
+
"private": false,
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ansi",
|
|
28
|
+
"colors",
|
|
29
|
+
"style",
|
|
30
|
+
"template",
|
|
31
|
+
"cli",
|
|
32
|
+
"zero-dependency"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"lint": "eslint ./index.js",
|
|
36
|
+
"test": "NODE_OPTIONS='--experimental-vm-modules' jest"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@jest/globals": "^30.2.0",
|
|
40
|
+
"eslint": "^9.39.3",
|
|
41
|
+
"jest": "^30.2.0",
|
|
42
|
+
"neostandard": "^0.12.2"
|
|
43
|
+
}
|
|
44
|
+
}
|