UNPKG

@bernierllc/email-template-engine

Version:

Email template processing engine with compilation, rendering, and text generation

75 lines (67 loc) 2.34 kB
/* Copyright (c) 2025 Bernier LLC This file is licensed to the client under a limited-use license. The client may use and modify this code *only within the scope of the project it was delivered for*. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC. */ /** * Check if template has balanced braces */ export function checkBalancedBraces(template: string): { balanced: boolean; position?: number } { let count = 0; for (let i = 0; i < template.length; i++) { if (template[i] === '{' && template[i + 1] === '{') { count++; i++; // Skip next brace } else if (template[i] === '}' && template[i + 1] === '}') { count--; i++; // Skip next brace if (count < 0) { return { balanced: false, position: i }; } } } return { balanced: count === 0, position: count !== 0 ? template.length : undefined }; } /** * Check for unclosed block helpers */ export function checkUnclosedBlocks(template: string): string[] { const unclosed: string[] = []; const blockStack: string[] = []; const blockRegex = /\{\{#(\w+).*?\}\}|\{\{\/(\w+)\}\}/g; let match; while ((match = blockRegex.exec(template)) !== null) { if (match[1]) { // Opening block blockStack.push(match[1]); } else if (match[2]) { // Closing block const last = blockStack.pop(); if (last !== match[2]) { unclosed.push(match[2]); } } } // Any remaining blocks are unclosed return [...unclosed, ...blockStack]; } /** * Check if a variable name is a built-in Handlebars helper */ export function isBuiltInHelper(variable: string): boolean { const builtIns = ['if', 'unless', 'each', 'with', 'log', 'lookup', 'else']; const firstWord = variable.split(/[\s.]/)[0]; return builtIns.includes(firstWord); } /** * Infer variable type from path */ export function inferVariableType(path: string): 'string' | 'number' | 'boolean' | 'object' | 'array' { // Simple heuristic based on variable name if (path.includes('.length') || path.includes('.count')) return 'number'; if (path.includes('.is') || path.includes('.has')) return 'boolean'; if (path.includes('.items') || path.includes('.list')) return 'array'; if (path.includes('.')) return 'object'; return 'string'; }