ccsay
Version:
A joke CLI tool that displays text in ASCII art like cowsay
97 lines (89 loc) • 7.99 kB
text/typescript
export const BLOCK_FONT: Record<string, string[]> = {
A: [" █████╗ ", "██╔══██╗", "███████║", "██╔══██║", "██║ ██║", "╚═╝ ╚═╝"],
B: ["██████╗ ", "██╔══██╗", "██████╔╝", "██╔══██╗", "██████╔╝", "╚═════╝ "],
C: [" ██████╗", "██╔════╝", "██║ ", "██║ ", "╚██████╗", " ╚═════╝"],
D: ["██████╗ ", "██╔══██╗", "██║ ██║", "██║ ██║", "██████╔╝", "╚═════╝ "],
E: ["███████╗", "██╔════╝", "█████╗ ", "██╔══╝ ", "███████╗", "╚══════╝"],
F: ["███████╗", "██╔════╝", "█████╗ ", "██╔══╝ ", "██║ ", "╚═╝ "],
G: [" ██████╗ ", "██╔════╝ ", "██║ ███╗", "██║ ██║", "╚██████╔╝", " ╚═════╝ "],
H: ["██╗ ██╗", "██║ ██║", "███████║", "██╔══██║", "██║ ██║", "╚═╝ ╚═╝"],
I: ["██╗", "██║", "██║", "██║", "██║", "╚═╝"],
J: [" ██╗", " ██║", " ██║", "██ ██║", "╚█████╔╝", " ╚════╝ "],
K: ["██╗ ██╗", "██║ ██╔╝", "█████╔╝ ", "██╔═██╗ ", "██║ ██╗", "╚═╝ ╚═╝"],
L: ["██╗ ", "██║ ", "██║ ", "██║ ", "███████╗", "╚══════╝"],
M: ["███╗ ███╗", "████╗ ████║", "██╔████╔██║", "██║╚██╔╝██║", "██║ ╚═╝ ██║", "╚═╝ ╚═╝"],
N: ["███╗ ██╗", "████╗ ██║", "██╔██╗ ██║", "██║╚██╗██║", "██║ ╚████║", "╚═╝ ╚═══╝"],
O: [" ██████╗ ", "██╔═══██╗", "██║ ██║", "██║ ██║", "╚██████╔╝", " ╚═════╝ "],
P: ["██████╗ ", "██╔══██╗", "██████╔╝", "██╔═══╝ ", "██║ ", "╚═╝ "],
Q: [" ██████╗ ", "██╔═══██╗", "██║ ██║", "██║▄▄ ██║", "╚██████╔╝", " ╚══▀▀═╝ "],
R: ["██████╗ ", "██╔══██╗", "██████╔╝", "██╔══██╗", "██║ ██║", "╚═╝ ╚═╝"],
S: ["███████╗", "██╔════╝", "███████╗", "╚════██║", "███████║", "╚══════╝"],
T: ["████████╗", "╚══██╔══╝", " ██║ ", " ██║ ", " ██║ ", " ╚═╝ "],
U: ["██╗ ██╗", "██║ ██║", "██║ ██║", "██║ ██║", "╚██████╔╝", " ╚═════╝ "],
V: ["██╗ ██╗", "██║ ██║", "██║ ██║", "╚██╗ ██╔╝", " ╚████╔╝ ", " ╚═══╝ "],
W: ["██╗ ██╗", "██║ ██║", "██║ █╗ ██║", "██║███╗██║", "╚███╔███╔╝", " ╚══╝╚══╝ "],
X: ["██╗ ██╗", "╚██╗██╔╝", " ╚███╔╝ ", " ██╔██╗ ", "██╔╝ ██╗", "╚═╝ ╚═╝"],
Y: ["██╗ ██╗", "╚██╗ ██╔╝", " ╚████╔╝ ", " ╚██╔╝ ", " ██║ ", " ╚═╝ "],
Z: ["███████╗", "╚══███╔╝", " ███╔╝ ", " ███╔╝ ", "███████╗", "╚══════╝"],
" ": [" ", " ", " ", " ", " ", " "],
"!": ["██╗", "██║", "██║", "╚═╝", "██╗", "╚═╝"],
"?": ["██████╗ ", "╚════██╗", " ▄███╔╝", " ▀▀══╝ ", " ██╗ ", " ╚═╝ "],
".": [" ", " ", " ", " ", "██╗", "╚═╝"],
",": [" ", " ", " ", " ", "▄█╗", "╚═╝"],
"-": [" ", " ", "█████╗", "╚════╝", " ", " "],
"0": [" ██████╗ ", "██╔═████╗", "██║██╔██║", "████╔╝██║", "╚██████╔╝", " ╚═════╝ "],
"1": [" ██╗", "███║", "╚██║", " ██║", " ██║", " ╚═╝"],
"2": ["██████╗ ", "╚════██╗", " █████╔╝", "██╔═══╝ ", "███████╗", "╚══════╝"],
"3": ["██████╗ ", "╚════██╗", " █████╔╝", " ╚═══██╗", "██████╔╝", "╚═════╝ "],
"4": ["██╗ ██╗", "██║ ██║", "███████║", "╚════██║", " ██║", " ╚═╝"],
"5": ["███████╗", "██╔════╝", "███████╗", "╚════██║", "███████║", "╚══════╝"],
"6": [" ██████╗ ", "██╔════╝ ", "███████╗ ", "██╔═══██╗", "╚██████╔╝", " ╚═════╝ "],
"7": ["███████╗", "╚════██║", " ██╔╝", " ██╔╝ ", " ██║ ", " ╚═╝ "],
"8": [" █████╗ ", "██╔══██╗", "╚█████╔╝", "██╔══██╗", "╚█████╔╝", " ╚════╝ "],
"9": [" █████╗ ", "██╔══██╗", "╚██████║", " ╚═══██║", " █████╔╝", " ╚════╝ "],
};
export function textToAsciiArt(text: string): string {
if (!text) return "\n\n\n\n\n";
const textLines = text.split("\n");
const spaceChar = BLOCK_FONT[" "];
const allAsciiLines: string[][] = [];
for (let lineIndex = 0; lineIndex < textLines.length; lineIndex++) {
const textLine = textLines[lineIndex];
if (!textLine) {
// Add empty lines for empty text lines
for (let i = 0; i < 6; i++) {
allAsciiLines.push([]);
}
} else {
const upperText = textLine.toUpperCase();
const lines: string[][] = [[], [], [], [], [], []];
// Pre-calculate character arts to avoid repeated lookups
const charArts: string[][] = [];
for (let charIndex = 0; charIndex < upperText.length; charIndex++) {
const char = upperText[charIndex];
const charArt = char ? BLOCK_FONT[char] : undefined;
charArts[charIndex] = charArt || spaceChar;
}
// Build all 6 lines simultaneously
for (let i = 0; i < 6; i++) {
const line = lines[i];
if (line) {
for (let charIndex = 0; charIndex < charArts.length; charIndex++) {
const charArt = charArts[charIndex];
const artLine = charArt?.[i];
if (artLine) {
line.push(artLine);
}
}
allAsciiLines.push(line);
}
}
}
// Add separator between text lines (except last)
if (lineIndex < textLines.length - 1) {
allAsciiLines.push([]);
}
}
// Join all at once for better performance
return allAsciiLines.map((line) => line.join("")).join("\n");
}