/** * @module m * DOM-based template engine with reactive rendering capabilities. * * Compiles HTML templates with mustache-style expressions into efficient * render functions that update the DOM when data changes. * * **Features:** * - Text interpolation: `{{name}}`, `{{user.profile.email}}` * - Attribute binding: `
` * - Pipes: `{{price | currency}}`, `{{name | uppercase | truncate:20}}` * - Function calls: `{{formatDate(createdAt)}}`, `{{add(5, 3)}}` * - Array indexing: `{{items[0]}}`, `{{users[1].name}}` * - Conditionals: `
`, `
` * - Loops: `
  • {{item.name}}
  • ` * * @example * // Basic usage * import { compileTemplate } from './m'; * * const { content, render } = compileTemplate(` *
    *

    {{title}}

    *

    {{description}}

    *
    * `); * * render({ title: 'Hello', description: 'World' }); * document.body.appendChild(content); * * @example * // With pipes and functions * import { createPipeRegistry } from '../pipes'; * * const pipeRegistry = createPipeRegistry(); * const { content, render } = compileTemplate(` * {{user.name | uppercase}} * {{formatDate(user.createdAt)}} * `, { strict: false, pipeRegistry }); * * render( * { user: { name: 'john', createdAt: new Date() } }, * { formatDate: (d) => d.toLocaleDateString() } * ); * * @example * // With loops and conditionals * const { content, render } = compileTemplate(` *
      *
    • * {{item.name}}: {{item.price | currency}} *
    • *
    * `); * * render({ items: [ * { name: 'Apple', price: 1.5, visible: true }, * { name: 'Hidden', price: 0, visible: false } * ]}); */ import { PipeRegistry } from '../pipes'; /** * Configuration options for the template engine. * * @example * const config: EngineConfig = { * strict: true, * onError: (msg) => console.error(msg), * pipeRegistry: createPipeRegistry() * }; */ export interface EngineConfig { /** When true, throws errors for missing paths/functions. When false, returns empty string. */ strict: boolean; /** Optional callback invoked when errors occur, receives formatted error message. */ onError?: (msg: string) => void; /** Custom pipe registry for transformations. Defaults to built-in pipes. */ pipeRegistry?: PipeRegistry; } export type Path = string; export type TemplateValue = string | number | boolean | null | undefined; /** * Data context object passed to render function. * Contains the data values that expressions resolve against. * * @example * const ctx: Context = { * user: { name: 'John', age: 30 }, * items: ['a', 'b', 'c'], * isActive: true * }; */ export interface Context { [key: string]: ContextValue; } /** * Functions context object passed as second argument to render. * Contains callable functions that can be invoked from templates. * * @example * const fns: FunctionsContext = { * formatDate: (d) => d.toLocaleDateString(), * add: (a, b) => a + b, * greet: (name) => `Hello, ${name}!` * }; */ export interface FunctionsContext { [key: string]: (...args: any[]) => any; } export type ContextValue = TemplateValue | any[] | Context | ((...args: any[]) => any); export type Getter = (ctx: Context, path: Path, debugInfo?: string) => TemplateValue; export type Setter = (ctx: Context, fns?: FunctionsContext) => void; export type Patcher = (node: Node, get: Getter, config: EngineConfig) => Setter | void; export type ExpressionFn = (ctx: Context, fns?: FunctionsContext) => TemplateValue; /** * Result of compiling a template. * Contains the DOM content and a render function for updating it with data. */ export interface CompiledTemplate { /** The compiled DOM element containing the template structure. */ content: DocumentFragment | HTMLElement; /** * Updates the DOM with the provided data context. * Memoized: only re-renders when context object reference changes. * @param ctx - Data context with values for template expressions * @param fns - Optional functions context for callable expressions */ render: (ctx: Context, fns?: FunctionsContext) => void; } /** * Compiles an HTML template string into a reusable render function. * * The template supports mustache-style expressions `{{expression}}` for: * - Path resolution: `{{user.name}}`, `{{items[0].title}}` * - Pipes: `{{value | uppercase}}`, `{{price | currency}}` * - Function calls: `{{formatDate(createdAt)}}`, `{{add(a, b)}}` * * Directive attributes for control flow: * - `if="condition"` - Renders element only when condition is truthy * - `unless="condition"` - Renders element only when condition is falsy * - `loop="item in items"` - Repeats element for each array item * * @param templateStr - HTML template string with mustache expressions * @param config - Optional engine configuration * @returns Compiled template with content and render function * * @example * // Simple data binding * const { content, render } = compileTemplate('

    {{title}}

    '); * render({ title: 'Hello World' }); * document.body.appendChild(content); * * @example * // Re-rendering with new data * const { content, render } = compileTemplate('Count: {{count}}'); * render({ count: 0 }); * render({ count: 1 }); // DOM updates automatically * * @example * // With strict mode and error handling * const { render } = compileTemplate('{{missing}}', { * strict: true, * onError: (msg) => console.error(msg) * }); * render({}); // Throws error for missing path */ export declare function compileTemplate(templateStr: string, config?: EngineConfig): CompiledTemplate;