standout_render/template/mod.rs
1//! Two-pass template rendering with style tag processing.
2//!
3//! This module provides the core rendering pipeline that transforms templates
4//! and data into styled terminal output. Templates are processed in two passes:
5//! MiniJinja for logic, then BBParser for style tags.
6//!
7//! ## Two-Pass Rendering
8//!
9//! Templates are processed in two distinct passes, which is why style tags use
10//! bracket notation (`[name]...[/name]`) instead of Jinja syntax:
11//!
12//! **Pass 1 - MiniJinja**: Variable substitution, control flow, filters.
13//! ```text
14//! Template: [title]{{ name | upper }}[/title] has {{ count }} items
15//! After: [title]WIDGET[/title] has 42 items
16//! ```
17//!
18//! **Pass 2 - BBParser**: Style tags converted to ANSI codes (or stripped).
19//! ```text
20//! Input: [title]WIDGET[/title] has 42 items
21//! Output: \x1b[1;32mWIDGET\x1b[0m has 42 items
22//! ```
23//!
24//! This separation keeps template logic independent from styling concerns.
25//!
26//! ## Which Render Function?
27//!
28//! Choose based on your needs:
29//!
30//! | Function | Use When |
31//! |----------|----------|
32//! | [`render`] | Simple case, let Standout auto-detect everything |
33//! | [`render_with_output`] | Honoring `--output` flag (Term/Text/Auto) |
34//! | [`render_with_mode`] | Full control over output mode AND color mode |
35//! | [`render_auto`] | CLI with `--output=json` support (skips template for structured modes) |
36//!
37//! The "auto" in [`render_auto`] refers to template-vs-serialization dispatch,
38//! not color detection. Structured modes (JSON, YAML, XML, CSV) serialize data
39//! directly, skipping the template entirely.
40//!
41//! ## Style Tags in Templates
42//!
43//! Use bracket notation for styling:
44//! ```jinja
45//! [title]{{ name }}[/title] - [muted]{{ description }}[/muted]
46//! ```
47//!
48//! Tags can nest, span multiple lines, and contain template logic. Unknown tags
49//! show a `?` marker (`[unknown?]text[/unknown?]`) — use [`validate_template`]
50//! to catch typos at startup or in tests.
51//!
52//! ## Template Registry
53//!
54//! For file-based templates, use [`TemplateRegistry`]:
55//!
56//! ```rust,ignore
57//! let mut registry = TemplateRegistry::new();
58//! registry.add_from_files(walk_template_dir("./templates")?)?;
59//! let content = registry.get_content("config")?;
60//! ```
61//!
62//! Resolution priority: inline templates → embedded (compile-time) → file-based.
63//! Supported extensions: `.jinja`, `.jinja2`, `.j2`, `.txt` (in priority order).
64//!
65//! ## Key Types
66//!
67//! - [`Renderer`]: Pre-compiled template renderer for repeated rendering
68//! - [`TemplateRegistry`]: Template resolution from multiple sources
69//! - [`validate_template`]: Check templates for unknown style tags
70//!
71//! ## See Also
72//!
73//! - [`crate::theme`]: Theme and style definitions
74//! - [`crate::tabular`]: Column formatting utilities and template filters
75//! - [`crate::context`]: Context injection for templates
76
77pub mod filters;
78mod functions;
79pub mod registry;
80mod renderer;
81
82pub use functions::{
83 render, render_auto, render_auto_with_context, render_auto_with_spec, render_with_context,
84 render_with_mode, render_with_output, render_with_vars, validate_template,
85};
86pub use registry::{
87 walk_template_dir, RegistryError, ResolvedTemplate, TemplateFile, TemplateRegistry,
88 TEMPLATE_EXTENSIONS,
89};
90pub use renderer::Renderer;