UNPKG

cli-ascii-logo

Version:

Create beautiful ASCII art logos with gradient colors for your CLI applications

196 lines 6.86 kB
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