pub struct Renderer { /* private fields */ }Expand description
A renderer with pre-registered templates.
Use this when your application has multiple templates that are rendered repeatedly. Templates are compiled once and reused.
§Template Sources
Templates can come from multiple sources:
- Inline strings via
add_template- highest priority - Filesystem directories via
add_template_dir - Embedded content via
with_embedded
When the same name exists in multiple sources, inline templates take precedence over file-based templates.
Note: File-based templates must have unique names across all registered directories. If the same name exists in multiple directories, it is treated as a collision error.
§Example: Inline Templates
use standout::{Renderer, Theme};
use console::Style;
use serde::Serialize;
let theme = Theme::new()
.add("title", Style::new().bold())
.add("count", Style::new().cyan());
let mut renderer = Renderer::new(theme).unwrap();
renderer.add_template("header", r#"[title]{{ title }}[/title]"#).unwrap();
renderer.add_template("stats", r#"Count: [count]{{ n }}[/count]"#).unwrap();
#[derive(Serialize)]
struct Header { title: String }
#[derive(Serialize)]
struct Stats { n: usize }
let h = renderer.render("header", &Header { title: "Report".into() }).unwrap();
let s = renderer.render("stats", &Stats { n: 42 }).unwrap();§Example: File-Based Templates
use standout::{Renderer, Theme};
let mut renderer = Renderer::new(Theme::new())?;
// Register template directory
renderer.add_template_dir("./templates")?;
// Templates are resolved by relative path:
// "config" -> ./templates/config.jinja
// "todos/list" -> ./templates/todos/list.jinja
let output = renderer.render("config", &data)?;§Hot Reloading (Development)
In debug builds, file-based templates are re-read from disk on each render. This enables editing templates without recompiling:
# Edit template
vim templates/todos/list.jinja
# Re-run - changes are picked up immediately
cargo run -- todos listImplementations§
Source§impl Renderer
impl Renderer
Sourcepub fn new(theme: Theme) -> Result<Self, Error>
pub fn new(theme: Theme) -> Result<Self, Error>
Creates a new renderer with automatic color detection.
Color mode is detected automatically from the OS settings. Styles are resolved for the detected mode.
§Errors
Returns an error if any style aliases are invalid (dangling or cyclic).
Sourcepub fn with_output(theme: Theme, mode: OutputMode) -> Result<Self, Error>
pub fn with_output(theme: Theme, mode: OutputMode) -> Result<Self, Error>
Creates a new renderer with explicit output mode.
Color mode is detected automatically from the OS settings. Styles are resolved for the detected mode.
§Errors
Returns an error if any style aliases are invalid (dangling or cyclic).
Sourcepub fn add_template_dir<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error>
pub fn add_template_dir<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error>
Adds a directory to search for template files.
Templates in the directory are resolved by their relative path without
extension. For example, with directory ./templates:
"config"→./templates/config.jinja"todos/list"→./templates/todos/list.jinja
§Extension Priority
Recognized extensions in priority order: .jinja, .jinja2, .j2, .txt
If multiple files share the same base name with different extensions, the higher-priority extension wins for extensionless lookups.
§Multiple Directories
Multiple directories can be registered. However, template names must be unique across all directories.
§Collision Detection
If the same template name exists in multiple directories, an error
is returned (either immediately or during refresh()) with details
about the conflicting files. Strict uniqueness is enforced to prevent
ambiguous template resolution.
§Lazy Initialization
Directory walking happens lazily on first render (or explicit refresh).
In development mode, this is automatic. Call refresh() if you add
directories after the first render.
§Errors
Returns an error if the directory doesn’t exist or isn’t readable.
§Example
renderer.add_template_dir("./templates")?;
renderer.add_template_dir("./plugin-templates")?;
// "config" resolves from first directory that has it
let output = renderer.render("config", &data)?;Sourcepub fn with_embedded(&mut self, templates: HashMap<String, String>) -> &mut Self
pub fn with_embedded(&mut self, templates: HashMap<String, String>) -> &mut Self
Loads pre-embedded templates for release builds.
Embedded templates are stored directly in memory, avoiding filesystem access at runtime. This is useful for deployment where template files may not be available.
§Arguments
templates- Map of template name to content
§Example
// Generated at build time
let embedded = standout::embed_templates!("./templates");
let mut renderer = Renderer::new(theme)?;
renderer.with_embedded(embedded);Sourcepub fn with_embedded_source(&mut self, source: EmbeddedTemplates) -> &mut Self
pub fn with_embedded_source(&mut self, source: EmbeddedTemplates) -> &mut Self
Loads templates from an EmbeddedTemplates source.
This is the recommended way to use embed_templates! with Renderer.
The embedded templates are converted to a registry that supports both
extensionless and with-extension lookups.
In debug mode, if the source path exists, templates are loaded from disk (enabling hot-reload). Otherwise, embedded content is used.
§Example
use standout::{embed_templates, Renderer, Theme};
let mut renderer = Renderer::new(Theme::new())?;
renderer.with_embedded_source(embed_templates!("./templates"));
// Now you can render any template from the embedded source
let output = renderer.render("list", &data)?;Sourcepub fn set_output_mode(&mut self, mode: OutputMode)
pub fn set_output_mode(&mut self, mode: OutputMode)
Sets the output mode for subsequent renders.
This allows changing the output mode without creating a new renderer, which is useful when the same templates need to be rendered with different output modes.
§Example
let mut renderer = Renderer::new(theme)?;
// Render with terminal colors
renderer.set_output_mode(OutputMode::Term);
let colored = renderer.render("list", &data)?;
// Render plain text
renderer.set_output_mode(OutputMode::Text);
let plain = renderer.render("list", &data)?;Sourcepub fn refresh(&mut self) -> Result<(), Error>
pub fn refresh(&mut self) -> Result<(), Error>
Forces a rebuild of the template resolution map.
This re-walks all registered template directories and rebuilds the resolution map. Call this if:
- You’ve added template directories after the first render
- Template files have been added/removed from disk
In development mode, this is called automatically on first render.
§Errors
Returns an error if directory walking fails or template collisions are detected.
Sourcepub fn render<T: Serialize>(
&mut self,
name: &str,
data: &T,
) -> Result<String, Error>
pub fn render<T: Serialize>( &mut self, name: &str, data: &T, ) -> Result<String, Error>
Renders a registered template with the given data.
Templates are looked up in this order:
- Inline templates (added via
add_template) - File-based templates (from
add_template_dir)
§Hot Reloading (Development)
In debug builds, file-based templates are re-read from disk on each render. This enables editing templates without recompiling the application.
§Errors
Returns an error if the template name is not found or rendering fails.
§Example
let output = renderer.render("todos/list", &data)?;Sourcepub fn template_count(&self) -> usize
pub fn template_count(&self) -> usize
Returns the number of registered templates.
This includes both inline and file-based templates. Note: File-based templates are counted with both extensionless and with-extension names, so this may be higher than the number of files.