UNPKG

@docfy/ember-vite

Version:

Vite plugin for Docfy Ember integration with @embroider/vite

108 lines (107 loc) 4.2 kB
import debugFactory from 'debug'; const debug = debugFactory('@docfy/ember-vite-plugin:process-preview-templates'); /** * Process preview-template blocks and convert them to inline components */ export function processPreviewTemplates(page) { debug('Processing preview templates', { url: page.meta.url }); const inlineComponents = []; const imports = []; let updatedContent = page.rendered || ''; // Find preview-template code blocks const previewTemplateRegex = /<pre><code class="language-hbs">([^<]*)<\/code><\/pre>/g; const previewTemplateMatches = []; let match; // First pass: find all preview template blocks while ((match = previewTemplateRegex.exec(updatedContent)) !== null) { const templateCode = match[1]; // Check if this is a preview template (look for preceding context) const beforeMatch = updatedContent.substring(0, match.index); if (beforeMatch.includes('preview-template')) { previewTemplateMatches.push({ fullMatch: match[0], templateCode: templateCode, index: match.index }); } } // Process each preview template previewTemplateMatches.forEach((previewMatch, index) => { const componentName = `PreviewTemplate${index + 1}`; // Decode HTML entities for processing const decodedTemplate = decodeHTMLEntities(previewMatch.templateCode); // Create inline component const inlineComponent = { name: componentName, type: 'const-template', template: decodedTemplate, imports: extractImportsFromTemplate(decodedTemplate) }; inlineComponents.push(inlineComponent); // Add component imports if (inlineComponent.imports) { imports.push(...inlineComponent.imports); } // Replace the preview template block with component usage updatedContent = updatedContent.replace(previewMatch.fullMatch, `<${componentName} />`); }); debug('Processed preview templates', { url: page.meta.url, previewTemplateCount: previewTemplateMatches.length, inlineComponentsCount: inlineComponents.length }); // Only return updated content if we actually made modifications const finalContent = previewTemplateMatches.length > 0 ? updatedContent : ''; return { inlineComponents, imports, updatedContent: finalContent }; } /** * 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)) { // Generate proper import path for known components let importPath; if (componentName === 'DocfyLink') { importPath = 'test-app-vite/components/docfy-link'; } else { // For other components, use the generic relative path importPath = `../components/${componentName.toLowerCase()}`; } imports.push({ type: 'component', name: componentName, path: importPath, isDefault: true }); } } } return imports; } /** * Decode HTML entities in template code */ function decodeHTMLEntities(str) { const entities = { '&lt;': '<', '&gt;': '>', '&amp;': '&', '&quot;': '"', '&#x27;': "'", '&#x2F;': '/', '&#x3C;': '<', '&#x3E;': '>', '&#x26;': '&' }; return str.replace(/&[#\w]+;/g, (entity) => entities[entity] || entity); }