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.
Files changed (2) hide show
  1. package/package.json +3 -2
  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.2",
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
  }
@@ -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 art horse head + GBOS logo combined
27
- const ASCII_LOGO = `
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
- // Simpler horse ASCII for smaller displays
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 catimg or ASCII fallback
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
- if (hasCatimg() && fs.existsSync(logoPath)) {
67
- try {
68
- // Use catimg with width constraint for terminal
69
- const result = spawnSync('catimg', ['-w', '40', logoPath], {
70
- encoding: 'utf8',
71
- stdio: ['ignore', 'pipe', 'ignore'],
72
- });
73
- if (result.stdout) {
74
- console.log(result.stdout);
75
- // Print GBOS text next to it
76
- console.log(`${colors.purple4}${colors.bold} ██████╗ ██████╗ ██████╗ ███████╗`);
77
- console.log(`${colors.purple4} ██╔════╝ ██╔══██╗██╔═══██╗██╔════╝`);
78
- console.log(`${colors.purple5} ██║ ███╗██████╔╝██║ ██║███████╗`);
79
- console.log(`${colors.purple5} ██║ ██║██╔══██╗██║ ██║╚════██║`);
80
- console.log(`${colors.purple6} ╚██████╔╝██████╔╝╚██████╔╝███████║`);
81
- console.log(`${colors.purple6} ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝${colors.reset}`);
82
- return;
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
- } catch (e) {
85
- // Fall through to ASCII
143
+ console.log('');
144
+ return;
86
145
  }
87
146
  }
88
147
 
89
- // ASCII fallback with horse icon
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
  };