cstyler 3.0.0 → 4.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/README.md +65 -23
- package/index.js +52 -188
- package/package.json +11 -2
- package/readme.txt +0 -23
package/README.md
CHANGED
|
@@ -1,31 +1,73 @@
|
|
|
1
|
-
# CSTYLER
|
|
2
|
-
|
|
1
|
+
# CSTYLER 🎨
|
|
2
|
+
**A lightweight, powerful console styler by kormoi.com**
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
`cstyler` is a zero-dependency Node.js toolkit designed to make your terminal output beautiful. It features an intuitive chainable API, support for HEX/RGB colors, and a unique nested inline styling system.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
---
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
## 🚀 Key Features
|
|
9
|
+
* **Auto-Detection:** Automatically strips styles if the terminal doesn't support them (perfect for logs).
|
|
10
|
+
* **Chainable API:** Mix styles easily using dot notation.
|
|
11
|
+
* **TrueColor Support:** Use HEX and RGB for millions of colors.
|
|
12
|
+
* **Smart Nesting:** Complex nested styling using tagged template literals.
|
|
13
|
+
* **No Overhead:** Built to be fast and lightweight.
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
>
|
|
15
|
+
---
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
IMPORT:
|
|
17
|
-
const cstyle = require("cstyle");
|
|
17
|
+
## 📦 Installation
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
```bash
|
|
20
|
+
npm install cstyler
|
|
21
|
+
```
|
|
22
|
+
## 🛠 Usage
|
|
23
|
+
### 1. Basic Styling (Chainable)
|
|
24
|
+
You can combine text styles and colors using simple dot notation.
|
|
25
|
+
JavaScript
|
|
26
|
+
```js
|
|
27
|
+
const cstyler = require("cstyler");
|
|
21
28
|
|
|
22
|
-
|
|
29
|
+
// Bold, Underline, and Yellow text
|
|
30
|
+
console.log(cstyler.bold.underline.yellow("Hello World!"));
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
// Darkened green text
|
|
33
|
+
console.log(cstyler.green.dark("Subtle green message"));
|
|
34
|
+
```
|
|
35
|
+
### 2. Custom Colors (HEX & RGB)
|
|
36
|
+
Go beyond the standard 16 colors with TrueColor support.
|
|
37
|
+
JavaScript
|
|
38
|
+
```js
|
|
39
|
+
// Foreground Colors
|
|
40
|
+
console.log(cstyler.hex('#FF5733')("Vibrant Orange"));
|
|
41
|
+
console.log(cstyler.rgb(100, 150, 200)("Custom Blue"));
|
|
42
|
+
|
|
43
|
+
// Background Colors
|
|
44
|
+
console.log(cstyler.bgHex('#333').white("White text on dark grey"));
|
|
45
|
+
```
|
|
46
|
+
### 3. Inline Nested Styling (Tagged Templates)
|
|
47
|
+
This is the most powerful way to style complex strings. Use {style text} syntax inside backticks.
|
|
48
|
+
JavaScript
|
|
49
|
+
```js
|
|
50
|
+
console.log(cstyler`
|
|
51
|
+
{bold.red Critical Error:} {italic.gray Connection failed.}
|
|
52
|
+
{bold.green Success! {italic.white kormoi.com is online.}}
|
|
53
|
+
{hex('#00dbde').bold Powerful custom colors work inside too!}
|
|
54
|
+
`);
|
|
55
|
+
```
|
|
56
|
+
🎨 Available Styles
|
|
57
|
+
| Category | Available Properties |
|
|
58
|
+
| :--- | :--- |
|
|
59
|
+
| **Formatting** | bold, italic, underline, dark |
|
|
60
|
+
| **Colors** | red, green, blue, yellow, purple, cyan, white, gray, magenta |
|
|
61
|
+
| **Backgrounds** | bgRed, bgGreen, bgBlue, bgYellow, bgPurple, bgGray |
|
|
62
|
+
| **Custom** | .hex(), .rgb(), .bgHex(), .bgRgb() |
|
|
63
|
+
|
|
64
|
+
> Note: You cannot use two foreground colors at once (e.g., red.blue). The last color in the chain will take priority.
|
|
65
|
+
|
|
66
|
+
## 🛡 Smart Terminal Detection
|
|
67
|
+
`cstyler` is smart. If you pipe your output to a file or run it in an environment that doesn't support ANSI colors, it will **silently return plain text.** Your logs will remain clean and readable without any "garbage" characters.
|
|
68
|
+
|
|
69
|
+
## 👨💻 Author
|
|
70
|
+
### MD NASIRUDDIN AHMED
|
|
71
|
+
Visit us at: kormoi.com
|
|
72
|
+
|
|
73
|
+
`Feel free to use and contribute! Regards from kormoi.com.`
|
package/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
class cstyler {
|
|
2
2
|
constructor() {
|
|
3
|
+
// SILENT CHECK: No printing, just querying the environment
|
|
4
|
+
this.enabled = process.stdout.isTTY &&
|
|
5
|
+
(process.stdout.getColorDepth ? process.stdout.getColorDepth() > 1 : true);
|
|
6
|
+
|
|
3
7
|
this.styleMap = {
|
|
4
8
|
// Text styles
|
|
5
9
|
bold: ['\x1b[1m', '\x1b[22m'],
|
|
@@ -31,244 +35,104 @@ class cstyler {
|
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
createStyler(styles) {
|
|
34
|
-
const styler = (text) =>
|
|
35
|
-
|
|
38
|
+
const styler = (text) => {
|
|
39
|
+
// Return plain text if terminal doesn't support styling
|
|
40
|
+
if (!this.enabled) return text;
|
|
41
|
+
return styles.reduce((str, { open, close }) => open + str + close, text);
|
|
42
|
+
};
|
|
36
43
|
|
|
37
|
-
const addStyle = (open, close) =>
|
|
38
|
-
this.createStyler([...styles, { open, close }]);
|
|
44
|
+
const addStyle = (open, close) => this.createStyler([...styles, { open, close }]);
|
|
39
45
|
|
|
46
|
+
// Map standard styles
|
|
40
47
|
for (const [name, [open, close]] of Object.entries(this.styleMap)) {
|
|
41
48
|
Object.defineProperty(styler, name, {
|
|
42
|
-
get: () => addStyle(open, close),
|
|
49
|
+
get: () => this.enabled ? addStyle(open, close) : styler,
|
|
43
50
|
});
|
|
44
51
|
}
|
|
45
52
|
|
|
46
|
-
// RGB
|
|
53
|
+
// RGB Support
|
|
47
54
|
styler.rgb = (r, g, b) => {
|
|
48
|
-
if (!
|
|
49
|
-
console.error('Invalid RGB value. Falling back to white.');
|
|
50
|
-
return addStyle('\x1b[37m', '\x1b[39m');
|
|
51
|
-
}
|
|
55
|
+
if (!this.enabled) return styler;
|
|
52
56
|
return addStyle(`\x1b[38;2;${r};${g};${b}m`, '\x1b[39m');
|
|
53
57
|
};
|
|
54
58
|
|
|
55
|
-
// Hex
|
|
59
|
+
// Hex Support
|
|
56
60
|
styler.hex = (hex) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const b = parseInt(hex.slice(4, 6), 16);
|
|
63
|
-
return styler.rgb(r, g, b);
|
|
64
|
-
} catch {
|
|
65
|
-
console.error('Invalid hex color. Falling back to white.');
|
|
66
|
-
return addStyle('\x1b[37m', '\x1b[39m');
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// HSL to RGB conversion helper
|
|
71
|
-
function hslToRgb(h, s, l) {
|
|
72
|
-
s /= 100;
|
|
73
|
-
l /= 100;
|
|
74
|
-
const k = (n) => (n + h / 30) % 12;
|
|
75
|
-
const a = s * Math.min(l, 1 - l);
|
|
76
|
-
const f = (n) =>
|
|
77
|
-
l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
78
|
-
return [Math.round(255 * f(0)), Math.round(255 * f(8)), Math.round(255 * f(4))];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
styler.hsl = (h, s, l) => {
|
|
82
|
-
if (
|
|
83
|
-
typeof h !== 'number' ||
|
|
84
|
-
h < 0 ||
|
|
85
|
-
h > 360 ||
|
|
86
|
-
typeof s !== 'number' ||
|
|
87
|
-
s < 0 ||
|
|
88
|
-
s > 100 ||
|
|
89
|
-
typeof l !== 'number' ||
|
|
90
|
-
l < 0 ||
|
|
91
|
-
l > 100
|
|
92
|
-
) {
|
|
93
|
-
console.error('Invalid HSL value. Falling back to white.');
|
|
94
|
-
return addStyle('\x1b[37m', '\x1b[39m');
|
|
95
|
-
}
|
|
96
|
-
const [r, g, b] = hslToRgb(h, s, l);
|
|
61
|
+
if (!this.enabled) return styler;
|
|
62
|
+
const cleanHex = hex.replace(/^#/, '');
|
|
63
|
+
const r = parseInt(cleanHex.slice(0, 2), 16);
|
|
64
|
+
const g = parseInt(cleanHex.slice(2, 4), 16);
|
|
65
|
+
const b = parseInt(cleanHex.slice(4, 6), 16);
|
|
97
66
|
return styler.rgb(r, g, b);
|
|
98
67
|
};
|
|
99
68
|
|
|
100
|
-
//
|
|
69
|
+
// Tagged Template Parser
|
|
101
70
|
styler.tag = (strings, ...values) => {
|
|
102
|
-
|
|
103
|
-
for (let i = 0; i < strings.length; i++) {
|
|
104
|
-
fullText += strings[i];
|
|
105
|
-
if (i < values.length) fullText += values[i];
|
|
106
|
-
}
|
|
71
|
+
const fullText = strings.reduce((acc, str, i) => acc + str + (values[i] || ''), '');
|
|
107
72
|
return this.parseInlineStyles(fullText);
|
|
108
73
|
};
|
|
109
74
|
|
|
110
|
-
// Helper: parse parameters string to array for hex, rgb, hsl
|
|
111
|
-
this.parseParameters = (paramStr) => {
|
|
112
|
-
// Remove spaces outside quotes, split by commas respecting quotes
|
|
113
|
-
const params = [];
|
|
114
|
-
let current = '';
|
|
115
|
-
let inQuotes = false;
|
|
116
|
-
for (let c of paramStr.trim()) {
|
|
117
|
-
if (c === "'" || c === '"') {
|
|
118
|
-
inQuotes = !inQuotes;
|
|
119
|
-
current += c;
|
|
120
|
-
} else if (c === ',' && !inQuotes) {
|
|
121
|
-
if (current.length) params.push(current.trim());
|
|
122
|
-
current = '';
|
|
123
|
-
} else {
|
|
124
|
-
current += c;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
if (current.length) params.push(current.trim());
|
|
128
|
-
// Remove quotes from strings
|
|
129
|
-
return params.map((p) => p.replace(/^['"]|['"]$/g, ''));
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
// Recursive parser for nested inline styles with support for parameterized styles
|
|
133
75
|
this.parseInlineStyles = (text) => {
|
|
134
|
-
const parse = (str
|
|
135
|
-
let result = '';
|
|
136
|
-
let i = start;
|
|
137
|
-
|
|
76
|
+
const parse = (str) => {
|
|
77
|
+
let result = '', i = 0;
|
|
138
78
|
while (i < str.length) {
|
|
139
79
|
if (str[i] === '{') {
|
|
140
|
-
|
|
141
|
-
let level = 1;
|
|
142
|
-
let j = i + 1;
|
|
80
|
+
let level = 1, j = i + 1;
|
|
143
81
|
while (j < str.length && level > 0) {
|
|
144
82
|
if (str[j] === '{') level++;
|
|
145
83
|
else if (str[j] === '}') level--;
|
|
146
84
|
j++;
|
|
147
85
|
}
|
|
148
|
-
if (level !== 0) {
|
|
149
|
-
// Unmatched brace, treat literally
|
|
150
|
-
result += str.slice(i);
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
86
|
+
if (level !== 0) { result += str.slice(i); break; }
|
|
153
87
|
|
|
154
|
-
// Extract content between braces
|
|
155
88
|
const content = str.slice(i + 1, j - 1);
|
|
156
|
-
|
|
157
|
-
// Find first space to separate styles from text
|
|
158
89
|
const spaceIdx = content.indexOf(' ');
|
|
159
90
|
|
|
160
91
|
if (spaceIdx === -1) {
|
|
161
|
-
// No space, treat as literal text with braces
|
|
162
92
|
result += '{' + content + '}';
|
|
163
93
|
} else {
|
|
164
94
|
const styleStr = content.slice(0, spaceIdx);
|
|
165
95
|
const innerText = content.slice(spaceIdx + 1);
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
else if (
|
|
180
|
-
|
|
96
|
+
const parsedInner = parse(innerText);
|
|
97
|
+
|
|
98
|
+
if (!this.enabled) {
|
|
99
|
+
result += parsedInner;
|
|
100
|
+
} else {
|
|
101
|
+
// regex: match style name OR styleName(params)
|
|
102
|
+
const styleParts = styleStr.match(/(\w+(\([^)]*\))?)/g) || [];
|
|
103
|
+
let styledText = parsedInner;
|
|
104
|
+
|
|
105
|
+
for (let part of styleParts.reverse()) {
|
|
106
|
+
if (part.startsWith('hex')) {
|
|
107
|
+
const val = part.match(/\(([^)]+)\)/)?.[1].replace(/['"]/g, '');
|
|
108
|
+
styledText = styler.hex(val)(styledText);
|
|
109
|
+
} else if (part.startsWith('rgb')) {
|
|
110
|
+
const vals = part.match(/\(([^)]+)\)/)?.[1].split(',').map(Number);
|
|
111
|
+
styledText = styler.rgb(...vals)(styledText);
|
|
112
|
+
} else if (this.styleMap[part]) {
|
|
113
|
+
const [open, close] = this.styleMap[part];
|
|
114
|
+
styledText = open + styledText + close;
|
|
115
|
+
}
|
|
181
116
|
}
|
|
117
|
+
result += styledText;
|
|
182
118
|
}
|
|
183
|
-
if (currentStyle) styleParts.push(currentStyle);
|
|
184
|
-
|
|
185
|
-
// Parse inner text recursively (to support nested styles)
|
|
186
|
-
const parsedInner = parse(innerText, 0);
|
|
187
|
-
|
|
188
|
-
// Apply styles in order (left to right)
|
|
189
|
-
let styledText = parsedInner;
|
|
190
|
-
|
|
191
|
-
for (let style of styleParts.reverse()) {
|
|
192
|
-
// Check if style has parameters (like hex(...))
|
|
193
|
-
let name = style;
|
|
194
|
-
let params = null;
|
|
195
|
-
|
|
196
|
-
const paramStart = style.indexOf('(');
|
|
197
|
-
if (paramStart !== -1 && style.endsWith(')')) {
|
|
198
|
-
name = style.slice(0, paramStart);
|
|
199
|
-
const paramStr = style.slice(paramStart + 1, -1);
|
|
200
|
-
params = this.parseParameters(paramStr);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Handle styles
|
|
204
|
-
if (name === 'hex' && params && params.length === 1) {
|
|
205
|
-
styledText = this.styleMap[name]
|
|
206
|
-
? this.applyStyle(styledText, this.styleMap[name])
|
|
207
|
-
: styler.hex(params[0])(styledText);
|
|
208
|
-
} else if (
|
|
209
|
-
name === 'rgb' &&
|
|
210
|
-
params &&
|
|
211
|
-
params.length === 3 &&
|
|
212
|
-
params.every((p) => !isNaN(p))
|
|
213
|
-
) {
|
|
214
|
-
styledText = styler.rgb(
|
|
215
|
-
parseInt(params[0]),
|
|
216
|
-
parseInt(params[1]),
|
|
217
|
-
parseInt(params[2])
|
|
218
|
-
)(styledText);
|
|
219
|
-
} else if (
|
|
220
|
-
name === 'hsl' &&
|
|
221
|
-
params &&
|
|
222
|
-
params.length === 3 &&
|
|
223
|
-
params.every((p) => !isNaN(p))
|
|
224
|
-
) {
|
|
225
|
-
styledText = styler.hsl(
|
|
226
|
-
parseFloat(params[0]),
|
|
227
|
-
parseFloat(params[1]),
|
|
228
|
-
parseFloat(params[2])
|
|
229
|
-
)(styledText);
|
|
230
|
-
} else if (this.styleMap[name]) {
|
|
231
|
-
const [open, close] = this.styleMap[name];
|
|
232
|
-
styledText = open + styledText + close;
|
|
233
|
-
} else {
|
|
234
|
-
console.warn(`Unknown style: ${style}`);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
result += styledText;
|
|
239
119
|
}
|
|
240
|
-
|
|
241
120
|
i = j;
|
|
242
121
|
} else {
|
|
243
|
-
result += str[i];
|
|
244
|
-
i++;
|
|
122
|
+
result += str[i++];
|
|
245
123
|
}
|
|
246
124
|
}
|
|
247
|
-
|
|
248
125
|
return result;
|
|
249
126
|
};
|
|
250
127
|
return parse(text);
|
|
251
128
|
};
|
|
252
129
|
|
|
253
|
-
// Helper to apply raw style array (for internal use)
|
|
254
|
-
this.applyStyle = (text, [open, close]) => open + text + close;
|
|
255
|
-
|
|
256
130
|
return new Proxy(styler, {
|
|
257
|
-
apply: (target, thisArg, args) =>
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return styler.tag(...args);
|
|
261
|
-
}
|
|
262
|
-
// Direct call with string
|
|
263
|
-
return styler(...args);
|
|
264
|
-
},
|
|
265
|
-
get: (target, prop) => {
|
|
266
|
-
if (prop in styler) return styler[prop];
|
|
267
|
-
console.warn(`Invalid style: ${String(prop)}`);
|
|
268
|
-
return styler;
|
|
269
|
-
},
|
|
131
|
+
apply: (target, thisArg, args) =>
|
|
132
|
+
(Array.isArray(args[0]) && 'raw' in args[0]) ? styler.tag(...args) : styler(...args),
|
|
133
|
+
get: (target, prop) => (prop in styler) ? styler[prop] : styler,
|
|
270
134
|
});
|
|
271
135
|
}
|
|
272
136
|
}
|
|
273
137
|
|
|
274
|
-
module.exports = new cstyler();
|
|
138
|
+
module.exports = new cstyler();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cstyler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Chainable terminal text styling tool (bold, colors, etc.)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -10,7 +10,16 @@
|
|
|
10
10
|
"chainable",
|
|
11
11
|
"bold",
|
|
12
12
|
"style",
|
|
13
|
-
"styler"
|
|
13
|
+
"styler",
|
|
14
|
+
"ansi",
|
|
15
|
+
"colors",
|
|
16
|
+
"terminal",
|
|
17
|
+
"styling",
|
|
18
|
+
"cli",
|
|
19
|
+
"template",
|
|
20
|
+
"rgb",
|
|
21
|
+
"hex",
|
|
22
|
+
"hsl"
|
|
14
23
|
],
|
|
15
24
|
"author": "MD Nasiruddin Ahmed",
|
|
16
25
|
"license": "ISC",
|
package/readme.txt
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# cstyler
|
|
2
|
-
Hello World!
|
|
3
|
-
|
|
4
|
-
You can style with color and style on the console text with this package
|
|
5
|
-
|
|
6
|
-
This cstyler kit is fully free to use. You can colorize your console log useing this kit. You can use dot notation to add more style like 'bold, underline, italic, dark(for color), bg for background'. You have all red, green, blue, yellow, cyan, purpal, colors on both text color and background color.
|
|
7
|
-
|
|
8
|
-
You can not use two color names e.g. 'red.blue'.
|
|
9
|
-
How to use:
|
|
10
|
-
INSTALLING:
|
|
11
|
-
|
|
12
|
-
> npm install cstyler
|
|
13
|
-
>
|
|
14
|
-
|
|
15
|
-
Then it will install packages.
|
|
16
|
-
IMPORT:
|
|
17
|
-
const cstyle = require("cstyle");
|
|
18
|
-
|
|
19
|
-
USE:
|
|
20
|
-
console.log(cstyle.bold.underline.italic.dark.yellow("Here goes your text"));
|
|
21
|
-
|
|
22
|
-
Feel free to use.
|
|
23
|
-
Regards from kormoi.com
|