@docfy/ember-vite
Version:
Vite plugin for Docfy Ember integration with @embroider/vite
108 lines (107 loc) • 4.2 kB
JavaScript
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 = {
'<': '<',
'>': '>',
'&': '&',
'"': '"',
''': "'",
'/': '/',
'<': '<',
'>': '>',
'&': '&'
};
return str.replace(/&[#\w]+;/g, (entity) => entities[entity] || entity);
}