UNPKG

@vibe-dev-kit/cli

Version:

Advanced Command-line toolkit that analyzes your codebase and deploys project-aware rules, memories, commands and agents to any AI coding assistant - VDK is the world's first Vibe Development Kit

195 lines (169 loc) 6.66 kB
/** * Light Templating Utility * ------------------------ * Provides simple, fast string interpolation as an alternative to Handlebars. * Uses ${variable} syntax for project-specific customization of rules. * * Benefits over Handlebars: * - 10x faster performance (no compilation step) * - Simple syntax, no complex logic * - Compatible with existing remote .mdc rules * - No dependency on external templating libraries */ /** * Applies light templating to content using ${variable} syntax * @param {string} content - Content to template * @param {Object} variables - Variables to substitute * @returns {string} Templated content */ export function applyLightTemplating(content, variables = {}) { if (!content || typeof content !== 'string') { return content; } // Simple string replacement for ${variable} patterns return content.replace(/\$\{([^}]+)\}/g, (match, variableName) => { const value = getNestedValue(variables, variableName.trim()); return value !== undefined ? value : match; // Keep original if not found }); } /** * Gets nested object values using dot notation (e.g., 'project.name') * @param {Object} obj - Object to search * @param {string} path - Dot notation path * @returns {*} Value or undefined */ function getNestedValue(obj, path) { return path.split('.').reduce((current, key) => { return current && current[key] !== undefined ? current[key] : undefined; }, obj); } /** * Prepares common template variables from analysis data * @param {Object} analysisData - Analysis data from project scanning * @returns {Object} Template variables */ export function prepareTemplateVariables(analysisData) { const projectStructure = analysisData.projectStructure || {}; const techData = analysisData.technologyData || {}; const patterns = analysisData.patterns || {}; return { // Project basics projectName: getProjectName(projectStructure), projectPath: projectStructure.root || process.cwd(), projectType: determineProjectType(techData), // Technology stack primaryLanguage: techData.primaryLanguage || 'Unknown', languages: techData.languages || [], frameworks: techData.frameworks || [], libraries: techData.libraries || [], // Architecture patterns architecturalPattern: patterns.architecturalPatterns?.[0]?.name || 'Unknown', patterns: patterns.architecturalPatterns || [], // Project structure hasTests: hasTestDirectory(projectStructure), hasComponents: hasComponentsDirectory(projectStructure), hasDocs: hasDocsDirectory(projectStructure), // Version info version: getProjectVersion(techData), nodeVersion: techData.nodeVersion, // Common paths srcPath: findSourceDirectory(projectStructure), testPath: findTestDirectory(projectStructure), docsPath: findDocsDirectory(projectStructure), // Utilities for templates join: (array, separator = ', ') => (Array.isArray(array) ? array.join(separator) : ''), capitalize: (str) => (str ? str.charAt(0).toUpperCase() + str.slice(1) : ''), lowercase: (str) => (str ? str.toLowerCase() : ''), }; } /** * Helper functions for template variable preparation */ function getProjectName(projectStructure) { // Try to get from package.json, fallback to directory name const packageJson = projectStructure.packageJson; if (packageJson && packageJson.name) { return packageJson.name; } const root = projectStructure.root || process.cwd(); return root.split('/').pop() || 'UnknownProject'; } function determineProjectType(techData) { const frameworks = techData.frameworks || []; const libraries = techData.libraries || []; if (frameworks.includes('React') || libraries.includes('react')) return 'React App'; if (frameworks.includes('Vue') || libraries.includes('vue')) return 'Vue App'; if (frameworks.includes('Angular') || libraries.includes('@angular/core')) return 'Angular App'; if (frameworks.includes('Next.js') || libraries.includes('next')) return 'Next.js App'; if (frameworks.includes('Express') || libraries.includes('express')) return 'Express API'; if (frameworks.includes('Django')) return 'Django App'; if (frameworks.includes('Rails')) return 'Rails App'; return 'Application'; } function hasTestDirectory(projectStructure) { const directories = projectStructure.directories || []; return directories.some((dir) => /^(test|tests|__tests__|spec|specs)$/i.test(dir.name)); } function hasComponentsDirectory(projectStructure) { const directories = projectStructure.directories || []; return directories.some( (dir) => /^(components|component)$/i.test(dir.name) || dir.path.includes('/components/') ); } function hasDocsDirectory(projectStructure) { const directories = projectStructure.directories || []; return directories.some((dir) => /^(docs|doc|documentation)$/i.test(dir.name)); } function getProjectVersion(techData) { const packageJson = techData.packageJson; return packageJson && packageJson.version ? packageJson.version : '1.0.0'; } function findSourceDirectory(projectStructure) { const directories = projectStructure.directories || []; const srcDir = directories.find((dir) => /^(src|source|lib|app)$/i.test(dir.name)); return srcDir ? srcDir.path : './src'; } function findTestDirectory(projectStructure) { const directories = projectStructure.directories || []; const testDir = directories.find((dir) => /^(test|tests|__tests__|spec|specs)$/i.test(dir.name)); return testDir ? testDir.path : './test'; } function findDocsDirectory(projectStructure) { const directories = projectStructure.directories || []; const docsDir = directories.find((dir) => /^(docs|doc|documentation)$/i.test(dir.name)); return docsDir ? docsDir.path : './docs'; } /** * Template helper functions for processing template variables */ export const templateHelpers = { capitalize: (str) => (str ? str.charAt(0).toUpperCase() + str.slice(1) : ''), lowercase: (str) => (str ? str.toLowerCase() : ''), join: (array, separator = ', ') => (Array.isArray(array) ? array.join(separator) : ''), ifCond: (v1, operator, v2) => { switch (operator) { case '==': return v1 == v2; case '===': return v1 === v2; case '!=': return v1 != v2; case '!==': return v1 !== v2; case '<': return v1 < v2; case '<=': return v1 <= v2; case '>': return v1 > v2; case '>=': return v1 >= v2; case '&&': return v1 && v2; case '||': return v1 || v2; default: return false; } }, };