build-in-public-bot
Version:
AI-powered CLI bot for automating build-in-public tweets with code screenshots
203 lines • 9.27 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.terminalCommand = void 0;
const commander_1 = require("commander");
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const terminal_capture_1 = require("../services/terminal-capture");
const errors_1 = require("../utils/errors");
const fs = __importStar(require("fs/promises"));
exports.terminalCommand = new commander_1.Command('terminal')
.description('Capture and annotate terminal output')
.option('-o, --output <path>', 'Output file path', 'terminal-capture.png')
.option('-h, --height <lines>', 'Number of lines to capture', '30')
.option('--theme <theme>', 'Color theme to apply')
.option('-s, --select <ranges>', 'Select line ranges (e.g., "5-10,15,20-")')
.option('--highlight <pattern>', 'Highlight lines matching pattern')
.option('--highlight-regex <regex>', 'Highlight lines matching regex')
.option('--last-command', 'Capture last command with output')
.option('--command <n>', 'Capture nth command (negative for reverse)')
.option('--select-errors', 'Auto-select error output')
.option('--select-diff', 'Highlight diff changes')
.option('--select-prompts', 'Include command prompts')
.option('--cursor <pos>', 'Show cursor at position (line:col)')
.option('--no-colors', 'Strip ANSI colors')
.option('--font-size <size>', 'Font size in pixels', '14')
.option('--padding <padding>', 'Padding in pixels', '20')
.option('--arrow <spec...>', 'Add arrow annotation (from:to:label)')
.option('--box <spec...>', 'Add box annotation (startLine-endLine:startCol-endCol)')
.option('--note <spec...>', 'Add note annotation (line:text)')
.option('--format <format>', 'Output format (png, svg)', 'png')
.option('--list-themes', 'List available terminal themes')
.option('--detect-editor', 'Show editor detection information')
.option('--dry-run', 'Show what would be captured without saving')
.action(async (options) => {
try {
const terminalCapture = new terminal_capture_1.TerminalCapture();
if (options.listThemes) {
const themes = terminalCapture.getAvailableThemes();
console.log(chalk_1.default.cyan('Available terminal themes:'));
themes.forEach((theme) => console.log(` - ${theme}`));
return;
}
if (options.detectEditor) {
const editorInfo = terminalCapture.getEditorInfo();
console.log(chalk_1.default.cyan('Editor Detection:'));
console.log(` Running in editor: ${editorInfo.isEditor ? chalk_1.default.green('Yes') : chalk_1.default.red('No')}`);
if (editorInfo.isEditor && editorInfo.editor) {
console.log(` Editor type: ${chalk_1.default.yellow(editorInfo.editor)}`);
}
if (editorInfo.mode) {
console.log(` Mode: ${chalk_1.default.yellow(editorInfo.mode)}`);
}
return;
}
const spinner = (0, ora_1.default)('Capturing terminal...').start();
try {
const captureOptions = {
height: parseInt(options.height),
theme: options.theme || 'auto',
includeColors: !options.noColors,
fontSize: parseInt(options.fontSize),
padding: parseInt(options.padding)
};
const terminalData = await terminalCapture.capture(captureOptions);
if (options.select) {
terminalCapture.selectLines(parseRanges(options.select));
}
if (options.highlight) {
terminalCapture.highlightPattern(options.highlight);
}
if (options.highlightRegex) {
terminalCapture.highlightRegex(new RegExp(options.highlightRegex));
}
if (options.lastCommand) {
terminalCapture.selectLastCommand();
}
if (options.command) {
terminalCapture.selectCommand(parseInt(options.command));
}
if (options.selectErrors) {
terminalCapture.selectErrors();
}
if (options.selectDiff) {
terminalCapture.selectDiff();
}
if (options.cursor) {
const [line, col] = options.cursor.split(':').map(Number);
terminalCapture.showCursor(line, col);
}
for (const arrow of (options.arrow || [])) {
const parts = arrow.split(':');
if (parts.length >= 4) {
const fromLine = parseInt(parts[0]);
const fromCol = parseInt(parts[1]);
const toLine = parseInt(parts[2]);
const toCol = parseInt(parts[3]);
const label = parts.slice(4).join(':').replace(/['"]/g, '');
terminalCapture.addArrow({ line: fromLine, col: fromCol }, { line: toLine, col: toCol }, label);
}
else {
const [from, to, label] = parts;
const [fromLine, fromCol] = from.split(',').map(Number);
const [toLine, toCol] = to.split(',').map(Number);
terminalCapture.addArrow({ line: fromLine, col: fromCol }, { line: toLine, col: toCol }, label);
}
}
for (const box of (options.box || [])) {
const [range, cols] = box.split(':');
const [startLine, endLine] = range.split('-').map(Number);
const [startCol, endCol] = cols ? cols.split('-').map(Number) : [0, -1];
terminalCapture.addBox({
startLine,
endLine,
startCol,
endCol
});
}
for (const note of (options.note || [])) {
const [line, ...text] = note.split(':');
terminalCapture.addNote(parseInt(line), text.join(':'));
}
if (options.dryRun) {
spinner.stop();
console.log(chalk_1.default.yellow('Dry run - would capture:'));
console.log(` Lines: ${terminalData.lines.length}`);
console.log(` Theme: ${captureOptions.theme}`);
console.log(` Output: ${options.output}`);
console.log(` Format: ${options.format}`);
if (options.select) {
console.log(` Selected lines: ${options.select}`);
}
return;
}
const buffer = await terminalCapture.render(options.format);
await fs.writeFile(options.output, buffer);
spinner.succeed(chalk_1.default.green(`Terminal captured to ${options.output}`));
}
catch (error) {
spinner.fail(chalk_1.default.red('Failed to capture terminal'));
throw error;
}
}
catch (error) {
(0, errors_1.handleError)(error);
}
});
function parseRanges(rangeStr) {
const ranges = [];
const parts = rangeStr.split(',');
for (const part of parts) {
const trimmed = part.trim();
if (trimmed.includes('-')) {
const [start, end] = trimmed.split('-');
ranges.push({
start: start ? parseInt(start) : 1,
end: end ? parseInt(end) : -1
});
}
else {
const line = parseInt(trimmed);
ranges.push({ start: line, end: line });
}
}
return ranges;
}
exports.default = exports.terminalCommand;
//# sourceMappingURL=terminal.js.map
;