UNPKG

kist

Version:

Package Pipeline Processor

125 lines (107 loc) 4.25 kB
// ============================================================================ // Imports // ============================================================================ import { mkdir, readFile, writeFile } from "fs/promises"; import { glob } from "glob"; import nunjucks from "nunjucks"; import path from "path"; import { Action } from "../../core/pipeline/Action"; import { ActionOptionsType } from "../../types/ActionOptionsType"; import nunjucksConfig from "./nunjucks.config.js"; // ============================================================================ // Classes // ============================================================================ export class TemplateRenderAction extends Action { async execute(options: ActionOptionsType): Promise<void> { const { templatesDir = "./templates", outputDir = "./dist", templates = [], context = {}, contextFiles = [], renderAllFromDir = false, customConfig = {}, } = options; const config = { ...nunjucksConfig, ...customConfig }; nunjucks.configure(templatesDir, config); // Load and merge all JSON context files const mergedContext = await this.mergeContextFiles( context, contextFiles, ); try { if (renderAllFromDir) { this.logInfo( `Auto-rendering all templates from ${templatesDir}...`, ); const templateFiles = await glob("**/*.jinja", { cwd: templatesDir, }); for (const templateRelPath of templateFiles) { const outputFile = path.join( outputDir, templateRelPath.replace(/\.jinja$/, ""), ); await this.renderTemplate( templateRelPath, outputFile, mergedContext, templatesDir, ); } } else { if (!Array.isArray(templates) || templates.length === 0) { throw new Error( "Option 'templates' must be provided if 'renderAllFromDir' is false.", ); } for (const { template, outputFile } of templates) { await this.renderTemplate( template, outputFile, mergedContext, templatesDir, ); } } this.logInfo("✓ All templates rendered successfully."); } catch (error) { this.logError("Error rendering templates.", error); throw error; } } private async renderTemplate( template: string, outputFile: string, context: Record<string, any>, templatesDir: string, ): Promise<void> { this.logInfo(`Rendering: ${template}${outputFile}`); const content = nunjucks.render(template, context); const dir = path.dirname(outputFile); await mkdir(dir, { recursive: true }); await writeFile(outputFile, content, "utf-8"); this.logInfo(`✓ Rendered: ${outputFile}`); } private async mergeContextFiles( baseContext: Record<string, any>, files: string[], ): Promise<Record<string, any>> { let merged = { ...baseContext }; for (const file of files) { try { const content = await readFile(file, "utf-8"); const parsed = JSON.parse(content); merged = { ...merged, ...parsed }; } catch (error) { this.logWarn(`Skipping context file due to error: ${file}`); this.logError("Context file parsing failed", error); } } return merged; } describe(): string { return "Renders one or many Nunjucks templates using a shared context or context files. Supports folder-wide auto-rendering."; } } export default TemplateRenderAction;