Skip to content

KimuEngine โ€‹

Rendering engine and template management that provides core functionality for rendering, template loading, and dynamic component management.

Description โ€‹

KimuEngine acts as a bridge between the rendering system (Lit) and the asset manager, providing unified APIs for:

  • Style injection in Shadow DOM
  • HTML template loading and compilation
  • Reactive rendering with Lit
  • Dynamic component loading

All methods are static, making the class a central utility for rendering operations.

Usage โ€‹

Style Injection โ€‹

typescript
import { KimuEngine } from './core/kimu-engine';

// Inject style into a component
await KimuEngine.injectStyle(
    this,                           // Target component
    'assets/theme.css',            // CSS path
    'my-theme-style'               // Unique ID (optional)
);

Template Loading โ€‹

typescript
// Load and compile HTML template
const renderFunction = await KimuEngine.loadTemplate('/extensions/my-app/view.html');

// Use the rendering function
KimuEngine.render(this, { title: 'Hello!' }, renderFunction);

Direct Rendering โ€‹

typescript
// Compile template from string
const templateString = '<h1>${title}</h1><p>${description}</p>';
const renderFn = KimuEngine.compileTemplate(templateString);

// Rendering with data
KimuEngine.render(this, {
    title: 'Dynamic Title',
    description: 'Updated content'
}, renderFn);

API โ€‹

Style Management โ€‹

injectStyle(component, stylePath, styleId?): Promise<void> โ€‹

Injects a CSS file into the component's Shadow DOM.

Parameters:

  • component: HTMLElement - Target component
  • stylePath: string - Path to CSS file
  • styleId: string | null - Unique ID for the style element (optional)

Example:

typescript
// Inject main style
await KimuEngine.injectStyle(this, 'assets/main.css', 'main-style');

// Inject conditional theme
if (isDarkMode) {
    await KimuEngine.injectStyle(this, 'assets/dark-theme.css', 'dark-theme');
}

Template Management โ€‹

loadTemplate(path): Promise<Function> โ€‹

Loads an HTML template file and compiles it into a Lit rendering function.

Parameters:

  • path: string - Path to template file

Returns: Promise<Function> - Compiled rendering function

Example:

typescript
// In a component
async connectedCallback(): Promise<void> {
    const templatePath = `/extensions/${this.getMeta().basePath}/view.html`;
    this._renderFn = await KimuEngine.loadTemplate(templatePath);
    this.refresh();
}

compileTemplate(template): Function โ€‹

Compiles an HTML string into a Lit rendering function.

Parameters:

  • template: string - HTML template string

Returns: Function - Rendering function

Example:

typescript
// Dynamic template
const templateStr = `
    <div class="card">
        <h2>\${title}</h2>
        <p>\${description}</p>
        <button onclick="\${onClick}">\${buttonLabel}</button>
    </div>
`;

const renderFn = KimuEngine.compileTemplate(templateStr);

// Immediate use
KimuEngine.render(this, {
    title: 'Dynamic Card',
    description: 'Generated at runtime',
    buttonLabel: 'Click here',
    onClick: 'handleClick()'
}, renderFn);

Rendering โ€‹

render(component, data, renderFn): void โ€‹

Performs reactive rendering using Lit.

Parameters:

  • component: HTMLElement - Target component
  • data: Record<string, any> - Data for the template
  • renderFn: Function - Rendering function

Example:

typescript
// Rendering with dynamic data
const data = {
    users: ['Alice', 'Bob', 'Charlie'],
    currentTime: new Date().toLocaleString(),
    isLoggedIn: true
};

KimuEngine.render(this, data, this._renderFn);

Component Loading โ€‹

loadComponent(tag, path): Promise<any> โ€‹

Loads a component from a specific path and registers it if not already registered.

Parameters:

  • tag: string - Component tag name
  • path: string - Path to component module

Returns: Promise<any> - Loaded module

Example:

typescript
// Dynamic component loading
await KimuEngine.loadComponent(
    'custom-widget',
    '/extensions/widgets/custom-widget/component.js'
);

// Now the component can be used
const widget = document.createElement('custom-widget');

Advanced Examples โ€‹

Dynamic Theme System โ€‹

typescript
class ThemeManager {
    static async applyTheme(component: HTMLElement, themeName: string): Promise<void> {
        // Remove previous theme
        const oldTheme = component.shadowRoot?.getElementById('current-theme');
        if (oldTheme) {
            oldTheme.remove();
        }
        
        // Load new theme
        await KimuEngine.injectStyle(
            component,
            `assets/themes/${themeName}.css`,
            'current-theme'
        );
    }
}

// Usage
await ThemeManager.applyTheme(this, 'dark');

Conditional Templates โ€‹

typescript
class ConditionalRenderer {
    static async renderByCondition(
        component: HTMLElement, 
        condition: string, 
        data: any
    ): Promise<void> {
        // Select template based on condition
        const templateMap = {
            'loading': 'templates/loading.html',
            'error': 'templates/error.html',
            'success': 'templates/content.html'
        };
        
        const templatePath = templateMap[condition] || templateMap['error'];
        const renderFn = await KimuEngine.loadTemplate(templatePath);
        
        KimuEngine.render(component, data, renderFn);
    }
}

// Usage
await ConditionalRenderer.renderByCondition(this, 'loading', {
    message: 'Loading in progress...'
});

Dynamic Template Builder โ€‹

typescript
class TemplateBuilder {
    private static buildListTemplate(items: any[]): string {
        const itemTemplates = items.map((_, index) => 
            `<li class="item">\${items[${index}].name}</li>`
        ).join('');
        
        return `
            <div class="list-container">
                <h3>\${title}</h3>
                <ul class="items">
                    ${itemTemplates}
                </ul>
            </div>
        `;
    }
    
    static renderDynamicList(component: HTMLElement, data: any): void {
        const template = this.buildListTemplate(data.items);
        const renderFn = KimuEngine.compileTemplate(template);
        
        KimuEngine.render(component, data, renderFn);
    }
}

// Usage
TemplateBuilder.renderDynamicList(this, {
    title: 'Dynamic List',
    items: [
        { name: 'Item 1' },
        { name: 'Item 2' },
        { name: 'Item 3' }
    ]
});

Rendering with Performance Monitoring โ€‹

typescript
class PerformantRenderer {
    static async renderWithProfiling(
        component: HTMLElement,
        data: any,
        renderFn: Function,
        label = 'render'
    ): Promise<void> {
        // Start profiling
        performance.mark(`${label}-start`);
        
        try {
            KimuEngine.render(component, data, renderFn);
            
            // End profiling
            performance.mark(`${label}-end`);
            performance.measure(label, `${label}-start`, `${label}-end`);
            
            const measure = performance.getEntriesByName(label)[0];
            console.log(`๐ŸŽฏ Rendering ${label}: ${measure.duration.toFixed(2)}ms`);
            
        } catch (error) {
            console.error(`โŒ Rendering error ${label}:`, error);
        } finally {
            // Cleanup
            performance.clearMarks(`${label}-start`);
            performance.clearMarks(`${label}-end`);
            performance.clearMeasures(label);
        }
    }
}

Integration with Lit โ€‹

KimuEngine internally uses Lit for reactive rendering:

typescript
import { html, render as litRender, TemplateResult } from 'lit';

// The compiled template uses Lit syntax
const template = html`
    <div class="component">
        <h1>${data.title}</h1>
        <p>${data.content}</p>
    </div>
`;

// Rendering in Shadow DOM
litRender(template, component.shadowRoot!);

Best Practices โ€‹

โœ… Error Handling โ€‹

typescript
try {
    const renderFn = await KimuEngine.loadTemplate(templatePath);
    KimuEngine.render(this, data, renderFn);
} catch (error) {
    console.error('Rendering error:', error);
    // Fallback template
    const fallbackFn = KimuEngine.compileTemplate('<p>Loading error</p>');
    KimuEngine.render(this, {}, fallbackFn);
}

โœ… Template Caching โ€‹

typescript
private static templateCache = new Map<string, Function>();

static async getCachedTemplate(path: string): Promise<Function> {
    if (!this.templateCache.has(path)) {
        const renderFn = await KimuEngine.loadTemplate(path);
        this.templateCache.set(path, renderFn);
    }
    return this.templateCache.get(path)!;
}

โœ… Lazy Loading Components โ€‹

typescript
static async loadComponentLazy(tag: string): Promise<void> {
    if (!customElements.get(tag)) {
        const path = `/extensions/${tag}/component.js`;
        await KimuEngine.loadComponent(tag, path);
    }
}

Optimizations and Cache Management โ€‹

Template Cache Management โ€‹

KimuEngine includes an intelligent cache system with memory management.

configureCaching(maxSize: number): void (Static) โ€‹

Configure template cache settings.

Parameters:

  • maxSize: number - Maximum cache size (default: 50)

Example:

typescript
// Cache configuration for large apps
KimuEngine.configureCaching(100);

// Conservative configuration for low-memory devices
KimuEngine.configureCaching(25);

clearCaches(): void (Static) โ€‹

Clear all caches (useful for debugging and testing).

typescript
// Clear caches for testing
KimuEngine.clearCaches();

// After template updates
if (developmentMode) {
    KimuEngine.clearCaches();
}

Advanced Asset Preloading โ€‹

preloadAssets(paths: string[]): Promise<void> (Static) โ€‹

Preload assets in batches to improve performance.

Features:

  • Batch loading with concurrency control (5 assets at a time)
  • Graceful error handling for missing assets
  • Support for templates (.html), styles (.css), and generic assets

Example:

typescript
// Preload critical assets
await KimuEngine.preloadAssets([
    'extensions/dashboard/view.html',
    'extensions/dashboard/style.css',
    'extensions/sidebar/view.html',
    'extensions/navigation/style.css',
    'assets/icons.css',
    'assets/theme.css'
]);

// Conditional preloading
if (userPreferences.preloadEnabled) {
    const criticalAssets = getCriticalAssetsForUser();
    await KimuEngine.preloadAssets(criticalAssets);
}

LRU (Least Recently Used) Cache โ€‹

The cache system uses LRU algorithm for automatic memory management:

typescript
// Internal cache with access tracking
// - Automatic removal of least used entries
// - Evicts 20% when limit is reached
// - Timestamp tracking for LRU algorithm

// Cache monitoring (automatic console.log)
// "[KimuEngine] Evicted X old template cache entries"

Performance Monitoring โ€‹

typescript
class PerformanceMonitor {
    static measureTemplateLoad(path: string) {
        const start = performance.now();
        
        return KimuEngine.loadTemplate(path).then(result => {
            const duration = performance.now() - start;
            console.log(`Template ${path} loaded in ${duration.toFixed(2)}ms`);
            return result;
        });
    }
    
    static async benchmarkPreloading(assets: string[]) {
        const start = performance.now();
        await KimuEngine.preloadAssets(assets);
        const duration = performance.now() - start;
        
        console.log(`Preloaded ${assets.length} assets in ${duration.toFixed(2)}ms`);
    }
}

See Also โ€‹

Released under Creative Commons Attribution 4.0 International (CC BY 4.0)