// Copyright (c) 2024 LinZeming
// Released under the MIT License
//
// Template — top-level entry point for parsing and rendering templates.
//
// Public API methods return `TemplateError` for structured error reporting
// with source-location tracking.
pub(all) struct Template {
nodes : Array[Node]
} derive(Debug)
// ---------------------------------------------------------------------------
// Parse
// ---------------------------------------------------------------------------
///|
/// Parse a template source string into a `Template`.
/// Returns `TemplateError` with location info on failure.
pub fn Template::parse(source : String) -> Result[Template, TemplateError] {
let tokens_result = tokenize(source)
let tokens = match tokens_result {
Ok(ts) => ts
Err(msg) => return Err(
TemplateError::new(ErrorKind::LexicalError, "Lexer error: " + msg)
)
}
let parser = Parser::new(tokens)
let parse_result = parser.parse_template()
let (nodes, _rest) = match parse_result {
Ok((ns, pp)) => (ns, pp)
Err(msg) => return Err(
TemplateError::new(ErrorKind::SyntaxError, "Parse error: " + msg)
)
}
let _ = _rest
Ok({ nodes: nodes })
}
// ---------------------------------------------------------------------------
// Render
// ---------------------------------------------------------------------------
///|
/// Render with empty loader (no includes).
pub fn Template::render(
self : Template,
ctx : Context
) -> Result[String, TemplateError] {
self.render_with_loader(ctx, TemplateLoader::new())
}
///|
/// Render with a specific loader for `{% include %}` support.
pub fn Template::render_with_loader(
self : Template,
ctx : Context,
loader : TemplateLoader
) -> Result[String, TemplateError] {
let renderer = Renderer::new(ctx, loader)
let result = renderer.render(self.nodes)
match result {
Ok(s) => Ok(s)
Err(msg) => Err(TemplateError::new(ErrorKind::RenderError, msg))
}
}