@aetherframework/template-engine 1.0.2 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Basic Usage Example - Demonstrates template rendering with enhanced syntax support
3
+ * This example shows how to use the TemplateEngineFactory to create and use renderers
4
+ */
5
+
6
+ // Import the factory function from the main index file
7
+ import { createEngine } from '../index.js';
8
+ import fs from 'fs/promises';
9
+ import path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ // Helper function to get current directory in ES Module environment
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ /**
17
+ * Main function to run the basic usage example
18
+ * Demonstrates template rendering with Aether template engine using factory pattern
19
+ */
20
+ async function run() {
21
+ console.log('šŸš€ Starting Basic Usage Example with Enhanced Syntax...\n');
22
+
23
+ try {
24
+ // 1ļøāƒ£ Initialize Engine using Factory Pattern
25
+ console.log('1ļøāƒ£ Initializing Engine with Factory Pattern...');
26
+
27
+ // Create engine factory with template mode configuration
28
+ const factory = await createEngine({
29
+ mode: 'template', // Set rendering mode: 'template' or 'ssr'
30
+ cacheEnabled: true, // Enable template compilation caching for better performance
31
+ debug: true, // Enable debug mode to see compilation details
32
+ templateDir: path.join(__dirname, '../dist') // Optional: specify default template directory
33
+ });
34
+
35
+ console.log('āœ… Engine factory initialized successfully\n');
36
+
37
+ // 2ļøāƒ£ Create Renderer from Factory
38
+ console.log('2ļøāƒ£ Creating Template Renderer...');
39
+
40
+ // Create a renderer instance using the factory
41
+ // The 'aether' engine name refers to the default Aether template engine
42
+ const renderer = factory.createRenderer('aether');
43
+ console.log('āœ… Template renderer created successfully\n');
44
+
45
+ // 3ļøāƒ£ Define Template String with Aether Syntax
46
+ // Aether template engine uses Blade-like syntax with {{ }} for variables and @ directives for control structures
47
+ const template = `
48
+ <header class="header">
49
+ <nav class="navbar">
50
+ <div class="container">
51
+ <a class="navbar-brand" href="{{ route('home') }}">
52
+ <img src="{{ asset('images/logo.png') }}" alt="Logo" height="40">
53
+ </a>
54
+
55
+ <ul class="navbar-nav">
56
+ <li class="nav-item">
57
+ <a class="nav-link" href="{{ route('home') }}">Home</a>
58
+ </li>
59
+ <li class="nav-item">
60
+ <a class="nav-link" href="{{ route('about') }}">About</a>
61
+ </li>
62
+
63
+ @if(auth().check())
64
+ <li class="nav-item dropdown">
65
+ <a class="nav-link dropdown-toggle" href="#" role="button">
66
+ {{ auth().user.name }}
67
+ </a>
68
+ <div class="dropdown-menu">
69
+ <a class="dropdown-item" href="{{ route('profile') }}">Profile</a>
70
+ <a class="dropdown-item" href="{{ route('logout') }}">Logout</a>
71
+ </div>
72
+ </li>
73
+ @else
74
+ <li class="nav-item">
75
+ <a class="nav-link" href="{{ route('login') }}">Login</a>
76
+ </li>
77
+ <li class="nav-item">
78
+ <a class="nav-link" href="{{ route('register') }}">Register</a>
79
+ </li>
80
+ @endif
81
+ </ul>
82
+ </div>
83
+ </nav>
84
+ </header>`;
85
+
86
+ // 4ļøāƒ£ Define Template Data and Helper Functions
87
+ // These functions will be available in the template context during rendering
88
+ const data = {
89
+ // Mock authentication function - simulates user authentication state
90
+ auth: () => ({
91
+ check: () => true, // Change to false to test the @else block
92
+ user: {
93
+ name: 'John Doe',
94
+ email: 'john.doe@example.com',
95
+ role: 'admin'
96
+ }
97
+ }),
98
+
99
+ // Mock route function - generates URLs for named routes
100
+ route: (name) => {
101
+ const routes = {
102
+ 'home': '/',
103
+ 'about': '/about',
104
+ 'login': '/login',
105
+ 'register': '/register',
106
+ 'profile': '/profile',
107
+ 'logout': '/logout'
108
+ };
109
+ return routes[name] || '#';
110
+ },
111
+
112
+ // Mock asset function - generates URLs for static assets
113
+ asset: (filePath) => `/assets/${filePath}`,
114
+
115
+ // Additional template data can be added here
116
+ siteName: 'Aether Template Demo',
117
+ currentYear: new Date().getFullYear()
118
+ };
119
+
120
+ // 5ļøāƒ£ Render Template with Provided Data
121
+ console.log('3ļøāƒ£ Rendering Template with Enhanced Syntax...');
122
+ try {
123
+ // Use the renderer to process template with data
124
+ // The render method compiles the template and executes it with the provided context
125
+ const result = await renderer.render(template, data);
126
+
127
+ console.log('\n--- Rendered Output ---');
128
+ console.log(result);
129
+ console.log('-----------------------\n');
130
+
131
+ // 6ļøāƒ£ Save Rendered Output to File
132
+ console.log('4ļøāƒ£ Saving rendered output to file...');
133
+ const outputDir = path.join(__dirname, 'dist');
134
+
135
+ // Create output directory if it doesn't exist
136
+ try {
137
+ await fs.access(outputDir);
138
+ console.log('šŸ“ Output directory already exists');
139
+ } catch {
140
+ await fs.mkdir(outputDir, { recursive: true });
141
+ console.log('šŸ“ Created output directory');
142
+ }
143
+
144
+ // Define output file path and write the rendered HTML
145
+ const outputPath = path.join(outputDir, 'basic-usage-result.html');
146
+ await fs.writeFile(outputPath, result, 'utf-8');
147
+
148
+ console.log(`šŸ’¾ HTML file saved to: ${outputPath}`);
149
+ console.log(`šŸ“„ File size: ${result.length} characters`);
150
+
151
+ } catch (error) {
152
+ // Enhanced error handling with detailed information
153
+ console.error('āŒ Error during template rendering:');
154
+ console.error(` Message: ${error.message}`);
155
+ console.error(` Stack: ${error.stack}`);
156
+
157
+ // Provide helpful debugging information
158
+ console.error('\nšŸ”§ Debugging Tips:');
159
+ console.error(' 1. Check template syntax for errors');
160
+ console.error(' 2. Verify all template functions are defined in data');
161
+ console.error(' 3. Ensure template uses correct Aether syntax');
162
+ }
163
+
164
+ // 7ļøāƒ£ Display Engine Statistics and Configuration
165
+ console.log('\nšŸ“Š Engine Factory Statistics:');
166
+ const stats = factory.getStats();
167
+ console.log(JSON.stringify(stats, null, 2));
168
+
169
+ // Additional debug information
170
+ console.log('\nšŸ”§ Configuration Details:');
171
+ console.log(` - Mode: ${stats.mode}`);
172
+ console.log(` - Cache Enabled: ${stats.cacheEnabled}`);
173
+ console.log(` - Cache Size: ${stats.cacheSize}`);
174
+ console.log(` - Available Engines: ${stats.engines.join(', ')}`);
175
+ console.log(` - Template Directory: ${stats.templateDir || 'Not specified'}`);
176
+
177
+ // 8ļøāƒ£ Demonstrate Additional Factory Features
178
+ console.log('\nšŸŽÆ Additional Factory Features:');
179
+
180
+ // List all available engines
181
+ const availableEngines = factory.listEngines();
182
+ console.log(` Available engines: ${availableEngines.join(', ')}`);
183
+
184
+ // Show cache information if enabled
185
+ if (stats.cacheEnabled) {
186
+ console.log(` Cache TTL: ${stats.cacheTTL}ms`);
187
+ }
188
+
189
+ // Demonstrate engine switching capability
190
+ console.log('\nšŸ”„ Engine Switching Demo:');
191
+ console.log(' The factory pattern allows easy switching between different engines:');
192
+ console.log(' - Use createRenderer(\'aether\') for standard template rendering');
193
+ console.log(' - Use createRenderer(\'ssr-mode\') for server-side rendering');
194
+ console.log(' - Use createRenderer(\'template-mode\') for basic template mode');
195
+
196
+ } catch (error) {
197
+ // Handle initialization errors
198
+ console.error('āŒ Error during engine initialization:');
199
+ console.error(` Message: ${error.message}`);
200
+ console.error(` Stack: ${error.stack}`);
201
+
202
+ console.error('\nšŸ”§ Troubleshooting:');
203
+ console.error(' 1. Check that all required modules are installed');
204
+ console.error(' 2. Verify the index.js file exports createEngine correctly');
205
+ console.error(' 3. Ensure the engine modules are in the correct location');
206
+ }
207
+ }
208
+
209
+ // Execute the main function with error handling
210
+ run().catch(error => {
211
+ console.error('šŸ’„ Unhandled error in main execution:');
212
+ console.error(error);
213
+ process.exit(1);
214
+ });
215
+
216
+ // Export the run function for potential module usage
217
+ export { run };
@@ -0,0 +1,404 @@
1
+ /**
2
+ * Layout Example - Demonstrates template inheritance using @extends and @section
3
+ * This example shows how to use template layouts and inheritance with Aether template engine
4
+ * Uses the same factory pattern as ssr-example.js and basic-usage.js for consistency
5
+ */
6
+
7
+ import { createEngine } from '../index.js';
8
+ import fs from 'fs/promises';
9
+ import path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ // Helper function to get current directory in ES Module environment
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
15
+
16
+ /**
17
+ * Main function to run layout example
18
+ * Demonstrates template inheritance using @extends and @section directives
19
+ * @returns {Promise<void>}
20
+ */
21
+ async function runLayoutExample() {
22
+ console.log('šŸš€ Starting Layout Example...\n');
23
+
24
+ try {
25
+ // 1ļøāƒ£ Initialize Engine using Factory Pattern
26
+ console.log('1ļøāƒ£ Initializing Engine with Factory Pattern...');
27
+
28
+ // Create engine factory with template mode configuration
29
+ const factory = await createEngine({
30
+ mode: 'template', // Use template mode for layout rendering
31
+ cacheEnabled: true, // Enable caching for better performance
32
+ debug: true, // Enable debug logging to see compilation details
33
+ templateDir: path.join(__dirname, './dist/templates') // Set template directory
34
+ });
35
+
36
+ console.log('āœ… Engine factory initialized successfully\n');
37
+
38
+ // 2ļøāƒ£ Create Renderer from Factory
39
+ console.log('2ļøāƒ£ Creating Template Renderer...');
40
+
41
+ // Create a renderer instance using the factory
42
+ // The 'aether' engine name refers to the default Aether template engine
43
+ const renderer = factory.createRenderer('aether');
44
+ console.log('āœ… Template renderer created successfully\n');
45
+
46
+ // 3ļøāƒ£ Setup Template Directory Structure
47
+ console.log('3ļøāƒ£ Setting up template directories...');
48
+
49
+ // Create necessary directories for templates
50
+ const layoutsDir = path.join(__dirname, './dist/templates/layouts');
51
+ const pagesDir = path.join(__dirname, './dist/templates/pages');
52
+ const distDir = path.join(__dirname, './dist');
53
+
54
+ // Create directories if they don't exist
55
+ await fs.mkdir(layoutsDir, { recursive: true });
56
+ await fs.mkdir(pagesDir, { recursive: true });
57
+ await fs.mkdir(distDir, { recursive: true });
58
+
59
+ console.log('šŸ“ Directory structure created');
60
+ console.log(` - Layouts: ${layoutsDir}`);
61
+ console.log(` - Pages: ${pagesDir}`);
62
+ console.log(` - Output: ${distDir}\n`);
63
+
64
+ // 4ļøāƒ£ Create Main Layout Template
65
+ console.log('4ļøāƒ£ Creating Main Layout Template...');
66
+
67
+ // Define the main layout template with @yield directives
68
+ // @yield directives define sections that child templates can fill
69
+ const layoutContent = `<!DOCTYPE html>
70
+ <html lang="zh-CN">
71
+ <head>
72
+ <meta charset="UTF-8">
73
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
74
+ <title>@yield('title', 'Aether Framework')</title>
75
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
76
+ <script src="https://cdn.tailwindcss.com"></script>
77
+ @yield('head')
78
+ </head>
79
+ <body class="bg-gray-900 text-white">
80
+ <!-- Header Section -->
81
+ <header class="bg-gray-800 shadow-lg">
82
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
83
+ <div class="flex justify-between h-16">
84
+ <div class="flex items-center">
85
+ <span class="text-xl font-bold text-indigo-400">Aether<span class="text-white">Framework</span></span>
86
+ </div>
87
+ <nav class="flex items-center space-x-4">
88
+ <a href="/" class="text-gray-300 hover:text-white transition-colors duration-200">Home</a>
89
+ <a href="/about" class="text-gray-300 hover:text-white transition-colors duration-200">About</a>
90
+ <a href="/docs" class="text-gray-300 hover:text-white transition-colors duration-200">Documentation</a>
91
+ </nav>
92
+ </div>
93
+ </div>
94
+ </header>
95
+
96
+ <!-- Main Content Section -->
97
+ <main class="py-8">
98
+ @yield('content')
99
+ </main>
100
+
101
+ <!-- Footer Section -->
102
+ <footer class="bg-gray-800 border-t border-gray-700 mt-12">
103
+ <div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
104
+ <div class="flex justify-between items-center">
105
+ <p class="text-sm text-gray-400">
106
+ &copy; {{ currentYear }} Aether Template Engine. All rights reserved.
107
+ </p>
108
+ <div class="flex space-x-4">
109
+ <a href="#" class="text-gray-400 hover:text-white">
110
+ <i class="fab fa-github"></i>
111
+ </a>
112
+ <a href="#" class="text-gray-400 hover:text-white">
113
+ <i class="fab fa-twitter"></i>
114
+ </a>
115
+ <a href="#" class="text-gray-400 hover:text-white">
116
+ <i class="fab fa-discord"></i>
117
+ </a>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </footer>
122
+
123
+ <!-- Scripts Section -->
124
+ @yield('scripts')
125
+ </body>
126
+ </html>`;
127
+
128
+ // Save layout template to file
129
+ const layoutPath = path.join(layoutsDir, 'main.aether');
130
+ await fs.writeFile(layoutPath, layoutContent, 'utf-8');
131
+ console.log(`āœ… Layout template saved to: ${layoutPath}\n`);
132
+
133
+ // 5ļøāƒ£ Create Child Template with @extends and @section
134
+ console.log('5ļøāƒ£ Creating Child Template with Layout Inheritance...');
135
+
136
+ // Define child template that extends the main layout
137
+ // IMPORTANT: Use Aether/Blade syntax (@foreach), NOT Handlebars syntax ({{#each}})
138
+ const childTemplate = `@extends('layouts/main')
139
+
140
+ @section('title', 'Home Page - Aether Framework')
141
+
142
+ @section('head')
143
+ <style>
144
+ body {
145
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
146
+ line-height: 1.6;
147
+ }
148
+ .feature-grid {
149
+ display: grid;
150
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
151
+ gap: 2rem;
152
+ margin-top: 2rem;
153
+ }
154
+ .feature-card {
155
+ background: rgba(255, 255, 255, 0.05);
156
+ border-radius: 0.75rem;
157
+ padding: 1.5rem;
158
+ border: 1px solid rgba(255, 255, 255, 0.1);
159
+ transition: all 0.3s ease;
160
+ }
161
+ .feature-card:hover {
162
+ transform: translateY(-5px);
163
+ border-color: #4f46e5;
164
+ box-shadow: 0 10px 25px rgba(79, 70, 229, 0.2);
165
+ }
166
+ .feature-icon {
167
+ font-size: 2rem;
168
+ color: #4f46e5;
169
+ margin-bottom: 1rem;
170
+ }
171
+ </style>
172
+ @endsection
173
+
174
+ @section('content')
175
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
176
+ <!-- Hero Section -->
177
+ <div class="text-center py-12">
178
+ <h1 class="text-4xl font-bold text-white mb-4">
179
+ Welcome to Aether Framework
180
+ </h1>
181
+ <p class="text-xl text-gray-300 max-w-3xl mx-auto">
182
+ A modern template engine with layout inheritance, SSR support, and enhanced syntax.
183
+ This content is injected into the main layout using @section directives.
184
+ </p>
185
+ </div>
186
+
187
+ <!-- Features Grid -->
188
+ <div class="feature-grid">
189
+ @foreach(features as feature)
190
+ <div class="feature-card">
191
+ <div class="feature-icon">
192
+ <i class="{{ feature.icon }}"></i>
193
+ </div>
194
+ <h3 class="text-xl font-semibold text-white mb-2">
195
+ {{ feature.name }}
196
+ </h3>
197
+ <p class="text-gray-300">
198
+ {{ feature.description }}
199
+ </p>
200
+ <div class="mt-4">
201
+ <span class="inline-block bg-indigo-900 text-indigo-200 text-xs font-semibold px-3 py-1 rounded-full">
202
+ {{ feature.tag }}
203
+ </span>
204
+ </div>
205
+ </div>
206
+ @endforeach
207
+ </div>
208
+
209
+ <!-- Additional Content -->
210
+ <div class="mt-12 bg-gradient-to-r from-indigo-900/30 to-purple-900/30 rounded-2xl p-8 border border-indigo-800/30">
211
+ <h2 class="text-2xl font-bold text-white mb-4">
212
+ Why Choose Aether?
213
+ </h2>
214
+ <ul class="space-y-3 text-gray-300">
215
+ <li class="flex items-center">
216
+ <i class="fas fa-check text-green-400 mr-3"></i>
217
+ <span>Blade-style syntax with @extends, @section, and @yield directives</span>
218
+ </li>
219
+ <li class="flex items-center">
220
+ <i class="fas fa-check text-green-400 mr-3"></i>
221
+ <span>Server-side rendering (SSR) support with hydration</span>
222
+ </li>
223
+ <li class="flex items-center">
224
+ <i class="fas fa-check text-green-400 mr-3"></i>
225
+ <span>Template inheritance and component reuse</span>
226
+ </li>
227
+ <li class="flex items-center">
228
+ <i class="fas fa-check text-green-400 mr-3"></i>
229
+ <span>Built-in caching for optimal performance</span>
230
+ </li>
231
+ </ul>
232
+ </div>
233
+ </div>
234
+ @endsection
235
+
236
+ @section('scripts')
237
+ <script>
238
+ console.log('Home page loaded successfully');
239
+
240
+ // Add interactive features
241
+ document.addEventListener('DOMContentLoaded', function() {
242
+ const featureCards = document.querySelectorAll('.feature-card');
243
+ featureCards.forEach(card => {
244
+ card.addEventListener('click', function() {
245
+ this.classList.toggle('ring-2');
246
+ this.classList.toggle('ring-indigo-500');
247
+ });
248
+ });
249
+
250
+ console.log('Interactive features initialized');
251
+ });
252
+ </script>
253
+ @endsection`;
254
+
255
+ // Save child template to file
256
+ const childPath = path.join(pagesDir, 'home.aether');
257
+ await fs.writeFile(childPath, childTemplate, 'utf-8');
258
+ console.log(`āœ… Child template saved to: ${childPath}\n`);
259
+
260
+ // 6ļøāƒ£ Define Template Data
261
+ console.log('6ļøāƒ£ Defining Template Data...');
262
+
263
+ // Data to be passed to the template
264
+ const data = {
265
+ // Current year for dynamic copyright notice
266
+ currentYear: new Date().getFullYear(),
267
+
268
+ // Features array for dynamic rendering - FIXED: Use 'description' not 'desc'
269
+ features: [
270
+ {
271
+ name: 'Fast Rendering',
272
+ description: 'High performance template compilation and execution with built-in caching',
273
+ icon: 'fas fa-bolt',
274
+ tag: 'Performance'
275
+ },
276
+ {
277
+ name: 'Layout Inheritance',
278
+ description: 'Powerful @extends and @section directives for reusable layouts',
279
+ icon: 'fas fa-layer-group',
280
+ tag: 'Productivity'
281
+ },
282
+ {
283
+ name: 'SSR Support',
284
+ description: 'Server-side rendering with hydration for optimal SEO and performance',
285
+ icon: 'fas fa-server',
286
+ tag: 'Modern'
287
+ },
288
+ {
289
+ name: 'Easy Syntax',
290
+ description: 'Blade-style syntax that is intuitive and easy to learn',
291
+ icon: 'fas fa-code',
292
+ tag: 'Developer Experience'
293
+ }
294
+ ],
295
+
296
+ // Helper functions available in template
297
+ formatDate: (date) => {
298
+ return new Date(date).toLocaleDateString('zh-CN', {
299
+ year: 'numeric',
300
+ month: 'long',
301
+ day: 'numeric'
302
+ });
303
+ },
304
+
305
+ // Route helper function
306
+ route: (name) => {
307
+ const routes = {
308
+ 'home': '/',
309
+ 'about': '/about',
310
+ 'docs': '/documentation',
311
+ 'contact': '/contact'
312
+ };
313
+ return routes[name] || '#';
314
+ }
315
+ };
316
+
317
+ console.log(`āœ… Data defined with ${data.features.length} features\n`);
318
+
319
+ // 7ļøāƒ£ Render Template with Layout Inheritance
320
+ console.log('7ļøāƒ£ Rendering Template with Layout Inheritance...');
321
+
322
+ try {
323
+ // Render the child template with data
324
+ // The engine will automatically handle @extends and @section directives
325
+ const result = await renderer.render(childTemplate, data);
326
+
327
+ console.log('āœ… Rendering completed successfully\n');
328
+
329
+ // 8ļøāƒ£ Display Rendered Output
330
+ console.log('--- Rendered Output (First 1500 characters) ---');
331
+ console.log(result.substring(0, 1500) + (result.length > 1500 ? '...' : ''));
332
+ console.log('-----------------------------------------------\n');
333
+
334
+ // 9ļøāƒ£ Save Rendered Output to dist Folder
335
+ console.log('8ļøāƒ£ Saving rendered output to dist folder...');
336
+
337
+ const outputPath = path.join(distDir, 'layout-example-result.html');
338
+ await fs.writeFile(outputPath, result, 'utf-8');
339
+
340
+ console.log(`šŸ’¾ HTML file saved to: ${outputPath}`);
341
+ console.log(`šŸ“„ File size: ${result.length} characters\n`);
342
+
343
+ // šŸ”Ÿ Display Engine Statistics
344
+ console.log('šŸ“Š Engine Factory Statistics:');
345
+ const stats = factory.getStats();
346
+ console.log(JSON.stringify(stats, null, 2));
347
+
348
+ // Additional debug information
349
+ console.log('\nšŸ”§ Configuration Details:');
350
+ console.log(` - Mode: ${stats.mode}`);
351
+ console.log(` - Cache Enabled: ${stats.cacheEnabled}`);
352
+ console.log(` - Cache Size: ${stats.cacheSize}`);
353
+ console.log(` - Available Engines: ${stats.engines.join(', ')}`);
354
+ console.log(` - Template Directory: ${stats.templateDir || 'Not specified'}`);
355
+
356
+ // Layout-specific information
357
+ console.log('\nšŸŽÆ Layout Features Demonstrated:');
358
+ console.log(' 1. Template inheritance with @extends directive');
359
+ console.log(' 2. Section definition with @section directive');
360
+ console.log(' 3. Content injection with @yield directive');
361
+ console.log(' 4. Default content for @yield sections');
362
+ console.log(' 5. Multiple sections (title, head, content, scripts)');
363
+ console.log(' 6. Conditional rendering with @if/@else');
364
+ console.log(' 7. Looping with @foreach directive');
365
+ console.log(' 8. Variable interpolation with {{ }} syntax');
366
+
367
+ } catch (error) {
368
+ // Enhanced error handling for rendering errors
369
+ console.error('āŒ Error during template rendering:');
370
+ console.error(` Message: ${error.message}`);
371
+ console.error(` Stack: ${error.stack}`);
372
+
373
+ // Provide helpful debugging information
374
+ console.error('\nšŸ”§ Debugging Tips:');
375
+ console.error(' 1. Check that layout file exists at: ' + layoutPath);
376
+ console.error(' 2. Verify @extends path is correct (should match file path)');
377
+ console.error(' 3. Ensure all @section directives have matching @endsection');
378
+ console.error(' 4. Check for syntax errors in template files');
379
+ console.error(' 5. Make sure you are using Aether syntax (@foreach) not Handlebars ({{#each}})');
380
+ }
381
+
382
+ } catch (error) {
383
+ // Handle initialization and setup errors
384
+ console.error('āŒ Error during engine initialization or setup:');
385
+ console.error(` Message: ${error.message}`);
386
+ console.error(` Stack: ${error.stack}`);
387
+
388
+ console.error('\nšŸ”§ Troubleshooting:');
389
+ console.error(' 1. Check that all required modules are installed');
390
+ console.error(' 2. Verify the index.js file exports createEngine correctly');
391
+ console.error(' 3. Ensure file system permissions allow directory creation');
392
+ console.error(' 4. Check that template directory structure is correct');
393
+ }
394
+ }
395
+
396
+ // Execute the main function with error handling
397
+ runLayoutExample().catch(error => {
398
+ console.error('šŸ’„ Unhandled error in main execution:');
399
+ console.error(error);
400
+ process.exit(1);
401
+ });
402
+
403
+ // Export the run function for potential module usage
404
+ export { runLayoutExample };