UNPKG

doclyft

Version:

CLI for DocLyft - Interactive documentation generator with hosted documentation support

251 lines (250 loc) 8.83 kB
"use strict"; /** * Visual utilities for enhanced CLI output * Provides consistent styling, borders, and visual elements */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SEPARATORS = exports.DOUBLE_BOX = exports.BOX = void 0; exports.createBox = createBox; exports.createHeader = createHeader; exports.createStatus = createStatus; exports.createProgress = createProgress; exports.createTable = createTable; exports.createCommandList = createCommandList; exports.createDivider = createDivider; exports.createSuccessMessage = createSuccessMessage; exports.createErrorMessage = createErrorMessage; const chalk_1 = __importDefault(require("chalk")); // Box drawing characters for borders exports.BOX = { topLeft: '┌', topRight: '┐', bottomLeft: '└', bottomRight: '┘', horizontal: '─', vertical: '│', cross: '┼', teeDown: '┬', teeUp: '┴', teeRight: '├', teeLeft: '┤' }; // Enhanced box characters for double lines exports.DOUBLE_BOX = { topLeft: '╔', topRight: '╗', bottomLeft: '╚', bottomRight: '╝', horizontal: '═', vertical: '║', cross: '╬', teeDown: '╦', teeUp: '╩', teeRight: '╠', teeLeft: '╣' }; // Visual separators exports.SEPARATORS = { light: '─'.repeat(60), medium: '━'.repeat(60), heavy: '█'.repeat(60), dotted: '·'.repeat(60), dashed: '- '.repeat(30), wave: '~'.repeat(60) }; /** * Create a bordered box around content */ function createBox(content, options = {}) { const { title, style = 'single', color = 'cyan', padding = 1, width = 70 } = options; const box = style === 'double' ? exports.DOUBLE_BOX : exports.BOX; const colorFn = chalk_1.default[color] || chalk_1.default.cyan; // Calculate content width const contentWidth = width - 4; // Account for borders and padding // Prepare content lines with padding const paddedContent = content.map(line => { const stripped = stripAnsi(line); const padding = ' '.repeat(Math.max(0, contentWidth - stripped.length)); return ` ${line}${padding} `; }); // Add vertical padding if (padding > 0) { const emptyLine = ` ${' '.repeat(contentWidth)} `; for (let i = 0; i < padding; i++) { paddedContent.unshift(emptyLine); paddedContent.push(emptyLine); } } // Build the box const lines = []; // Top border if (title) { const titleLength = stripAnsi(title).length; const leftPadding = Math.floor((contentWidth - titleLength - 2) / 2); const rightPadding = contentWidth - titleLength - 2 - leftPadding; const topLine = box.topLeft + box.horizontal.repeat(leftPadding + 1) + ` ${title} ` + box.horizontal.repeat(rightPadding + 1) + box.topRight; lines.push(colorFn(topLine)); } else { lines.push(colorFn(box.topLeft + box.horizontal.repeat(contentWidth + 2) + box.topRight)); } // Content lines paddedContent.forEach(line => { lines.push(colorFn(box.vertical) + line + colorFn(box.vertical)); }); // Bottom border lines.push(colorFn(box.bottomLeft + box.horizontal.repeat(contentWidth + 2) + box.bottomRight)); return lines.join('\n'); } /** * Create a section header with decorative elements */ function createHeader(text, options = {}) { const { style = 'decorated', color = 'cyan', width = 60 } = options; const colorFn = chalk_1.default[color] || chalk_1.default.cyan; switch (style) { case 'simple': return colorFn(`\n${text}\n${'─'.repeat(text.length)}`); case 'banner': const padding = Math.max(0, Math.floor((width - text.length) / 2)); const line = '═'.repeat(width); return colorFn(`\n${line}\n${' '.repeat(padding)}${text}\n${line}`); case 'decorated': default: const decorLine = '━'.repeat(Math.max(0, Math.floor((width - text.length - 4) / 2))); return colorFn(`\n${decorLine}${text}${decorLine}`); } } /** * Create a status indicator with icon and styling */ function createStatus(status, message) { const icons = { success: '✅', error: '❌', warning: '⚠️', info: 'ℹ️' }; const colors = { success: chalk_1.default.green, error: chalk_1.default.red, warning: chalk_1.default.yellow, info: chalk_1.default.blue }; return colors[status](`${icons[status]} ${message}`); } /** * Create a progress indicator */ function createProgress(current, total, label) { const percentage = Math.round((current / total) * 100); const filled = Math.round((current / total) * 20); const empty = 20 - filled; const bar = '█'.repeat(filled) + '░'.repeat(empty); const coloredBar = chalk_1.default.cyan(bar); return `${label ? label + ': ' : ''}[${coloredBar}] ${percentage}% (${current}/${total})`; } /** * Create an information table */ function createTable(data, options = {}) { const { title, keyColor = 'cyan', valueColor = 'white', separatorColor = 'gray' } = options; const keyColorFn = chalk_1.default[keyColor] || chalk_1.default.cyan; const valueColorFn = chalk_1.default[valueColor] || chalk_1.default.white; const sepColorFn = chalk_1.default[separatorColor] || chalk_1.default.gray; // Find max key length for alignment const maxKeyLength = Math.max(...data.map(item => stripAnsi(item.key).length)); const lines = []; if (title) { lines.push(createHeader(title, { style: 'simple', color: keyColor })); lines.push(''); } data.forEach((item, index) => { const padding = ' '.repeat(maxKeyLength - stripAnsi(item.key).length); const separator = sepColorFn(' │ '); lines.push(`${keyColorFn(item.key)}${padding}${separator}${valueColorFn(item.value)}`); if (index < data.length - 1) { lines.push(sepColorFn('─'.repeat(maxKeyLength + stripAnsi(item.value).length + 3))); } }); return lines.join('\n'); } /** * Create a command list with descriptions */ function createCommandList(commands, options = {}) { const { title, nameColor = 'green', descColor = 'gray' } = options; const nameColorFn = chalk_1.default[nameColor] || chalk_1.default.green; const descColorFn = chalk_1.default[descColor] || chalk_1.default.gray; const lines = []; if (title) { lines.push(createHeader(title, { style: 'decorated', color: nameColor })); lines.push(''); } // Find max command name length for alignment const maxNameLength = Math.max(...commands.map(cmd => cmd.name.length)); commands.forEach(cmd => { const padding = ' '.repeat(maxNameLength - cmd.name.length + 2); lines.push(` ${nameColorFn(cmd.name)}${padding}${descColorFn(cmd.description)}`); }); return lines.join('\n'); } /** * Create a divider line with optional text */ function createDivider(text, options = {}) { const { char = '─', color = 'gray', width = 60 } = options; const colorFn = chalk_1.default[color] || chalk_1.default.gray; if (!text) { return colorFn(char.repeat(width)); } const textLength = stripAnsi(text).length; const sideLength = Math.floor((width - textLength - 2) / 2); const leftSide = char.repeat(sideLength); const rightSide = char.repeat(width - textLength - 2 - sideLength); return colorFn(`${leftSide} ${text} ${rightSide}`); } /** * Strip ANSI color codes for length calculation */ function stripAnsi(str) { // eslint-disable-next-line no-control-regex return str.replace(/\u001b\[[0-9;]*m/g, ''); } /** * Create a success message with celebration */ function createSuccessMessage(message, details) { const lines = [ chalk_1.default.green('🎉 ') + chalk_1.default.bold.green(message), '' ]; if (details && details.length > 0) { details.forEach(detail => { lines.push(chalk_1.default.green(' ✓ ') + chalk_1.default.white(detail)); }); lines.push(''); } return lines.join('\n'); } /** * Create an error message with clear formatting */ function createErrorMessage(message, details) { const lines = [ chalk_1.default.red('❌ ') + chalk_1.default.bold.red(message), '' ]; if (details && details.length > 0) { details.forEach(detail => { lines.push(chalk_1.default.red(' ✗ ') + chalk_1.default.white(detail)); }); lines.push(''); } return lines.join('\n'); }