gbos 1.1.2 → 1.1.3
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/package.json +3 -2
- package/src/lib/display.js +95 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gbos",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "GBOS - Command line interface for GBOS services",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"images/**/*"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"commander": "^12.1.0"
|
|
41
|
+
"commander": "^12.1.0",
|
|
42
|
+
"pngjs": "^7.0.0"
|
|
42
43
|
}
|
|
43
44
|
}
|
package/src/lib/display.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { execSync, spawnSync } = require('child_process');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
|
+
const { PNG } = require('pngjs');
|
|
4
5
|
|
|
5
6
|
// ANSI color codes - Dark Purple Theme
|
|
6
7
|
const colors = {
|
|
@@ -23,21 +24,70 @@ const colors = {
|
|
|
23
24
|
yellow: '\x1b[33m',
|
|
24
25
|
};
|
|
25
26
|
|
|
26
|
-
// ASCII
|
|
27
|
-
const
|
|
28
|
-
${colors.purple2}${colors.bold} ╱▔╲
|
|
29
|
-
${colors.purple3} ╱▔ ╲▁▁
|
|
30
|
-
${colors.purple3} ▕ ╲╲ ${colors.purple4}██████╗ ██████╗ ██████╗ ███████╗
|
|
31
|
-
${colors.purple4} ▕ ● ╲╲ ${colors.purple4}██╔════╝ ██╔══██╗██╔═══██╗██╔════╝
|
|
32
|
-
${colors.purple4} ╲ ╱╱ ${colors.purple5}██║ ███╗██████╔╝██║ ██║███████╗
|
|
33
|
-
${colors.purple5} ╲╲ ╱╱ ${colors.purple5}██║ ██║██╔══██╗██║ ██║╚════██║
|
|
34
|
-
${colors.purple5} ▁▁▁▁╱ ╲▁▁╱ ${colors.purple6}╚██████╔╝██████╔╝╚██████╔╝███████║
|
|
35
|
-
${colors.purple6} ╱ ${colors.purple6} ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
36
|
-
${colors.purple6} ╱ ╲
|
|
37
|
-
${colors.purple7} ▕ ▏
|
|
38
|
-
${colors.reset}`;
|
|
27
|
+
// ASCII characters from dark to light
|
|
28
|
+
const ASCII_CHARS = ' .:-=+*#%@';
|
|
39
29
|
|
|
40
|
-
//
|
|
30
|
+
// Convert image to ASCII art
|
|
31
|
+
function imageToAscii(imagePath, width = 30) {
|
|
32
|
+
try {
|
|
33
|
+
const data = fs.readFileSync(imagePath);
|
|
34
|
+
const png = PNG.sync.read(data);
|
|
35
|
+
|
|
36
|
+
const aspectRatio = 0.5; // Terminal characters are taller than wide
|
|
37
|
+
const height = Math.floor((png.height / png.width) * width * aspectRatio);
|
|
38
|
+
|
|
39
|
+
const cellWidth = png.width / width;
|
|
40
|
+
const cellHeight = png.height / height;
|
|
41
|
+
|
|
42
|
+
let ascii = '';
|
|
43
|
+
|
|
44
|
+
for (let y = 0; y < height; y++) {
|
|
45
|
+
let row = '';
|
|
46
|
+
for (let x = 0; x < width; x++) {
|
|
47
|
+
// Sample the center of each cell
|
|
48
|
+
const sampleX = Math.floor(x * cellWidth + cellWidth / 2);
|
|
49
|
+
const sampleY = Math.floor(y * cellHeight + cellHeight / 2);
|
|
50
|
+
const idx = (png.width * sampleY + sampleX) << 2;
|
|
51
|
+
|
|
52
|
+
const r = png.data[idx];
|
|
53
|
+
const g = png.data[idx + 1];
|
|
54
|
+
const b = png.data[idx + 2];
|
|
55
|
+
const a = png.data[idx + 3];
|
|
56
|
+
|
|
57
|
+
// If transparent, use space
|
|
58
|
+
if (a < 128) {
|
|
59
|
+
row += ' ';
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Calculate brightness (0-255)
|
|
64
|
+
const brightness = (r + g + b) / 3;
|
|
65
|
+
// Map to ASCII character (inverted - darker pixels = denser characters)
|
|
66
|
+
const charIndex = Math.floor((1 - brightness / 255) * (ASCII_CHARS.length - 1));
|
|
67
|
+
row += ASCII_CHARS[charIndex];
|
|
68
|
+
}
|
|
69
|
+
ascii += row + '\n';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return ascii;
|
|
73
|
+
} catch (e) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Color the ASCII art with purple gradient based on position
|
|
79
|
+
function colorAsciiArt(ascii, startColor = colors.purple2, endColor = colors.purple6) {
|
|
80
|
+
const lines = ascii.split('\n').filter(line => line.trim());
|
|
81
|
+
const purpleGradient = [colors.purple2, colors.purple3, colors.purple4, colors.purple5, colors.purple6];
|
|
82
|
+
|
|
83
|
+
return lines.map((line, i) => {
|
|
84
|
+
const colorIndex = Math.floor((i / lines.length) * purpleGradient.length);
|
|
85
|
+
const color = purpleGradient[Math.min(colorIndex, purpleGradient.length - 1)];
|
|
86
|
+
return color + line + colors.reset;
|
|
87
|
+
}).join('\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ASCII art horse head + GBOS logo combined (fallback)
|
|
41
91
|
const ASCII_LOGO_SIMPLE = `
|
|
42
92
|
${colors.purple3}${colors.bold} ▄▀▀▀▄▄
|
|
43
93
|
${colors.purple3} ▄▀ ▀▄ ${colors.purple4}██████╗ ██████╗ ██████╗ ███████╗
|
|
@@ -49,6 +99,14 @@ ${colors.purple6} █ █ ${colors.purple6} ╚═════
|
|
|
49
99
|
${colors.purple6} █ █
|
|
50
100
|
${colors.reset}`;
|
|
51
101
|
|
|
102
|
+
// GBOS text only
|
|
103
|
+
const GBOS_TEXT = `${colors.purple4}${colors.bold}██████╗ ██████╗ ██████╗ ███████╗
|
|
104
|
+
${colors.purple4}██╔════╝ ██╔══██╗██╔═══██╗██╔════╝
|
|
105
|
+
${colors.purple5}██║ ███╗██████╔╝██║ ██║███████╗
|
|
106
|
+
${colors.purple5}██║ ██║██╔══██╗██║ ██║╚════██║
|
|
107
|
+
${colors.purple6}╚██████╔╝██████╔╝╚██████╔╝███████║
|
|
108
|
+
${colors.purple6} ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝${colors.reset}`;
|
|
109
|
+
|
|
52
110
|
// Check if catimg is available
|
|
53
111
|
function hasCatimg() {
|
|
54
112
|
try {
|
|
@@ -59,34 +117,35 @@ function hasCatimg() {
|
|
|
59
117
|
}
|
|
60
118
|
}
|
|
61
119
|
|
|
62
|
-
// Display logo using
|
|
120
|
+
// Display logo using image-to-ascii or ASCII fallback
|
|
63
121
|
function displayLogo() {
|
|
64
122
|
const logoPath = path.join(__dirname, '../../images/logo.png');
|
|
65
123
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
124
|
+
// Try to convert image to ASCII
|
|
125
|
+
if (fs.existsSync(logoPath)) {
|
|
126
|
+
const ascii = imageToAscii(logoPath, 25);
|
|
127
|
+
if (ascii) {
|
|
128
|
+
// Color the ASCII art
|
|
129
|
+
const coloredAscii = colorAsciiArt(ascii);
|
|
130
|
+
const asciiLines = coloredAscii.split('\n');
|
|
131
|
+
const gbosLines = GBOS_TEXT.split('\n');
|
|
132
|
+
|
|
133
|
+
// Combine horse ASCII and GBOS text side by side
|
|
134
|
+
console.log('');
|
|
135
|
+
const maxLines = Math.max(asciiLines.length, gbosLines.length);
|
|
136
|
+
for (let i = 0; i < maxLines; i++) {
|
|
137
|
+
const asciiLine = asciiLines[i] || '';
|
|
138
|
+
const gbosLine = gbosLines[i - Math.floor((maxLines - gbosLines.length) / 2)] || '';
|
|
139
|
+
// Pad ASCII line to consistent width
|
|
140
|
+
const paddedAscii = asciiLine.padEnd(35);
|
|
141
|
+
console.log(` ${paddedAscii} ${gbosLine}`);
|
|
83
142
|
}
|
|
84
|
-
|
|
85
|
-
|
|
143
|
+
console.log('');
|
|
144
|
+
return;
|
|
86
145
|
}
|
|
87
146
|
}
|
|
88
147
|
|
|
89
|
-
//
|
|
148
|
+
// Fallback to manual ASCII horse
|
|
90
149
|
console.log(ASCII_LOGO_SIMPLE);
|
|
91
150
|
}
|
|
92
151
|
|
|
@@ -220,4 +279,5 @@ module.exports = {
|
|
|
220
279
|
displayConnectSuccess,
|
|
221
280
|
displayMessageBox,
|
|
222
281
|
hasCatimg,
|
|
282
|
+
imageToAscii,
|
|
223
283
|
};
|