UNPKG

userface

Version:

Universal Data-Driven UI Engine with live data, validation, and multi-platform support

202 lines (201 loc) 7.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SpecGenerator = void 0; class SpecGenerator { /** * Генерирует JSON-спеку компонента на основе AST анализа */ generateSpecFromAnalysis(analysis) { const variants = []; // Генерируем варианты для каждого типа пропса const variantProps = this.generateVariantsForProps(analysis.props); // Создаем комбинации вариантов const combinations = this.generateCombinations(variantProps); // Преобразуем в варианты компонента combinations.forEach((combo, index) => { variants.push({ name: `variant-${index + 1}`, description: this.generateVariantDescription(combo), props: combo }); }); // Добавляем дефолтный вариант const defaultProps = this.generateDefaultProps(analysis.props); variants.unshift({ name: 'default', description: 'Default variant with basic props', props: defaultProps }); return { name: analysis.name, description: analysis.description || `Component ${analysis.name}`, variants, defaultVariant: 'default' }; } /** * Генерирует варианты для каждого пропа на основе его типа */ generateVariantsForProps(props) { const variants = {}; props.forEach(prop => { if (prop.required) { // Для обязательных пропсов создаем базовые значения variants[prop.name] = [this.generateValueForType(prop.type, prop.description)]; } else { // Для опциональных создаем несколько вариантов variants[prop.name] = this.generateValuesForType(prop.type, prop.description); } }); return variants; } /** * Генерирует значение для конкретного типа */ generateValueForType(type, description) { // Сначала проверяем union types в самом типе const unionValues = this.extractUnionValues(type); if (unionValues.length > 0) { return unionValues[0]; // Возвращаем первое значение из union } // Затем проверяем union types в описании const descUnionValue = this.extractTextValue(description); if (descUnionValue) { return descUnionValue; } // Если union types не найдены, используем стандартные значения switch (type) { case 'text': case 'string': return 'Sample Text'; case 'boolean': return true; case 'number': return 42; case 'array': return []; case 'function': return () => { }; default: return null; } } /** * Генерирует несколько значений для типа */ generateValuesForType(type, description) { // Сначала проверяем union types в самом типе const unionValues = this.extractUnionValues(type); if (unionValues.length > 0) { return unionValues; } // Затем проверяем union types в описании const descUnionValues = this.extractTextValues(description); if (descUnionValues.length > 0) { return descUnionValues; } // Если union types не найдены, используем стандартные значения switch (type) { case 'text': case 'string': return ['Sample Text', 'Another Text']; case 'boolean': return [true, false]; case 'number': return [0, 42, 100]; case 'array': return [[], [1, 2, 3]]; case 'function': return [() => { }, () => console.log('clicked')]; default: return [null]; } } /** * Извлекает возможные значения из union types в типе (например: 'primary' | 'secondary') */ extractUnionValues(type) { // Ищем union types в формате 'value1' | 'value2' | 'value3' const unionMatch = type.match(/'([^']+)'(?:\s*\|\s*'([^']+)')*/g); if (unionMatch) { return unionMatch.map(match => match.replace(/'/g, '')); } // Ищем union types в формате "value1" | "value2" | "value3" const unionMatchDouble = type.match(/"([^"]+)"(?:\s*\|\s*"([^"]+)")*/g); if (unionMatchDouble) { return unionMatchDouble.map(match => match.replace(/"/g, '')); } // Ищем union types без кавычек (например: primary | secondary) const unionMatchNoQuotes = type.match(/(\w+)(?:\s*\|\s*(\w+))*/g); if (unionMatchNoQuotes && unionMatchNoQuotes.length > 1) { return unionMatchNoQuotes; } return []; } /** * Извлекает возможные значения из union types в описании (например: 'primary' | 'secondary') */ extractTextValues(description) { const unionMatch = description.match(/'([^']+)'(?:\s*\|\s*'([^']+)')*/g); if (unionMatch) { return unionMatch.map(match => match.replace(/'/g, '')); } return []; } /** * Извлекает одно значение из union type */ extractTextValue(description) { const values = this.extractTextValues(description); return values.length > 0 ? values[0] : null; } /** * Генерирует все возможные комбинации вариантов пропсов */ generateCombinations(variantProps) { const keys = Object.keys(variantProps); if (keys.length === 0) return [{}]; const combinations = []; const generateCombos = (index, current) => { if (index === keys.length) { combinations.push({ ...current }); return; } const key = keys[index]; const values = variantProps[key]; values.forEach(value => { current[key] = value; generateCombos(index + 1, current); }); }; generateCombos(0, {}); return combinations; } /** * Генерирует дефолтные пропсы */ generateDefaultProps(props) { const defaultProps = {}; props.forEach(prop => { if (prop.required) { defaultProps[prop.name] = this.generateValueForType(prop.type, prop.description); } }); return defaultProps; } /** * Генерирует описание варианта */ generateVariantDescription(props) { const descriptions = []; Object.entries(props).forEach(([key, value]) => { if (value !== null && value !== undefined) { descriptions.push(`${key}: ${String(value)}`); } }); return descriptions.length > 0 ? descriptions.join(', ') : 'Custom variant'; } } exports.SpecGenerator = SpecGenerator;