UNPKG

willow-cli

Version:

CLI for installing Willow Design System components

106 lines (105 loc) 3.69 kB
import { readFile } from 'fs/promises'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Get the templates directory relative to this file const TEMPLATES_DIR = join(__dirname, '../../templates'); /** * Load a template file and optionally process it with context */ export async function loadTemplate(templatePath, context) { try { const fullPath = join(TEMPLATES_DIR, templatePath); let content = await readFile(fullPath, 'utf-8'); // Simple template variable replacement if context is provided if (context) { content = processTemplate(content, context); } return content; } catch (error) { throw new Error(`Failed to load template ${templatePath}: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Load multiple templates in parallel */ export async function loadTemplates(templatePaths, context) { const results = await Promise.all(templatePaths.map(async (path) => { const content = await loadTemplate(path, context); // Use filename as key (without extension) const key = path.split('/').pop()?.replace(/\.[^/.]+$/, '') || path; return [key, content]; })); return Object.fromEntries(results); } /** * Simple template variable replacement * Supports: * - {{variable}} - simple replacement * - {{#if condition}}...{{/if}} - conditional blocks * - {{#unless condition}}...{{/unless}} - negative conditional blocks */ function processTemplate(content, context) { // Replace simple variables content = content.replace(/\{\{(\w+)\}\}/g, (match, key) => { return context[key]?.toString() || match; }); // Handle conditional blocks content = content.replace(/\{\{#if\s+(\w+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (match, condition, block) => { return context[condition] ? block : ''; }); content = content.replace(/\{\{#unless\s+(\w+)\}\}([\s\S]*?)\{\{\/unless\}\}/g, (match, condition, block) => { return !context[condition] ? block : ''; }); return content; } /** * Get the appropriate template variant based on project type */ export function getTemplateVariant(baseName, projectType) { const variants = [ // Try specific variants first `${baseName}.${projectType.type}`, `${baseName}.${projectType.isOnlineIDE ? 'online' : 'local'}`, `${baseName}.${projectType.hasTypeScript ? 'ts' : 'js'}`, // Fallback to base baseName ]; return variants[0]; // For now, return the most specific. Later we can add file existence checks } /** * Load template with automatic variant selection */ export async function loadTemplateVariant(baseName, projectType, context) { const templatePath = getTemplateVariant(baseName, projectType); return loadTemplate(templatePath, context); } /** * Check if a template exists */ export async function templateExists(templatePath) { try { const fullPath = join(TEMPLATES_DIR, templatePath); await readFile(fullPath); return true; } catch { return false; } } /** * List available templates in a directory */ export async function listTemplates(subdirectory = '') { try { const { readdir } = await import('fs/promises'); const fullPath = join(TEMPLATES_DIR, subdirectory); const files = await readdir(fullPath); return files.filter(file => file.endsWith('.ts') || file.endsWith('.js') || file.endsWith('.css') || file.endsWith('.json')); } catch { return []; } }