@blockrun/franklin 3.2.1 → 3.2.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/dist/banner.js +79 -67
- package/package.json +1 -1
package/dist/banner.js
CHANGED
|
@@ -2,38 +2,47 @@ import chalk from 'chalk';
|
|
|
2
2
|
// ─── Ben Franklin portrait ─────────────────────────────────────────────────
|
|
3
3
|
//
|
|
4
4
|
// Generated once, at build time, from the Joseph Duplessis 1785 oil painting
|
|
5
|
-
// of Benjamin Franklin (same source
|
|
6
|
-
// Public domain image from Wikimedia Commons:
|
|
5
|
+
// of Benjamin Franklin (same source used for the engraving on the US $100
|
|
6
|
+
// bill). Public domain image from Wikimedia Commons:
|
|
7
7
|
// https://commons.wikimedia.org/wiki/File:BenFranklinDuplessis.jpg
|
|
8
8
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
9
|
+
// Pipeline:
|
|
10
|
+
// 1. Crop the 2403×2971 original to a 1400×1400 square centred on the face
|
|
11
|
+
// (sips --cropToHeightWidth 1400 1400 --cropOffset 400 500)
|
|
12
|
+
// 2. Convert with ascii-image-converter in braille mode:
|
|
13
|
+
// ascii-image-converter ben-face.jpg --dimensions 34,16 --braille \
|
|
14
|
+
// --threshold 110
|
|
11
15
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
16
|
+
// Braille characters (U+2800..U+28FF) encode 2×4 dot matrices per cell, so
|
|
17
|
+
// a 34×16 braille output gives 68×64 = 4,352 effective "pixels" — 2.7× the
|
|
18
|
+
// resolution of chafa half-block mode at the same visible size. For a face,
|
|
19
|
+
// which is all about silhouette + key features, this is a massive win.
|
|
15
20
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
21
|
+
// The output is pure Unicode — no ANSI escape codes, no color tinting baked
|
|
22
|
+
// in — which means it's trivial to wrap in chalk.hex() at render time for
|
|
23
|
+
// brand tinting, and it ships as a clean readable TS array.
|
|
19
24
|
const BEN_PORTRAIT_ROWS = [
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
25
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣴⣶⣶⣦⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
26
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
27
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
28
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
29
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⠁⣀⠀⠉⣿⣿⣿⠋⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
30
|
+
'⠀⠀⠀⠀⠀⠀⠀⢀⠀⢠⣿⣿⣿⣾⣤⣴⣴⣿⣿⣷⠀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
31
|
+
'⠀⠀⠀⢠⡄⠀⠀⠁⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⢾⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
32
|
+
'⠀⠀⠀⠸⡔⠂⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣛⣛⠛⠁⠈⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
33
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⢿⣿⠿⢷⠄⠀⠙⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
34
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
35
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
36
|
+
'⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⡿⣿⡿⣿⣏⠛⠛⠙⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
37
|
+
'⠀⠀⡴⠺⠖⢒⣂⢄⡀⣹⣿⣿⣿⣶⣙⠂⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
38
|
+
'⣶⣤⣄⡀⠈⠻⠿⡙⠗⠸⡻⣿⡻⣿⣿⣷⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
39
|
+
'⣿⡟⠻⣿⣦⡀⠀⢁⡆⠀⠹⢿⣿⣮⣟⠿⣿⠏⠀⠀⣀⣴⣶⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
40
|
+
'⣿⣷⣄⠈⠿⣷⡀⣾⣿⡀⢦⢸⣿⡹⣿⣿⡆⣤⡐⠻⡻⣿⣿⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀',
|
|
30
41
|
];
|
|
31
42
|
// ─── FRANKLIN text banner (gold → emerald gradient) ────────────────────────
|
|
32
43
|
//
|
|
33
|
-
// Kept from v3.1.0.
|
|
34
|
-
//
|
|
35
|
-
// giving the smooth vertical gradient that's been Franklin's banner since
|
|
36
|
-
// v3.1.0.
|
|
44
|
+
// Kept from v3.1.0. 6 block-letter rows, each tinted with an interpolated
|
|
45
|
+
// colour between GOLD_START and EMERALD_END for a smooth vertical gradient.
|
|
37
46
|
const FRANKLIN_ART = [
|
|
38
47
|
' ███████╗██████╗ █████╗ ███╗ ██╗██╗ ██╗██╗ ██╗███╗ ██╗',
|
|
39
48
|
' ██╔════╝██╔══██╗██╔══██╗████╗ ██║██║ ██╔╝██║ ██║████╗ ██║',
|
|
@@ -63,23 +72,19 @@ function interpolateHex(start, end, t) {
|
|
|
63
72
|
}
|
|
64
73
|
// ─── Banner layout ─────────────────────────────────────────────────────────
|
|
65
74
|
// Minimum terminal width to show the side-by-side portrait + text layout.
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
const MIN_WIDTH_FOR_PORTRAIT =
|
|
75
|
+
// Portrait: 34 cols braille, FRANKLIN text: ~65 cols, gap: 3 cols,
|
|
76
|
+
// total: ~102 cols. Add a 3-col margin of safety → 105.
|
|
77
|
+
const MIN_WIDTH_FOR_PORTRAIT = 105;
|
|
69
78
|
/**
|
|
70
|
-
* Pad a line to an exact visual width
|
|
71
|
-
*
|
|
79
|
+
* Pad a line to an exact visual width. Braille characters have no ANSI
|
|
80
|
+
* escape codes and are all 1 cell wide, so this is a straightforward
|
|
81
|
+
* codepoint count.
|
|
72
82
|
*/
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
// eslint-disable-next-line no-control-regex
|
|
76
|
-
const visible = s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
77
|
-
// Unicode block characters are width 1 (they're half-blocks, not double-width)
|
|
78
|
-
const current = [...visible].length;
|
|
83
|
+
function padBraillePortrait(s, targetWidth) {
|
|
84
|
+
const current = [...s].length;
|
|
79
85
|
if (current >= targetWidth)
|
|
80
86
|
return s;
|
|
81
|
-
|
|
82
|
-
return s + '\x1b[0m' + ' '.repeat(targetWidth - current);
|
|
87
|
+
return s + ' '.repeat(targetWidth - current);
|
|
83
88
|
}
|
|
84
89
|
export function printBanner(version) {
|
|
85
90
|
const termWidth = process.stdout.columns ?? 80;
|
|
@@ -92,36 +97,42 @@ export function printBanner(version) {
|
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
/**
|
|
95
|
-
* Full layout: Ben Franklin portrait on the left, FRANKLIN
|
|
96
|
-
* right. Portrait is
|
|
97
|
-
*
|
|
98
|
-
*
|
|
100
|
+
* Full layout: Ben Franklin braille portrait on the left, FRANKLIN gradient
|
|
101
|
+
* text on the right. Portrait is 16 rows × 34 cols, text is 6 rows + 1-row
|
|
102
|
+
* tagline. Text starts at portrait row 5 so the FRANKLIN block aligns with
|
|
103
|
+
* Ben's face region (head at rows 1-4, face at rows 5-10, shoulders 11-16),
|
|
104
|
+
* giving the classic "portrait and nameplate" composition.
|
|
99
105
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
106
|
+
* row 1 ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣴⣶⣶⣦⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
107
|
+
* row 2 ⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀
|
|
108
|
+
* row 3 ⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀
|
|
109
|
+
* row 4 ⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀
|
|
110
|
+
* row 5 ⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⠁... ███████╗██████╗ █████╗ ...
|
|
111
|
+
* row 6 ⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣾... ██╔════╝██╔══██╗██╔══██╗...
|
|
112
|
+
* row 7 ⠀⠀⠀⢠⡄⠀⠀⠀⢀⣾⣿... █████╗ ██████╔╝███████║...
|
|
113
|
+
* row 8 ⠀⠀⠀⠸⡔⠂⠀⠀⠘⣿⣿... ██╔══╝ ██╔══██╗██╔══██║...
|
|
114
|
+
* row 9 ⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿... ██║ ██║ ██║██║ ██║...
|
|
115
|
+
* row 10 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿... ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝...
|
|
116
|
+
* row 11 ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿... blockrun.ai · The AI agent with a wallet · vX
|
|
117
|
+
* row 12 ⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿...
|
|
118
|
+
* row 13-16: neck, collar, body
|
|
113
119
|
*/
|
|
114
120
|
function printSideBySide(version) {
|
|
115
|
-
const TEXT_TOP_OFFSET =
|
|
116
|
-
const PORTRAIT_WIDTH =
|
|
117
|
-
const GAP = ' ';
|
|
121
|
+
const TEXT_TOP_OFFSET = 4; // text block starts at portrait row 5 (0-indexed row 4)
|
|
122
|
+
const PORTRAIT_WIDTH = 35; // 34 cols braille + 1 trailing space
|
|
123
|
+
const GAP = ' ';
|
|
118
124
|
const portraitRows = BEN_PORTRAIT_ROWS;
|
|
119
125
|
const textRows = FRANKLIN_ART.length;
|
|
120
126
|
const totalRows = Math.max(portraitRows.length, TEXT_TOP_OFFSET + textRows + 2);
|
|
127
|
+
// Tint the braille portrait in dim white for a "pencil portrait" feel.
|
|
128
|
+
// Braille chars carry no colour on their own — chalk wraps them in an
|
|
129
|
+
// ANSI colour sequence at render time.
|
|
130
|
+
const portraitTint = chalk.hex('#E8E8E8');
|
|
121
131
|
for (let i = 0; i < totalRows; i++) {
|
|
122
|
-
const
|
|
123
|
-
?
|
|
132
|
+
const rawPortraitLine = i < portraitRows.length
|
|
133
|
+
? padBraillePortrait(portraitRows[i], PORTRAIT_WIDTH)
|
|
124
134
|
: ' '.repeat(PORTRAIT_WIDTH);
|
|
135
|
+
const portraitLine = portraitTint(rawPortraitLine);
|
|
125
136
|
// Text column content
|
|
126
137
|
let textCol = '';
|
|
127
138
|
const textIdx = i - TEXT_TOP_OFFSET;
|
|
@@ -132,21 +143,22 @@ function printSideBySide(version) {
|
|
|
132
143
|
textCol = chalk.hex(color)(FRANKLIN_ART[textIdx]);
|
|
133
144
|
}
|
|
134
145
|
else if (textIdx === textRows) {
|
|
135
|
-
// Tagline row sits right under the FRANKLIN block
|
|
146
|
+
// Tagline row sits right under the FRANKLIN block.
|
|
147
|
+
// The big block-letter FRANKLIN above already says the product name
|
|
148
|
+
// — the tagline uses that line for the parent brand URL
|
|
149
|
+
// (blockrun.ai — a real live domain; see v3.1.0 notes for why
|
|
150
|
+
// franklin.run is explicitly NOT used here).
|
|
136
151
|
textCol =
|
|
137
|
-
chalk.bold.hex(GOLD_START)('
|
|
152
|
+
chalk.bold.hex(GOLD_START)(' blockrun.ai') +
|
|
138
153
|
chalk.dim(' · The AI agent with a wallet · v' + version);
|
|
139
154
|
}
|
|
140
|
-
|
|
141
|
-
// previous line bleeding into the current row's portrait column.
|
|
142
|
-
process.stdout.write('\x1b[0m' + portraitLine + GAP + textCol + '\x1b[0m\n');
|
|
155
|
+
process.stdout.write(portraitLine + GAP + textCol + '\n');
|
|
143
156
|
}
|
|
144
|
-
// Trailing blank line for breathing room
|
|
145
157
|
process.stdout.write('\n');
|
|
146
158
|
}
|
|
147
159
|
/**
|
|
148
160
|
* Compact layout for narrow terminals: just the FRANKLIN text block with
|
|
149
|
-
* its gradient, no portrait.
|
|
161
|
+
* its gradient, no portrait.
|
|
150
162
|
*/
|
|
151
163
|
function printTextOnly(version) {
|
|
152
164
|
const textRows = FRANKLIN_ART.length;
|
|
@@ -155,7 +167,7 @@ function printTextOnly(version) {
|
|
|
155
167
|
const color = interpolateHex(GOLD_START, EMERALD_END, t);
|
|
156
168
|
console.log(chalk.hex(color)(FRANKLIN_ART[i]));
|
|
157
169
|
}
|
|
158
|
-
console.log(chalk.bold.hex(GOLD_START)('
|
|
170
|
+
console.log(chalk.bold.hex(GOLD_START)(' blockrun.ai') +
|
|
159
171
|
chalk.dim(' · The AI agent with a wallet · v' + version) +
|
|
160
172
|
'\n');
|
|
161
173
|
}
|
package/package.json
CHANGED