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.
Files changed (4) hide show
  1. package/README.md +65 -23
  2. package/index.js +52 -188
  3. package/package.json +11 -2
  4. package/readme.txt +0 -23
package/README.md CHANGED
@@ -1,31 +1,73 @@
1
- # CSTYLER
2
- Hello World!
1
+ # CSTYLER 🎨
2
+ **A lightweight, powerful console styler by kormoi.com**
3
3
 
4
- Style your console log with your cstyler package by kormoi.com
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
- 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.
6
+ ---
7
7
 
8
- You can not use two color names e.g. 'red.blue'.
9
- How to use:
10
- INSTALLING:
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
- > npm install cstyler
13
- >
15
+ ---
14
16
 
15
- Then it will install packages.
16
- IMPORT:
17
- const cstyle = require("cstyle");
17
+ ## 📦 Installation
18
18
 
19
- USE:
20
- console.log(cstyle.bold.underline.italic.dark.yellow("Here goes your text"));
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
- You can add these colors by name: red, green, blue, yellow, purpal, grey. You can darken them with a .dark property accessor. You can add rbg, hex, bgrgb and bghex color using .hex('#123456'), and rgb(100,100,100) and same for bg hex and bg rgb.
29
+ // Bold, Underline, and Yellow text
30
+ console.log(cstyler.bold.underline.yellow("Hello World!"));
23
31
 
24
- Feel free to use.
25
- <<<<<<< HEAD
26
- Regards from kormoi.com
27
- =======
28
- Regards from
29
- kormoi.com
30
- MD NASIRUDDIN AHMED
31
- >>>>>>> 7cb483c (Second commit)
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
- styles.reduce((str, { open, close }) => open + str + close, text);
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 foreground color
53
+ // RGB Support
47
54
  styler.rgb = (r, g, b) => {
48
- if (![r, g, b].every((n) => Number.isInteger(n) && n >= 0 && n <= 255)) {
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 foreground color
59
+ // Hex Support
56
60
  styler.hex = (hex) => {
57
- try {
58
- if (typeof hex !== 'string') throw new Error();
59
- hex = hex.replace(/^#/, '').slice(0, 6);
60
- const r = parseInt(hex.slice(0, 2), 16);
61
- const g = parseInt(hex.slice(2, 4), 16);
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
- // Parse tagged template literals with inline nested styles
69
+ // Tagged Template Parser
101
70
  styler.tag = (strings, ...values) => {
102
- let fullText = '';
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, start = 0) => {
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
- // Find matching closing brace for nested block
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
- // Parse styles separated by '.'
168
- // But styles may have params, like hex('#ff00ff'), rgb(255,0,0)
169
- const styleParts = [];
170
-
171
- let currentStyle = '';
172
- let parenLevel = 0;
173
- for (let ch of styleStr) {
174
- if (ch === '.' && parenLevel === 0) {
175
- if (currentStyle) styleParts.push(currentStyle);
176
- currentStyle = '';
177
- } else {
178
- if (ch === '(') parenLevel++;
179
- else if (ch === ')') parenLevel--;
180
- currentStyle += ch;
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
- // Tagged template literal usage
259
- if (Array.isArray(args[0]) && 'raw' in args[0]) {
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.0.0",
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