UNPKG

@docfy/ember-vite

Version:

Vite plugin for Docfy Ember integration with @embroider/vite

124 lines (123 loc) 4.51 kB
import debugFactory from 'debug'; const debug = debugFactory('@docfy/ember-vite-plugin:process-demos'); /** * Process demo components and convert them to inline components */ export function processPageDemos(page) { debug('Processing page demos', { url: page.meta.url }); const inlineComponents = []; const imports = []; // Check if the page has demo components from the core plugins const pluginData = page.pluginData || {}; const pluginDemoComponents = (pluginData.demoComponents || []); if (Array.isArray(pluginDemoComponents) && pluginDemoComponents.length > 0) { pluginDemoComponents.forEach((demoComponent) => { if (demoComponent.name && demoComponent.chunks) { const component = convertDemoToInlineComponent(demoComponent); if (component) { inlineComponents.push(component); // Add any imports that the component might need if (component.imports) { imports.push(...component.imports); } } } }); } debug('Processed demos', { url: page.meta.url, demoCount: pluginDemoComponents.length, inlineComponentsCount: inlineComponents.length }); return { inlineComponents, imports }; } /** * Convert a demo component to an inline component */ function convertDemoToInlineComponent(demoComponent) { const { name, chunks } = demoComponent; // Find template and script chunks const templateChunk = chunks.find(chunk => chunk.ext === 'hbs' || chunk.ext === 'html' || chunk.type === 'template'); const scriptChunk = chunks.find(chunk => ['js', 'ts', 'gjs', 'gts'].includes(chunk.ext) || chunk.type === 'component'); if (!templateChunk) { debug('No template chunk found for demo component', { name: name.dashCase }); return null; } // Determine component type and generate appropriate inline component if (templateChunk && scriptChunk) { // Component has both template and logic return { name: name.pascalCase, type: 'class-based', template: templateChunk.code, script: scriptChunk.code, imports: extractImportsFromScript(scriptChunk.code) }; } else if (templateChunk) { // Template-only component return { name: name.pascalCase, type: 'const-template', template: templateChunk.code, imports: extractImportsFromTemplate(templateChunk.code) }; } return null; } /** * Extract imports from script code */ function extractImportsFromScript(script) { const imports = []; // Basic import extraction - this can be enhanced later const importRegex = /import\s+(?:(\w+)(?:\s*,\s*)?)?(?:\{([^}]+)\})?\s+from\s+['"]([^'"]+)['"]/g; let match; while ((match = importRegex.exec(script)) !== null) { const [, defaultImport, namedImports, path] = match; if (defaultImport) { imports.push({ type: 'other', name: defaultImport, path: path, isDefault: true }); } if (namedImports) { const names = namedImports.split(',').map(name => name.trim()); imports.push({ type: 'other', name: names[0], path: path, isDefault: false, namedImports: names }); } } return imports; } /** * Extract imports from template code (e.g., components used in template) */ function extractImportsFromTemplate(template) { const imports = []; // Extract component usage from template const componentRegex = /<([A-Z][a-zA-Z0-9]*)/g; let match; while ((match = componentRegex.exec(template)) !== null) { const componentName = match[1]; // Skip known HTML elements if (!['HTML', 'HEAD', 'BODY', 'DIV', 'SPAN', 'P', 'A', 'IMG', 'BR', 'HR'].includes(componentName)) { // Check if we already have this import if (!imports.find(imp => imp.name === componentName)) { imports.push({ type: 'component', name: componentName, path: `../${componentName.toLowerCase()}`, isDefault: true }); } } } return imports; }