doclyft
Version:
CLI for DocLyft - Interactive documentation generator with hosted documentation support
251 lines (250 loc) • 8.83 kB
JavaScript
;
/**
* 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');
}