This commit is contained in:
94
src/utils/templateUtils.ts
Normal file
94
src/utils/templateUtils.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import { Layout, Template, TemplateVariable } from '../models/types';
|
||||
|
||||
export class TemplateUtils {
|
||||
private readonly variablePattern = /\$\{([^}]+)\}/g;
|
||||
|
||||
extractVariables(template: Template): string[] {
|
||||
const variables: string[] = [];
|
||||
const layoutJson = JSON.stringify(template.layout);
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = this.variablePattern.exec(layoutJson)) !== null) {
|
||||
if (!variables.includes(match[1])) {
|
||||
variables.push(match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
substituteVariables(layout: Layout, variables: Record<string, string>): Layout {
|
||||
const layoutStr = JSON.stringify(layout);
|
||||
let substituted = layoutStr;
|
||||
|
||||
for (const [key, value] of Object.entries(variables)) {
|
||||
const patterns = [`\\$\\{${key}\\}`, `\\$\\{${key}:([^}]*)\\}`];
|
||||
for (const pattern of patterns) {
|
||||
substituted = substituted.replace(new RegExp(pattern, 'g'), value);
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.parse(substituted) as Layout;
|
||||
}
|
||||
|
||||
async createTemplateFromLayout(
|
||||
name: string,
|
||||
displayName: string,
|
||||
description: string,
|
||||
layout: Layout,
|
||||
variableDefaults?: Record<string, string>
|
||||
): Promise<Template> {
|
||||
const variables: TemplateVariable[] = [];
|
||||
const extractedVars = this.extractVariables({ name, displayName, description, variables: [], layout });
|
||||
|
||||
for (const varName of extractedVars) {
|
||||
const isRequired = !variableDefaults || !variableDefaults[varName];
|
||||
variables.push({
|
||||
name: varName,
|
||||
description: `Variable: ${varName}`,
|
||||
defaultValue: variableDefaults?.[varName],
|
||||
required: isRequired,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
displayName,
|
||||
description,
|
||||
variables,
|
||||
layout,
|
||||
};
|
||||
}
|
||||
|
||||
validateTemplateVariables(template: Template, providedVars: Record<string, string>): string[] {
|
||||
const missing: string[] = [];
|
||||
|
||||
for (const variable of template.variables) {
|
||||
if (variable.required && !(variable.name in providedVars) && !variable.defaultValue) {
|
||||
missing.push(variable.name);
|
||||
}
|
||||
}
|
||||
|
||||
return missing;
|
||||
}
|
||||
|
||||
async saveTemplate(template: Template, templatesDir: string): Promise<string> {
|
||||
const filePath = path.join(templatesDir, `${template.name}.json`);
|
||||
await fs.writeJson(filePath, template, { spaces: 2 });
|
||||
return filePath;
|
||||
}
|
||||
|
||||
async loadTemplate(filePath: string): Promise<Template> {
|
||||
const content = await fs.readFile(filePath, 'utf-8');
|
||||
return JSON.parse(content) as Template;
|
||||
}
|
||||
|
||||
generateTemplatePreview(template: Template, variables: Record<string, string>): string {
|
||||
const substitutedLayout = this.substituteVariables(template.layout, variables);
|
||||
return JSON.stringify(substitutedLayout, null, 2);
|
||||
}
|
||||
}
|
||||
|
||||
export const templateUtils = new TemplateUtils();
|
||||
Reference in New Issue
Block a user