235 lines
7.7 KiB
JavaScript
235 lines
7.7 KiB
JavaScript
class ArgumentBuilder {
|
||
constructor() {
|
||
this.arguments = [];
|
||
this.container = document.getElementById('arguments-container');
|
||
this.headerInput = document.getElementById('custom-header');
|
||
this.generateBtn = document.getElementById('generate-btn');
|
||
this.helpContent = document.getElementById('help-content');
|
||
this.outputSection = document.getElementById('output-section');
|
||
this.generatedCode = document.getElementById('generated-code');
|
||
this.copyBtn = document.getElementById('copy-btn');
|
||
|
||
this.init();
|
||
}
|
||
|
||
init() {
|
||
// Add initial empty row
|
||
this.addArgumentRow();
|
||
|
||
// Event listeners
|
||
this.generateBtn.addEventListener('click', () => this.generateScript());
|
||
this.headerInput.addEventListener('input', () => this.updateHelpPreview());
|
||
this.copyBtn.addEventListener('click', () => this.copyToClipboard());
|
||
|
||
// Update help preview initially
|
||
this.updateHelpPreview();
|
||
}
|
||
|
||
addArgumentRow(params = '', command = '', helpText = '') {
|
||
const row = document.createElement('div');
|
||
row.className = 'argument-row';
|
||
|
||
const paramsInput = document.createElement('input');
|
||
paramsInput.type = 'text';
|
||
paramsInput.placeholder = '-v --verbose';
|
||
paramsInput.value = params;
|
||
|
||
const commandInput = document.createElement('input');
|
||
commandInput.type = 'text';
|
||
commandInput.placeholder = 'verbose';
|
||
commandInput.value = command;
|
||
|
||
const helpTextInput = document.createElement('input');
|
||
helpTextInput.type = 'text';
|
||
helpTextInput.placeholder = 'Enable verbose output';
|
||
helpTextInput.value = helpText;
|
||
|
||
const removeBtn = document.createElement('button');
|
||
removeBtn.className = 'remove-btn';
|
||
removeBtn.innerHTML = '×';
|
||
removeBtn.addEventListener('click', () => {
|
||
row.remove();
|
||
this.updateHelpPreview();
|
||
});
|
||
|
||
// Add input event listeners for real-time updates
|
||
const updatePreview = () => {
|
||
this.updateHelpPreview();
|
||
// Add new empty row if this is the last row and has content
|
||
const rows = this.container.querySelectorAll('.argument-row');
|
||
const isLastRow = rows[rows.length - 1] === row;
|
||
const hasContent = commandInput.value.trim() !== '';
|
||
|
||
if (isLastRow && hasContent) {
|
||
this.addArgumentRow();
|
||
}
|
||
};
|
||
|
||
paramsInput.addEventListener('input', updatePreview);
|
||
commandInput.addEventListener('input', updatePreview);
|
||
helpTextInput.addEventListener('input', updatePreview);
|
||
|
||
row.appendChild(paramsInput);
|
||
row.appendChild(commandInput);
|
||
row.appendChild(helpTextInput);
|
||
row.appendChild(removeBtn);
|
||
|
||
this.container.appendChild(row);
|
||
}
|
||
|
||
getArguments() {
|
||
const rows = this.container.querySelectorAll('.argument-row');
|
||
const args = [];
|
||
|
||
rows.forEach(row => {
|
||
const inputs = row.querySelectorAll('input');
|
||
const params = inputs[0].value.trim();
|
||
const command = inputs[1].value.trim();
|
||
const helpText = inputs[2].value.trim();
|
||
|
||
if (command) {
|
||
args.push({
|
||
params: params || command,
|
||
command: command,
|
||
helpText: helpText || command
|
||
});
|
||
}
|
||
});
|
||
|
||
return args;
|
||
}
|
||
|
||
addSubcommand(name = '', description = '') {
|
||
const subcommandSection = document.createElement('div');
|
||
subcommandSection.className = 'subcommand-section';
|
||
|
||
const header = this.createSubcommandHeader(name, description);
|
||
const argsContainer = this.createArgumentsContainer();
|
||
|
||
subcommandSection.appendChild(header);
|
||
subcommandSection.appendChild(argsContainer);
|
||
|
||
this.subcommandContainer.appendChild(subcommandSection);
|
||
|
||
return subcommandSection;
|
||
}
|
||
|
||
updateHelpPreview() {
|
||
const header = this.headerInput.value.trim();
|
||
const args = this.getArguments();
|
||
|
||
if (args.length === 0) {
|
||
this.helpContent.textContent = 'Add arguments to see the help output...';
|
||
return;
|
||
}
|
||
|
||
let helpText = '';
|
||
|
||
if (header) {
|
||
helpText += header + '\n\n';
|
||
}
|
||
|
||
helpText += 'Usage: script.sh [OPTIONS]\n\n';
|
||
helpText += 'Options:\n';
|
||
|
||
args.forEach(arg => {
|
||
const params = arg.params || arg.command;
|
||
const help = arg.helpText || arg.command;
|
||
helpText += ` ${params.padEnd(20)} ${help}\n`;
|
||
});
|
||
|
||
helpText += ` ${'-h --help'.padEnd(20)} Show this help message\n`;
|
||
|
||
this.helpContent.textContent = helpText;
|
||
}
|
||
createSubcommandHeader(name, description) {
|
||
const header = document.createElement('div');
|
||
header.className = 'subcommand-header';
|
||
header.innerHTML = `
|
||
<input type="text" class="subcommand-name"
|
||
placeholder="container" value="${name}">
|
||
<input type="text" class="subcommand-desc"
|
||
placeholder="Manage containers" value="${description}">
|
||
<button class="toggle-btn">▼</button>
|
||
<button class="remove-btn">×</button>
|
||
`;
|
||
return header;
|
||
}
|
||
|
||
getSubcommands() {
|
||
const sections = this.subcommandContainer.querySelectorAll('.subcommand-section');
|
||
return Array.from(sections).map(section => {
|
||
const nameInput = section.querySelector('.subcommand-name');
|
||
const descInput = section.querySelector('.subcommand-desc');
|
||
const args = this.getArgumentsFromSection(section);
|
||
|
||
return {
|
||
name: nameInput.value.trim(),
|
||
description: descInput.value.trim(),
|
||
arguments: args
|
||
};
|
||
}).filter(sc => sc.name);
|
||
}
|
||
|
||
async generateScript() {
|
||
const header = this.headerInput.value.trim();
|
||
const args = this.getArguments();
|
||
|
||
if (args.length === 0) {
|
||
alert('Please add at least one argument');
|
||
return;
|
||
}
|
||
|
||
const payload = {
|
||
header: this.headerInput.value.trim(),
|
||
arguments: this.getArguments(),
|
||
subcommands: this.getSubcommands()
|
||
};
|
||
|
||
try {
|
||
const response = await fetch('/generate', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(payload)
|
||
});
|
||
|
||
if (!response.ok) {
|
||
throw new Error('Failed to generate script');
|
||
}
|
||
|
||
const scriptCode = await response.text();
|
||
this.generatedCode.textContent = scriptCode;
|
||
this.outputSection.style.display = 'block';
|
||
|
||
// Smooth scroll to output
|
||
this.outputSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||
} catch (error) {
|
||
alert('Error generating script: ' + error.message);
|
||
}
|
||
}
|
||
|
||
async copyToClipboard() {
|
||
const code = this.generatedCode.textContent;
|
||
|
||
try {
|
||
await navigator.clipboard.writeText(code);
|
||
this.copyBtn.textContent = 'Copied!';
|
||
this.copyBtn.classList.add('copied');
|
||
|
||
setTimeout(() => {
|
||
this.copyBtn.textContent = 'Copy';
|
||
this.copyBtn.classList.remove('copied');
|
||
}, 2000);
|
||
} catch (error) {
|
||
alert('Failed to copy to clipboard');
|
||
}
|
||
}
|
||
}
|
||
|
||
// Initialize the application when DOM is ready
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
new ArgumentBuilder();
|
||
});
|