cli-ascii-logo
Version:
Create beautiful ASCII art logos with gradient colors for your CLI applications
196 lines • 6.86 kB
JavaScript
import figlet from "figlet";
import gradient from "gradient-string";
const DEFAULT_PALETTE = "sunset";
const DEFAULT_FONT = "ANSI Shadow";
const DEFAULT_TEXT_WIDTH = 100;
const PRESET_GRADIENTS = {
cristal: gradient.cristal,
teen: gradient.teen,
mind: gradient.mind,
morning: gradient.morning,
vice: gradient.vice,
passion: gradient.passion,
fruit: gradient.fruit,
instagram: gradient.instagram,
atlas: gradient.atlas,
retro: gradient.retro,
summer: gradient.summer,
pastel: gradient.pastel,
rainbow: gradient.rainbow,
};
const CUSTOM_GRADIENTS = {
sunset: ["#ff9966", "#ff5e62", "#ffa34e"],
ocean: ["#667eea", "#764ba2"],
fire: ["#ff0844", "#ffb199"],
forest: ["#134e5e", "#71b280"],
gold: ["#f7971e", "#ffd200"],
copper: ["#b87333", "#d4af37", "#cd7f32"],
blue: ["#4ea8ff", "#7f88ff"],
mint: ["#00d2ff", "#3a7bd5"],
aqua: ["#00ffff", "#00ced1", "#20b2aa"],
ice: ["#e0ffff", "#b0e0e6", "#87ceeb"],
dawn: ["#00c6ff", "#0072ff"],
lava: ["#ff4500", "#ffa500", "#ff0000"],
volcano: ["#8b0000", "#ff4500", "#ffd700"],
coral: ["#ff9a9e", "#fecfef"],
cherry: ["#ff1493", "#ff69b4", "#ff85c1"],
cyberpunk: ["#ff00ff", "#00ffff", "#ff00ff"],
neon: ["#39ff14", "#7fff00", "#adff2f"],
aurora: ["#00ff87", "#60efff", "#a78bfa"],
lavender: ["#e6e6fa", "#dda0dd", "#ba55d3"],
emerald: ["#50c878", "#2ecc71", "#00d084"],
matrix: ["#00ff41", "#008f11"],
nebula: ["#654ea3", "#eaafc8"],
};
const PALETTE_NAMES = [
...Object.keys(CUSTOM_GRADIENTS),
...Object.keys(PRESET_GRADIENTS),
];
class Logo {
constructor() {
this.text = "";
}
createLogo(text, palette = DEFAULT_PALETTE) {
return this.setText(text).addFontStyle().addGradient(palette);
}
createRandomLogo(text) {
const randomIndex = Math.floor(Math.random() * PALETTE_NAMES.length);
const randomPalette = PALETTE_NAMES[randomIndex];
return this.setText(text).addFontStyle().addGradient(randomPalette);
}
setText(text) {
if (!text || text.trim().length === 0) {
throw new Error("Text cannot be empty");
}
this.text = text;
return this;
}
getText() {
return this.text;
}
addFontStyle(font = DEFAULT_FONT, width = DEFAULT_TEXT_WIDTH) {
this.text = figlet.textSync(this.text, {
font,
horizontalLayout: "default",
verticalLayout: "default",
width,
whitespaceBreak: true,
});
return this;
}
addRandomGradient() {
const randomIndex = Math.floor(Math.random() * PALETTE_NAMES.length);
const randomPalette = PALETTE_NAMES[randomIndex];
return this.addGradient(randomPalette);
}
addGradient(palette) {
if (!this.text) {
throw new Error("No text set. Call setText() or addFontStyle() first.");
}
let gradientFunc;
if (palette in PRESET_GRADIENTS) {
gradientFunc = PRESET_GRADIENTS[palette];
}
else if (palette in CUSTOM_GRADIENTS) {
gradientFunc = gradient(CUSTOM_GRADIENTS[palette]);
}
else {
gradientFunc = gradient(CUSTOM_GRADIENTS[DEFAULT_PALETTE]);
}
return gradientFunc.multiline(this.text);
}
build(palette = DEFAULT_PALETTE) {
return this.addGradient(palette);
}
async display(options = {}) {
const { gradient: palette = DEFAULT_PALETTE, animation, duration = 2000, clearBefore = true, } = options;
const coloredLogo = this.addGradient(palette);
if (clearBefore) {
console.clear();
}
if (!animation) {
console.log(coloredLogo);
return;
}
const lines = coloredLogo.split("\n");
const lineCount = lines.length;
console.log("\n".repeat(lineCount - 1));
process.stdout.write(`\x1b[${lineCount}A`);
switch (animation) {
case "fade-in":
await this.animateFadeIn(coloredLogo, duration);
break;
case "slide-in":
await this.animateSlideIn(coloredLogo, duration, lineCount);
break;
case "typing":
await this.animateTyping(coloredLogo, duration);
break;
}
}
async animateFadeIn(text, duration) {
const lines = text.split("\n");
const delayPerLine = duration / lines.length;
for (let i = 0; i < lines.length; i++) {
process.stdout.write("\x1b[2K");
process.stdout.write(lines[i]);
if (i < lines.length - 1) {
process.stdout.write("\n");
}
await this.sleep(delayPerLine);
}
process.stdout.write("\n");
}
async animateSlideIn(text, duration, lineCount) {
const lines = text.split("\n");
const maxLineLength = Math.max(...lines.map(line => this.stripAnsi(line).length));
const fps = 30;
const totalFrames = Math.floor((duration / 1000) * fps);
const frameDelay = duration / totalFrames;
for (let frame = 0; frame <= totalFrames; frame++) {
const progress = frame / totalFrames;
const offset = Math.floor(maxLineLength * (1 - progress));
if (frame > 0) {
process.stdout.write(`\x1b[${lineCount}A`);
}
for (let i = 0; i < lines.length; i++) {
process.stdout.write("\x1b[2K");
const padding = " ".repeat(offset);
process.stdout.write(padding + lines[i]);
if (i < lines.length - 1) {
process.stdout.write("\n");
}
}
if (frame < totalFrames) {
await this.sleep(frameDelay);
}
}
process.stdout.write("\n");
}
stripAnsi(str) {
return str.replace(/\x1b\[[0-9;]*m/g, "");
}
async animateTyping(text, duration) {
const lines = text.split("\n");
const totalChars = text.length;
const delayPerChar = duration / totalChars;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
process.stdout.write("\x1b[2K");
for (const char of line) {
process.stdout.write(char);
await this.sleep(delayPerChar);
}
if (i < lines.length - 1) {
process.stdout.write("\n");
}
}
process.stdout.write("\n");
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
export { PALETTE_NAMES, CUSTOM_GRADIENTS, PRESET_GRADIENTS };
export default new Logo();
//# sourceMappingURL=Logo.js.map