refactor: 模块化重构 generator 和 runtime
This commit is contained in:
120
src/generator/template/engine.js
Normal file
120
src/generator/template/engine.js
Normal file
@@ -0,0 +1,120 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const Handlebars = require('handlebars');
|
||||
|
||||
const { registerAllHelpers } = require('../../helpers');
|
||||
|
||||
const handlebars = Handlebars.create();
|
||||
registerAllHelpers(handlebars);
|
||||
|
||||
function loadHandlebarsTemplates() {
|
||||
const templatesDir = path.join(process.cwd(), 'templates');
|
||||
|
||||
if (!fs.existsSync(templatesDir)) {
|
||||
throw new Error('Templates directory not found. Cannot proceed without templates.');
|
||||
}
|
||||
|
||||
const layoutsDir = path.join(templatesDir, 'layouts');
|
||||
if (!fs.existsSync(layoutsDir)) {
|
||||
throw new Error('Layouts directory not found. Cannot proceed without layout templates.');
|
||||
}
|
||||
|
||||
fs.readdirSync(layoutsDir)
|
||||
.filter((file) => file.endsWith('.hbs'))
|
||||
.sort()
|
||||
.forEach((file) => {
|
||||
const layoutName = path.basename(file, '.hbs');
|
||||
const layoutPath = path.join(layoutsDir, file);
|
||||
const layoutContent = fs.readFileSync(layoutPath, 'utf8');
|
||||
handlebars.registerPartial(layoutName, layoutContent);
|
||||
});
|
||||
|
||||
const componentsDir = path.join(templatesDir, 'components');
|
||||
if (!fs.existsSync(componentsDir)) {
|
||||
throw new Error('Components directory not found. Cannot proceed without component templates.');
|
||||
}
|
||||
|
||||
fs.readdirSync(componentsDir)
|
||||
.filter((file) => file.endsWith('.hbs'))
|
||||
.sort()
|
||||
.forEach((file) => {
|
||||
const componentName = path.basename(file, '.hbs');
|
||||
const componentPath = path.join(componentsDir, file);
|
||||
const componentContent = fs.readFileSync(componentPath, 'utf8');
|
||||
handlebars.registerPartial(componentName, componentContent);
|
||||
});
|
||||
|
||||
const defaultLayoutPath = path.join(layoutsDir, 'default.hbs');
|
||||
if (!fs.existsSync(defaultLayoutPath)) {
|
||||
throw new Error('Default layout template not found. Cannot proceed without default layout.');
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultLayoutTemplate() {
|
||||
const defaultLayoutPath = path.join(process.cwd(), 'templates', 'layouts', 'default.hbs');
|
||||
|
||||
if (!fs.existsSync(defaultLayoutPath)) {
|
||||
throw new Error('Default layout template not found. Cannot proceed without default layout.');
|
||||
}
|
||||
|
||||
try {
|
||||
const layoutContent = fs.readFileSync(defaultLayoutPath, 'utf8');
|
||||
const layoutTemplate = handlebars.compile(layoutContent);
|
||||
|
||||
return {
|
||||
path: defaultLayoutPath,
|
||||
template: layoutTemplate,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new Error(`Error loading default layout template: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function renderTemplate(templateName, data, useLayout = true) {
|
||||
const templatePath = path.join(process.cwd(), 'templates', 'pages', `${templateName}.hbs`);
|
||||
|
||||
if (!fs.existsSync(templatePath)) {
|
||||
const genericTemplatePath = path.join(process.cwd(), 'templates', 'pages', 'page.hbs');
|
||||
|
||||
if (!fs.existsSync(genericTemplatePath)) {
|
||||
throw new Error(
|
||||
`Template ${templateName}.hbs not found and generic template page.hbs not found. Cannot proceed without template.`
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`模板 ${templateName}.hbs 不存在,使用通用模板 page.hbs 代替`);
|
||||
const genericTemplateContent = fs.readFileSync(genericTemplatePath, 'utf8');
|
||||
const genericTemplate = handlebars.compile(genericTemplateContent);
|
||||
|
||||
const enhancedData = {
|
||||
...data,
|
||||
pageId: data && data.pageId ? data.pageId : templateName,
|
||||
};
|
||||
|
||||
const pageContent = genericTemplate(enhancedData);
|
||||
if (!useLayout) return pageContent;
|
||||
|
||||
const { template: layoutTemplate } = getDefaultLayoutTemplate();
|
||||
return layoutTemplate({ ...enhancedData, body: pageContent });
|
||||
}
|
||||
|
||||
try {
|
||||
const templateContent = fs.readFileSync(templatePath, 'utf8');
|
||||
const template = handlebars.compile(templateContent);
|
||||
|
||||
const pageContent = template(data);
|
||||
if (!useLayout) return pageContent;
|
||||
|
||||
const { template: layoutTemplate } = getDefaultLayoutTemplate();
|
||||
return layoutTemplate({ ...data, body: pageContent });
|
||||
} catch (error) {
|
||||
throw new Error(`Error rendering template ${templateName}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
handlebars,
|
||||
loadHandlebarsTemplates,
|
||||
getDefaultLayoutTemplate,
|
||||
renderTemplate,
|
||||
};
|
||||
Reference in New Issue
Block a user