UNPKG

dynamate-design-to-code

Version:

A powerful tool for converting Figma designs into high-quality, production-ready code with built-in best practices and customizable rulesets

135 lines (133 loc) 5.35 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CodeGenerator = void 0; const openai_1 = __importDefault(require("openai")); class CodeGenerator { constructor(config) { this.openai = new openai_1.default({ apiKey: config.openaiApiKey }); this.model = config.model || 'gpt-4'; this.temperature = config.temperature || 0.7; this.framework = config.framework || 'react'; this.styling = config.styling || 'tailwind'; this.features = { typescript: config.features?.typescript ?? true, storybook: config.features?.storybook ?? false, tests: config.features?.tests ?? false, accessibility: config.features?.accessibility ?? true }; } async generateComponent(component) { try { const prompt = this.buildPrompt(component); const response = await this.openai.chat.completions.create({ model: this.model, messages: [ { role: 'system', content: this.getSystemPrompt() }, { role: 'user', content: prompt } ], temperature: this.temperature }); const generatedCode = response.choices[0]?.message?.content || ''; return this.parseGeneratedCode(generatedCode); } catch (error) { throw error; } } getSystemPrompt() { return `You are a professional front-end developer. Generate clean, semantic ${this.framework} components with ${this.features.typescript ? 'TypeScript' : 'JavaScript'} and modern best practices. Focus on: - Semantic HTML and accessibility - Clean, maintainable code structure - ${this.styling === 'tailwind' ? 'Efficient Tailwind utilities' : 'Clean, modular styles'} - Proper component organization - Type safety and documentation - Responsive design patterns`; } buildPrompt(component) { const features = []; if (this.features.typescript) features.push('TypeScript types/interfaces'); if (this.features.storybook) features.push('Storybook stories'); if (this.features.tests) features.push('Unit tests'); if (this.features.accessibility) features.push('Accessibility features (ARIA attributes, keyboard navigation)'); return `Generate a ${this.framework} component for the following Figma component: Name: ${component.name} Type: ${component.type} Structure: ${JSON.stringify(component, null, 2)} Please include: ${features.map(f => `- ${f}`).join('\n')} - Proper component structure - ${this.styling === 'tailwind' ? 'Tailwind CSS classes' : 'CSS styles'} - Any necessary imports - Component documentation - Props validation - Error boundaries - Loading states - Interactive states (hover, focus, active) Return the code in markdown code blocks: - Component: \`\`\`${this.features.typescript ? 'tsx' : 'jsx'}\`\`\` - Styles: \`\`\`${this.styling}\`\`\` ${this.features.storybook ? '- Stories: \`\`\`tsx\`\`\`' : ''} ${this.features.tests ? '- Tests: \`\`\`tsx\`\`\`' : ''} - Types: \`\`\`typescript\`\`\` - Documentation: \`\`\`markdown\`\`\``; } parseGeneratedCode(rawCode) { const result = { code: '', styles: '', dependencies: [], types: '', stories: '', tests: '', documentation: '' }; // Extract code blocks using consistent language identifiers const codeMatch = rawCode.match(/```(?:tsx?|jsx)\n([\s\S]*?)```/); const stylesMatch = rawCode.match(/```(?:css|tailwind|scss|styled-components)\n([\s\S]*?)```/); const storiesMatch = rawCode.match(/```tsx\n([\s\S]*?)```/); const testsMatch = rawCode.match(/```tsx\n([\s\S]*?)```/); const typesMatch = rawCode.match(/```typescript\n([\s\S]*?)```/); const docsMatch = rawCode.match(/```markdown\n([\s\S]*?)```/); if (codeMatch) { result.code = codeMatch[1].trim(); result.dependencies = this.extractDependencies(result.code); } if (stylesMatch) result.styles = stylesMatch[1].trim(); if (storiesMatch) result.stories = storiesMatch[1].trim(); if (testsMatch) result.tests = testsMatch[1].trim(); if (typesMatch) result.types = typesMatch[1].trim(); if (docsMatch) result.documentation = docsMatch[1].trim(); return result; } extractDependencies(code) { const importRegex = /import\s+?(?:(?:(?:[\w*\s{},]*)\s+from\s+?)|)(?:(?:".*?")|(?:'.*?'))[\s]*?(?:;|$|)/g; const matches = code.match(importRegex) || []; return matches.map(match => { const moduleMatch = match.match(/from\s+['"]([^'"]+)['"]/); return moduleMatch ? moduleMatch[1] : ''; }).filter(Boolean); } } exports.CodeGenerator = CodeGenerator; //# sourceMappingURL=generator.js.map