@re-shell/cli
Version:
Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja
1,225 lines (1,199 loc) • 71.2 kB
JavaScript
"use strict";
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.InteractiveDocsGenerator = void 0;
exports.generateInteractiveDocs = generateInteractiveDocs;
exports.createDocsTheme = createDocsTheme;
const events_1 = require("events");
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const fast_glob_1 = __importDefault(require("fast-glob"));
class InteractiveDocsGenerator extends events_1.EventEmitter {
constructor(projectPath, config = {}) {
super();
this.projectPath = projectPath;
this.config = {
outputPath: path.join(projectPath, 'docs'),
includeExamples: true,
includeLiveDemo: true,
includeTypeDefinitions: true,
includeCodePlayground: true,
generateStaticSite: true,
autoRefresh: true,
port: 3000,
theme: this.getDefaultTheme(),
...config
};
}
async generateDocumentation() {
this.emit('generation:start', { projectPath: this.projectPath });
const startTime = Date.now();
const result = {
success: false,
outputPath: this.config.outputPath,
generatedFiles: [],
assets: [],
statistics: {
totalPages: 0,
totalCommands: 0,
totalExamples: 0,
totalGuides: 0,
totalTypes: 0,
generationTime: 0,
assetSize: 0,
codeBlocks: 0,
interactiveElements: 0
},
errors: [],
warnings: []
};
try {
// Ensure output directory exists
await fs.ensureDir(this.config.outputPath);
// Generate API documentation
const apiDocs = await this.generateAPIDocumentation();
// Generate static site if enabled
if (this.config.generateStaticSite) {
await this.generateStaticSite(apiDocs);
}
// Generate search index
if (apiDocs.search.enabled) {
result.searchIndex = await this.generateSearchIndex(apiDocs);
}
// Copy assets
await this.copyAssets();
// Generate statistics
result.statistics = this.calculateStatistics(apiDocs);
result.statistics.generationTime = Date.now() - startTime;
result.success = true;
this.emit('generation:complete', result);
}
catch (error) {
result.errors.push({
type: 'generation',
message: error.message,
severity: 'error'
});
this.emit('generation:error', error);
}
return result;
}
async generateAPIDocumentation() {
this.emit('api:generation:start');
const commands = await this.extractCommandDocumentation();
const types = await this.extractTypeDocumentation();
const examples = await this.generateExamples();
const guides = await this.generateGuides();
const apiDocs = {
metadata: await this.generateMetadata(),
commands,
types,
examples,
guides,
playground: this.generatePlaygroundConfig(),
search: this.generateSearchConfig()
};
// Save API documentation as JSON
const apiDocsPath = path.join(this.config.outputPath, 'api-docs.json');
await fs.writeJson(apiDocsPath, apiDocs, { spaces: 2 });
this.emit('api:generation:complete', apiDocs);
return apiDocs;
}
async extractCommandDocumentation() {
const commands = [];
try {
// Find command files
const commandFiles = await (0, fast_glob_1.default)('src/commands/**/*.ts', {
cwd: this.projectPath,
absolute: true
});
for (const file of commandFiles) {
const commandDoc = await this.parseCommandFile(file);
if (commandDoc) {
commands.push(commandDoc);
}
}
// Add built-in commands documentation
commands.push(...this.getBuiltInCommandDocs());
}
catch (error) {
this.emit('warning', {
type: 'missing_documentation',
message: 'Could not extract command documentation',
file: 'commands'
});
}
return commands.sort((a, b) => a.name.localeCompare(b.name));
}
async parseCommandFile(filePath) {
try {
const content = await fs.readFile(filePath, 'utf-8');
const commandName = path.basename(filePath, '.ts');
// Extract JSDoc comments and analyze code
const documentation = this.extractJSDocFromFile(content);
return {
name: commandName,
category: this.categorizeCommand(commandName),
description: documentation.description || `${commandName} command`,
synopsis: documentation.synopsis || `re-shell ${commandName} [options]`,
usage: documentation.usage || [
{
pattern: `re-shell ${commandName}`,
description: `Execute ${commandName} command`,
required: true
}
],
options: documentation.options || [],
examples: documentation.examples || this.generateDefaultExamples(commandName),
relatedCommands: documentation.relatedCommands || [],
since: documentation.since || '1.0.0',
deprecated: documentation.deprecated,
tags: documentation.tags || [this.categorizeCommand(commandName)],
complexity: documentation.complexity || 'beginner'
};
}
catch (error) {
return null;
}
}
extractJSDocFromFile(content) {
// Simple JSDoc extraction - in real implementation would use a proper parser
const jsdocRegex = /\/\*\*([\s\S]*?)\*\//g;
const matches = content.match(jsdocRegex);
if (!matches || matches.length === 0) {
return {};
}
// Parse first JSDoc block
const jsdoc = matches[0];
const description = this.extractDescription(jsdoc);
const examples = this.extractExamples(jsdoc);
return {
description,
examples,
synopsis: description ? `re-shell command - ${description}` : undefined,
usage: examples.length > 0 ? examples.map(ex => ({
pattern: ex.code,
description: ex.description,
required: true
})) : undefined
};
}
extractDescription(jsdoc) {
const lines = jsdoc.split('\n');
const descriptionLines = lines
.map(line => line.replace(/^\s*\*\s?/, ''))
.filter(line => line && !line.startsWith('@'))
.slice(1, -1);
return descriptionLines.join(' ').trim();
}
extractExamples(jsdoc) {
const examples = [];
const exampleRegex = /@example\s+([\s\S]*?)(?=@|\*\/)/g;
let match;
while ((match = exampleRegex.exec(jsdoc)) !== null) {
const exampleContent = match[1]
.split('\n')
.map(line => line.replace(/^\s*\*\s?/, ''))
.join('\n')
.trim();
examples.push({
id: `example-${examples.length + 1}`,
title: `Example ${examples.length + 1}`,
description: 'Command usage example',
code: exampleContent,
language: 'bash',
interactive: true,
playgroundEnabled: true,
difficulty: 'beginner',
tags: ['example'],
output: '# Command output would appear here'
});
}
return examples;
}
categorizeCommand(commandName) {
const categories = {
'Project Management': ['init', 'create', 'new', 'setup'],
'Build & Deploy': ['build', 'deploy', 'serve', 'start'],
'Development': ['dev', 'watch', 'test', 'lint'],
'Workspace': ['add', 'remove', 'list', 'workspace'],
'Configuration': ['config', 'configure', 'settings'],
'Analysis': ['analyze', 'doctor', 'audit', 'profile'],
'Utilities': ['help', 'version', 'update', 'clean']
};
for (const [category, commands] of Object.entries(categories)) {
if (commands.some(cmd => commandName.includes(cmd))) {
return category;
}
}
return 'General';
}
generateDefaultExamples(commandName) {
return [
{
id: `${commandName}-basic`,
title: `Basic ${commandName} usage`,
description: `Simple example of using the ${commandName} command`,
code: `re-shell ${commandName}`,
language: 'bash',
output: `# ${commandName} command executed successfully`,
interactive: true,
playgroundEnabled: true,
difficulty: 'beginner',
tags: ['basic', commandName]
},
{
id: `${commandName}-advanced`,
title: `Advanced ${commandName} usage`,
description: `Advanced example with options`,
code: `re-shell ${commandName} --verbose --config custom.yaml`,
language: 'bash',
output: `# ${commandName} executed with custom configuration`,
interactive: true,
playgroundEnabled: true,
difficulty: 'intermediate',
tags: ['advanced', commandName]
}
];
}
getBuiltInCommandDocs() {
return [
{
name: 'init',
category: 'Project Management',
description: 'Initialize a new Re-Shell project with comprehensive setup',
synopsis: 're-shell init [project-name] [options]',
usage: [
{
pattern: 're-shell init',
description: 'Initialize project in current directory',
required: false
},
{
pattern: 're-shell init <project-name>',
description: 'Initialize project in new directory',
required: false
}
],
options: [
{
name: 'template',
alias: 't',
type: 'string',
description: 'Project template to use',
default: 'basic',
required: false,
choices: ['basic', 'ecommerce', 'dashboard', 'saas'],
examples: ['--template ecommerce', '-t dashboard'],
validation: [
{
type: 'enum',
value: ['basic', 'ecommerce', 'dashboard', 'saas'],
message: 'Template must be one of: basic, ecommerce, dashboard, saas'
}
]
},
{
name: 'package-manager',
alias: 'pm',
type: 'string',
description: 'Package manager to use',
default: 'npm',
required: false,
choices: ['npm', 'yarn', 'pnpm', 'bun'],
examples: ['--package-manager yarn', '-pm pnpm']
},
{
name: 'skip-install',
type: 'boolean',
description: 'Skip dependency installation',
default: false,
required: false,
examples: ['--skip-install']
}
],
examples: [
{
id: 'init-basic',
title: 'Basic project initialization',
description: 'Create a new Re-Shell project with default settings',
code: 're-shell init my-project',
language: 'bash',
output: `Creating new Re-Shell project 'my-project'...
✓ Project structure created
✓ Dependencies installed
✓ Configuration files generated
✓ Git repository initialized
Project created successfully!
cd my-project && re-shell dev`,
interactive: true,
playgroundEnabled: true,
difficulty: 'beginner',
tags: ['init', 'basic', 'getting-started']
},
{
id: 'init-ecommerce',
title: 'E-commerce project with custom template',
description: 'Initialize an e-commerce project with specialized template',
code: 're-shell init my-store --template ecommerce --package-manager yarn',
language: 'bash',
output: `Creating e-commerce project 'my-store'...
✓ E-commerce template applied
✓ Product catalog structure created
✓ Payment integration setup
✓ Yarn dependencies installed
✓ Development environment configured
E-commerce project ready!`,
interactive: true,
playgroundEnabled: true,
difficulty: 'intermediate',
tags: ['init', 'ecommerce', 'template']
}
],
relatedCommands: ['create', 'add', 'dev'],
since: '1.0.0',
tags: ['project', 'initialization', 'setup'],
complexity: 'beginner'
},
{
name: 'build',
category: 'Build & Deploy',
description: 'Build the project for production with optimization',
synopsis: 're-shell build [workspace] [options]',
usage: [
{
pattern: 're-shell build',
description: 'Build all workspaces',
required: false
},
{
pattern: 're-shell build <workspace>',
description: 'Build specific workspace',
required: false
}
],
options: [
{
name: 'mode',
alias: 'm',
type: 'string',
description: 'Build mode',
default: 'production',
required: false,
choices: ['development', 'production', 'test'],
examples: ['--mode production', '-m development']
},
{
name: 'watch',
alias: 'w',
type: 'boolean',
description: 'Watch for changes and rebuild',
default: false,
required: false,
examples: ['--watch']
},
{
name: 'analyze',
type: 'boolean',
description: 'Analyze bundle size',
default: false,
required: false,
examples: ['--analyze']
}
],
examples: [
{
id: 'build-production',
title: 'Production build',
description: 'Build all workspaces for production deployment',
code: 're-shell build --mode production',
language: 'bash',
output: `Building all workspaces for production...
✓ Frontend built (2.3MB)
✓ Backend built (1.8MB)
✓ Shared libraries built (0.5MB)
✓ Assets optimized
✓ Source maps generated
Build completed in 45.2s`,
interactive: true,
playgroundEnabled: true,
difficulty: 'beginner',
tags: ['build', 'production']
}
],
relatedCommands: ['dev', 'serve', 'deploy'],
since: '1.0.0',
tags: ['build', 'production', 'optimization'],
complexity: 'beginner'
}
];
}
async extractTypeDocumentation() {
const types = [];
try {
// Find TypeScript definition files
const typeFiles = await (0, fast_glob_1.default)('src/**/*.ts', {
cwd: this.projectPath,
absolute: true
});
for (const file of typeFiles) {
const fileTypes = await this.parseTypeFile(file);
types.push(...fileTypes);
}
}
catch (error) {
this.emit('warning', {
type: 'missing_documentation',
message: 'Could not extract type documentation'
});
}
return types;
}
async parseTypeFile(filePath) {
try {
const content = await fs.readFile(filePath, 'utf-8');
const types = [];
// Extract interfaces
const interfaceRegex = /export interface (\w+)\s*{([^}]*)}/g;
let match;
while ((match = interfaceRegex.exec(content)) !== null) {
const [, name, body] = match;
const properties = this.parseInterfaceProperties(body);
types.push({
name,
type: 'interface',
description: `${name} interface definition`,
definition: match[0],
properties,
examples: [
{
title: `${name} usage example`,
description: `Example of using ${name} interface`,
code: this.generateTypeExample(name, properties),
explanation: `This example shows how to create and use a ${name} object`
}
],
since: '1.0.0',
module: path.relative(this.projectPath, filePath)
});
}
return types;
}
catch (error) {
return [];
}
}
parseInterfaceProperties(body) {
const properties = [];
const lines = body.split('\n');
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('*'))
continue;
const propertyMatch = trimmed.match(/(\w+)(\?)?\s*:\s*([^;]+);?/);
if (propertyMatch) {
const [, name, optional, type] = propertyMatch;
properties.push({
name,
type: type.trim(),
description: `${name} property`,
optional: !!optional,
readonly: trimmed.includes('readonly'),
examples: [`${name}: ${this.generatePropertyExample(type.trim())}`]
});
}
}
return properties;
}
generatePropertyExample(type) {
switch (type.toLowerCase()) {
case 'string': return '"example"';
case 'number': return '42';
case 'boolean': return 'true';
case 'date': return 'new Date()';
default:
if (type.includes('[]'))
return '[]';
if (type.includes('Record'))
return '{}';
return '{}';
}
}
generateTypeExample(name, properties) {
const exampleProps = properties.slice(0, 3).map(prop => {
return ` ${prop.name}: ${prop.examples[0]}`;
}).join(',\n');
return `const example: ${name} = {
${exampleProps}
};`;
}
async generateExamples() {
return [
{
id: 'getting-started',
category: 'Quick Start',
title: 'Getting Started with Re-Shell',
description: 'Complete guide to setting up your first Re-Shell project',
difficulty: 'beginner',
estimatedTime: '10 minutes',
prerequisites: ['Node.js 14+', 'Basic command line knowledge'],
objectives: [
'Create a new Re-Shell project',
'Understand the project structure',
'Run the development server',
'Make your first changes'
],
steps: [
{
stepNumber: 1,
title: 'Install Re-Shell CLI',
description: 'Install the Re-Shell CLI globally using npm',
code: 'npm install -g @re-shell/cli',
explanation: 'This installs the Re-Shell command line interface globally on your system',
output: 'Successfully installed @re-shell/cli@latest',
tips: ['Use sudo on Linux/Mac if you encounter permission errors']
},
{
stepNumber: 2,
title: 'Create New Project',
description: 'Initialize a new Re-Shell project',
code: 're-shell init my-first-app --template basic',
explanation: 'Creates a new project directory with the basic template',
output: 'Project created successfully! Navigate to my-first-app to get started.',
notes: ['The basic template includes a simple microfrontend setup']
},
{
stepNumber: 3,
title: 'Start Development Server',
description: 'Navigate to the project and start the development server',
code: 'cd my-first-app && re-shell dev',
explanation: 'Starts the development server with hot reloading',
output: 'Development server running at http://localhost:3000',
tips: ['The server will automatically reload when you make changes']
}
],
fullCode: `# Complete setup process
npm install -g @re-shell/cli
re-shell init my-first-app --template basic
cd my-first-app
re-shell dev`,
output: 'Project created and development server started successfully!',
troubleshooting: [
{
issue: 'Permission denied during global install',
solution: 'Use sudo or configure npm to use a different directory',
prevention: 'Set up npm to use a global directory in your home folder'
}
],
variations: [
{
title: 'Using Yarn',
description: 'Same setup but using Yarn package manager',
changes: ['Use yarn instead of npm'],
code: 're-shell init my-first-app --template basic --package-manager yarn'
}
],
relatedExamples: ['project-structure', 'adding-microfrontends']
},
{
id: 'adding-microfrontends',
category: 'Microfrontends',
title: 'Adding Your First Microfrontend',
description: 'Learn how to add and configure microfrontends in your Re-Shell project',
difficulty: 'intermediate',
estimatedTime: '15 minutes',
prerequisites: ['Existing Re-Shell project', 'Basic React knowledge'],
objectives: [
'Add a new microfrontend to your project',
'Configure routing between microfrontends',
'Share data between components',
'Build and deploy the application'
],
steps: [
{
stepNumber: 1,
title: 'Add New Microfrontend',
description: 'Create a new microfrontend for user management',
code: 're-shell add users --framework react --typescript',
explanation: 'Generates a new microfrontend with React and TypeScript setup',
output: 'Microfrontend "users" created successfully!'
},
{
stepNumber: 2,
title: 'Configure Routing',
description: 'Set up routing to the new microfrontend',
code: `// In src/App.tsx
import { Route } from 'react-router-dom';
import Users from 'users/Users';
<Route path="/users" component={Users} />`,
explanation: 'Adds routing configuration for the users microfrontend'
}
],
fullCode: `re-shell add users --framework react --typescript
# Update routing configuration
# Test the new microfrontend
re-shell build`,
output: 'Microfrontend integrated successfully!',
troubleshooting: [],
variations: [],
relatedExamples: ['getting-started', 'project-structure']
}
];
}
async generateGuides() {
return [
{
id: 'project-architecture',
title: 'Re-Shell Project Architecture',
description: 'Understanding the architecture and design principles of Re-Shell projects',
category: 'Architecture',
difficulty: 'intermediate',
estimatedTime: '20 minutes',
lastUpdated: new Date(),
sections: [
{
id: 'overview',
title: 'Architecture Overview',
content: `Re-Shell follows a microfrontend architecture pattern that allows teams to develop, deploy, and scale frontend applications independently. Each microfrontend is a self-contained application that can be developed using different frameworks and technologies.
## Key Principles
1. **Independence**: Each microfrontend operates independently
2. **Technology Agnostic**: Use different frameworks for different parts
3. **Deployment Flexibility**: Deploy components separately
4. **Team Autonomy**: Teams can work independently on their features`,
codeBlocks: [
{
id: 'structure-example',
language: 'text',
code: `project/
├── apps/
│ ├── shell/ # Main application shell
│ ├── header/ # Header microfrontend
│ ├── sidebar/ # Sidebar microfrontend
│ └── dashboard/ # Dashboard microfrontend
├── packages/
│ ├── shared/ # Shared utilities
│ └── types/ # Shared types
└── tools/ # Build and dev tools`,
caption: 'Typical Re-Shell project structure',
interactive: false,
runnable: false
}
],
images: [],
videos: [],
interactive: false
}
],
prerequisites: ['Basic React knowledge', 'Understanding of frontend build tools'],
learningObjectives: [
'Understand microfrontend architecture',
'Learn Re-Shell project structure',
'Master component communication patterns'
],
nextSteps: [
'Build your first microfrontend',
'Implement shared state management',
'Set up CI/CD pipeline'
],
resources: [
{
title: 'Microfrontends.org',
url: 'https://microfrontends.org',
description: 'Comprehensive guide to microfrontend architecture',
type: 'external'
}
]
}
];
}
async generateMetadata() {
try {
const packageJsonPath = path.join(this.projectPath, 'package.json');
const packageJson = await fs.readJson(packageJsonPath);
return {
title: packageJson.name || 'Re-Shell Documentation',
version: packageJson.version || '1.0.0',
description: packageJson.description || 'Interactive API documentation for Re-Shell CLI',
lastUpdated: new Date(),
contributors: [
{
name: 'Re-Shell Team',
role: 'Maintainer'
}
],
license: packageJson.license || 'MIT',
repository: packageJson.repository?.url || '',
homepage: packageJson.homepage || ''
};
}
catch {
return {
title: 'Re-Shell Documentation',
version: '1.0.0',
description: 'Interactive API documentation for Re-Shell CLI',
lastUpdated: new Date(),
contributors: [],
license: 'MIT',
repository: '',
homepage: ''
};
}
}
generatePlaygroundConfig() {
return {
enabled: this.config.includeCodePlayground || false,
defaultCode: `// Welcome to the Re-Shell playground!
// Try running some commands:
re-shell init my-app --template basic
re-shell add users --framework react
re-shell build`,
availableCommands: ['init', 'add', 'build', 'dev', 'serve', 'analyze'],
environment: {
type: 'browser',
runtime: 'nodejs',
dependencies: ['@re-shell/cli'],
timeout: 30000,
memoryLimit: 512
},
features: [
{ name: 'syntax-highlighting', enabled: true },
{ name: 'auto-completion', enabled: true },
{ name: 'error-highlighting', enabled: true },
{ name: 'live-output', enabled: true }
],
templates: [
{
id: 'basic-init',
title: 'Basic Project Initialization',
description: 'Create a new Re-Shell project with default settings',
code: 're-shell init my-project --template basic',
category: 'Getting Started',
difficulty: 'beginner'
},
{
id: 'ecommerce-setup',
title: 'E-commerce Project Setup',
description: 'Set up an e-commerce project with specialized features',
code: `re-shell init my-store --template ecommerce
re-shell add products --framework react
re-shell add cart --framework vue`,
category: 'Templates',
difficulty: 'intermediate'
}
]
};
}
generateSearchConfig() {
return {
enabled: true,
provider: 'local',
indexFields: ['title', 'description', 'content', 'tags'],
filters: [
{
field: 'category',
label: 'Category',
type: 'category',
options: [
{ value: 'commands', label: 'Commands' },
{ value: 'guides', label: 'Guides' },
{ value: 'examples', label: 'Examples' },
{ value: 'types', label: 'Types' }
]
},
{
field: 'difficulty',
label: 'Difficulty',
type: 'difficulty',
options: [
{ value: 'beginner', label: 'Beginner' },
{ value: 'intermediate', label: 'Intermediate' },
{ value: 'advanced', label: 'Advanced' }
]
}
],
suggestions: true,
instantSearch: true
};
}
async generateStaticSite(apiDocs) {
this.emit('static-site:generation:start');
// Generate HTML pages
await this.generateHomePage(apiDocs);
await this.generateCommandPages(apiDocs.commands);
await this.generateExamplePages(apiDocs.examples);
await this.generateGuidePages(apiDocs.guides);
await this.generateTypePages(apiDocs.types);
// Generate navigation and search
await this.generateNavigation(apiDocs);
await this.generateSearchPage(apiDocs);
// Generate assets
await this.generateStyles();
await this.generateScripts();
this.emit('static-site:generation:complete');
}
async generateHomePage(apiDocs) {
const html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${apiDocs.metadata.title}</title>
<link rel="stylesheet" href="assets/styles.css">
<link rel="icon" type="image/x-icon" href="assets/favicon.ico">
</head>
<body>
<div id="app">
<header class="header">
<div class="container">
<div class="header-content">
<h1 class="logo">${apiDocs.metadata.title}</h1>
<nav class="nav">
<a href="#commands">Commands</a>
<a href="#examples">Examples</a>
<a href="#guides">Guides</a>
<a href="#types">Types</a>
<a href="#playground">Playground</a>
</nav>
</div>
</div>
</header>
<main class="main">
<section class="hero">
<div class="container">
<h2>Interactive API Documentation</h2>
<p>${apiDocs.metadata.description}</p>
<div class="hero-actions">
<a href="#getting-started" class="btn btn-primary">Get Started</a>
<a href="#playground" class="btn btn-secondary">Try Playground</a>
</div>
</div>
</section>
<section class="features">
<div class="container">
<div class="feature-grid">
<div class="feature-card">
<h3>📚 Comprehensive Commands</h3>
<p>${apiDocs.commands.length} documented commands with examples</p>
<a href="commands.html">Explore Commands</a>
</div>
<div class="feature-card">
<h3>🚀 Live Examples</h3>
<p>${apiDocs.examples.length} interactive examples to try</p>
<a href="examples.html">Browse Examples</a>
</div>
<div class="feature-card">
<h3>📖 Step-by-Step Guides</h3>
<p>${apiDocs.guides.length} detailed guides for every use case</p>
<a href="guides.html">Read Guides</a>
</div>
<div class="feature-card">
<h3>🔧 Type Definitions</h3>
<p>${apiDocs.types.length} TypeScript interfaces and types</p>
<a href="types.html">View Types</a>
</div>
</div>
</div>
</section>
</main>
<footer class="footer">
<div class="container">
<p>© ${new Date().getFullYear()} ${apiDocs.metadata.title}. Licensed under ${apiDocs.metadata.license}.</p>
</div>
</footer>
</div>
<script src="assets/scripts.js"></script>
</body>
</html>`;
await fs.writeFile(path.join(this.config.outputPath, 'index.html'), html);
}
async generateCommandPages(commands) {
// Generate commands index page
const commandsHtml = this.generateCommandsIndexHtml(commands);
await fs.writeFile(path.join(this.config.outputPath, 'commands.html'), commandsHtml);
// Generate individual command pages
for (const command of commands) {
const commandHtml = this.generateCommandPageHtml(command);
await fs.writeFile(path.join(this.config.outputPath, 'commands', `${command.name}.html`), commandHtml);
}
}
generateCommandsIndexHtml(commands) {
const categories = this.groupCommandsByCategory(commands);
const categoriesHtml = Object.entries(categories).map(([category, cmds]) => `
<section class="command-category">
<h3>${category}</h3>
<div class="command-grid">
${cmds.map(cmd => `
<div class="command-card">
<h4><a href="commands/${cmd.name}.html">${cmd.name}</a></h4>
<p>${cmd.description}</p>
<div class="command-meta">
<span class="complexity ${cmd.complexity}">${cmd.complexity}</span>
${cmd.deprecated ? '<span class="deprecated">Deprecated</span>' : ''}
</div>
</div>
`).join('')}
</div>
</section>
`).join('');
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Commands - Re-Shell Documentation</title>
<link rel="stylesheet" href="assets/styles.css">
</head>
<body>
<div id="app">
<header class="header">
<div class="container">
<div class="header-content">
<h1><a href="index.html">Re-Shell Docs</a></h1>
<nav class="nav">
<a href="commands.html" class="active">Commands</a>
<a href="examples.html">Examples</a>
<a href="guides.html">Guides</a>
</nav>
</div>
</div>
</header>
<main class="main">
<div class="container">
<div class="content">
<h2>Commands Reference</h2>
<p>Complete reference for all Re-Shell CLI commands with examples and options.</p>
<div class="search-box">
<input type="text" placeholder="Search commands..." id="command-search">
</div>
${categoriesHtml}
</div>
</div>
</main>
</div>
<script src="assets/scripts.js"></script>
</body>
</html>`;
}
groupCommandsByCategory(commands) {
const categories = {};
for (const command of commands) {
if (!categories[command.category]) {
categories[command.category] = [];
}
categories[command.category].push(command);
}
return categories;
}
generateCommandPageHtml(command) {
const optionsHtml = command.options.map(option => `
<tr>
<td><code>--${option.name}${option.alias ? `, -${option.alias}` : ''}</code></td>
<td>${option.type}</td>
<td>${option.description}</td>
<td>${option.default || 'None'}</td>
<td>${option.required ? 'Yes' : 'No'}</td>
</tr>
`).join('');
const examplesHtml = command.examples.map(example => `
<div class="example">
<h4>${example.title}</h4>
<p>${example.description}</p>
<div class="code-block">
<pre><code class="language-${example.language}">${example.code}</code></pre>
${example.interactive ? '<button class="run-example">Run Example</button>' : ''}
</div>
${example.output ? `
<div class="output">
<h5>Output:</h5>
<pre><code>${example.output}</code></pre>
</div>
` : ''}
</div>
`).join('');
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${command.name} - Re-Shell Documentation</title>
<link rel="stylesheet" href="../assets/styles.css">
<link rel="stylesheet" href="../assets/prism.css">
</head>
<body>
<div id="app">
<header class="header">
<div class="container">
<div class="header-content">
<h1><a href="../index.html">Re-Shell Docs</a></h1>
<nav class="nav">
<a href="../commands.html">Commands</a>
<a href="../examples.html">Examples</a>
<a href="../guides.html">Guides</a>
</nav>
</div>
</div>
</header>
<main class="main">
<div class="container">
<div class="content">
<div class="breadcrumb">
<a href="../index.html">Home</a> >
<a href="../commands.html">Commands</a> >
${command.name}
</div>
<h1>${command.name}</h1>
<p class="lead">${command.description}</p>
<div class="command-meta">
<span class="category">${command.category}</span>
<span class="complexity ${command.complexity}">${command.complexity}</span>
<span class="since">Since v${command.since}</span>
</div>
<section class="synopsis">
<h2>Synopsis</h2>
<div class="code-block">
<pre><code>${command.synopsis}</code></pre>
</div>
</section>
<section class="usage">
<h2>Usage</h2>
${command.usage.map(usage => `
<div class="usage-pattern">
<code>${usage.pattern}</code>
<p>${usage.description}</p>
</div>
`).join('')}
</section>
<section class="options">
<h2>Options</h2>
<table class="options-table">
<thead>
<tr>
<th>Option</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
<th>Required</th>
</tr>
</thead>
<tbody>
${optionsHtml}
</tbody>
</table>
</section>
<section class="examples">
<h2>Examples</h2>
${examplesHtml}
</section>
${command.relatedCommands.length > 0 ? `
<section class="related">
<h2>Related Commands</h2>
<ul>
${command.relatedCommands.map(cmd => `
<li><a href="${cmd}.html">${cmd}</a></li>
`).join('')}
</ul>
</section>
` : ''}
</div>
</div>
</main>
</div>
<script src="../assets/scripts.js"></script>
<script src="../assets/prism.js"></script>
</body>
</html>`;
}
async generateExamplePages(examples) {
// Implementation for example pages
const examplesHtml = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Examples - Re-Shell Documentation</title>
<link rel="stylesheet" href="assets/styles.css">
</head>
<body>
<div id="app">
<main class="main">
<div class="container">
<h2>Interactive Examples</h2>
<p>Learn by doing with our interactive examples.</p>
${examples.map(example => `
<div class="example-card">
<h3>${example.title}</h3>
<p>${example.description}</p>
<div class="example-meta">
<span class="difficulty ${example.difficulty}">${example.difficulty}</span>
<span class="time">${example.estimatedTime}</span>
</div>
<a href="examples/${example.id}.html" class="btn">Try Example</a>
</div>
`).join('')}
</div>
</main>
</div>
</body>
</html>`;
await fs.writeFile(path.join(this.config.outputPath, 'examples.html'), examplesHtml);
}
async generateGuidePages(guides) {
// Implementation for guide pages
const guidesHtml = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guides - Re-Shell Documentation</title>
<link rel="stylesheet" href="assets/styles.css">
</head>
<body>
<div id="app">
<main class="main">
<div class="container">
<h2>Comprehensive Guides</h2>
<p>Step-by-step guides to master Re-Shell.</p>
${guides.map(guide => `
<div class="guide-card">
<h3>${guide.title}</h3>
<p>${guide.description}</p>
<div class="guide-meta">
<span class="difficulty ${guide.difficulty}">${guide.difficulty}</span>
<span class="time">${guide.estimatedTime}</span>
</div>
<a href="guides/${guide.id}.html" class="btn">Re