standout_render/lib.rs
1//! # Standout Render - Styled Terminal Output Library
2//!
3//! `standout-render` provides a complete rendering system for styled terminal output,
4//! including template processing, theming, and adaptive color support.
5//!
6//! This crate is the rendering foundation for the `standout` CLI framework, but can
7//! be used independently for any application that needs rich terminal output.
8//!
9//! ## Core Concepts
10//!
11//! - [`Theme`]: Named collection of adaptive styles that respond to light/dark mode
12//! - [`ColorMode`]: Light or dark color mode enum
13//! - [`OutputMode`]: Control output formatting (Auto/Term/Text/TermDebug/Json/Yaml)
14//! - Style syntax: Tag-based styling `[name]content[/name]`
15//! - [`Renderer`]: Pre-compile templates for repeated rendering
16//! - [`validate_template`]: Check templates for unknown style tags
17//!
18//! ## Quick Start
19//!
20//! ```rust
21//! use standout_render::{render, Theme};
22//! use console::Style;
23//! use serde::Serialize;
24//!
25//! #[derive(Serialize)]
26//! struct Summary {
27//! title: String,
28//! total: usize,
29//! }
30//!
31//! let theme = Theme::new()
32//! .add("title", Style::new().bold())
33//! .add("count", Style::new().cyan());
34//!
35//! let template = r#"
36//! [title]{{ title }}[/title]
37//! ---------------------------
38//! Total items: [count]{{ total }}[/count]
39//! "#;
40//!
41//! let output = render(
42//! template,
43//! &Summary { title: "Report".into(), total: 3 },
44//! &theme,
45//! ).unwrap();
46//! println!("{}", output);
47//! ```
48//!
49//! ## Tag-Based Styling
50//!
51//! Use tag syntax `[name]content[/name]` for styling both static and dynamic content:
52//!
53//! ```rust
54//! use standout_render::{render_with_output, Theme, OutputMode};
55//! use console::Style;
56//! use serde::Serialize;
57//!
58//! #[derive(Serialize)]
59//! struct Data { name: String, count: usize }
60//!
61//! let theme = Theme::new()
62//! .add("title", Style::new().bold())
63//! .add("count", Style::new().cyan());
64//!
65//! let template = r#"[title]Report[/title]: [count]{{ count }}[/count] items by {{ name }}"#;
66//!
67//! let output = render_with_output(
68//! template,
69//! &Data { name: "Alice".into(), count: 42 },
70//! &theme,
71//! OutputMode::Text,
72//! ).unwrap();
73//!
74//! assert_eq!(output, "Report: 42 items by Alice");
75//! ```
76//!
77//! ## Adaptive Themes (Light & Dark)
78//!
79//! Themes are inherently adaptive. Individual styles can define mode-specific
80//! variations that are automatically selected based on the user's OS color mode.
81//!
82//! ```rust
83//! use standout_render::Theme;
84//! use console::Style;
85//!
86//! let theme = Theme::new()
87//! // Non-adaptive style (same in all modes)
88//! .add("header", Style::new().bold().cyan())
89//! // Adaptive style with light/dark variants
90//! .add_adaptive(
91//! "panel",
92//! Style::new(), // Base
93//! Some(Style::new().fg(console::Color::Black)), // Light mode
94//! Some(Style::new().fg(console::Color::White)), // Dark mode
95//! );
96//! ```
97//!
98//! ## YAML-Based Themes
99//!
100//! Themes can be loaded from YAML files:
101//!
102//! ```rust
103//! use standout_render::Theme;
104//!
105//! let theme = Theme::from_yaml(r#"
106//! header:
107//! fg: cyan
108//! bold: true
109//! panel:
110//! fg: gray
111//! light:
112//! fg: black
113//! dark:
114//! fg: white
115//! title: header
116//! "#).unwrap();
117//! ```
118//!
119//! ## More Examples
120//!
121//! ```rust
122//! use standout_render::{Renderer, Theme};
123//! use console::Style;
124//! use serde::Serialize;
125//!
126//! #[derive(Serialize)]
127//! struct Entry { label: String, value: i32 }
128//!
129//! let theme = Theme::new()
130//! .add("label", Style::new().bold())
131//! .add("value", Style::new().green());
132//!
133//! let mut renderer = Renderer::new(theme).unwrap();
134//! renderer.add_template("row", "[label]{{ label }}[/label]: [value]{{ value }}[/value]").unwrap();
135//! let rendered = renderer.render("row", &Entry { label: "Count".into(), value: 42 }).unwrap();
136//! assert_eq!(rendered, "Count: 42");
137//! ```
138
139// Internal modules
140pub mod context;
141mod embedded;
142pub mod file_loader;
143pub mod output;
144pub mod prelude;
145pub mod style;
146pub mod tabular;
147pub mod template;
148pub mod theme;
149mod util;
150
151// Re-export minijinja::Error for convenience
152pub use minijinja::Error;
153
154// Style module exports (including former stylesheet exports)
155pub use style::{
156 parse_css, parse_stylesheet, ColorDef, StyleAttributes, StyleDefinition, StyleValidationError,
157 StyleValue, Styles, StylesheetError, StylesheetRegistry, ThemeVariants,
158 DEFAULT_MISSING_STYLE_INDICATOR, STYLESHEET_EXTENSIONS,
159};
160
161// Theme module exports
162pub use theme::{detect_color_mode, set_theme_detector, ColorMode, Theme};
163
164// Output module exports
165pub use output::{write_binary_output, write_output, OutputDestination, OutputMode};
166
167// Render module exports
168pub use template::{
169 render,
170 render_auto,
171 render_auto_with_context,
172 render_auto_with_spec,
173 render_with_context,
174 render_with_mode,
175 render_with_output,
176 render_with_vars,
177 validate_template,
178 // Template registry
179 walk_template_dir,
180 RegistryError,
181 Renderer,
182 ResolvedTemplate,
183 TemplateFile,
184 TemplateRegistry,
185 TEMPLATE_EXTENSIONS,
186};
187
188// Re-export BBParser types for template validation
189pub use standout_bbparser::{UnknownTagError, UnknownTagErrors, UnknownTagKind};
190
191// Utility exports
192pub use util::{flatten_json_for_csv, rgb_to_ansi256, rgb_to_truecolor, truncate_to_width};
193
194// File loader exports
195pub use file_loader::{
196 build_embedded_registry, extension_priority, strip_extension, walk_dir, FileRegistry,
197 FileRegistryConfig, LoadError, LoadedEntry, LoadedFile,
198};
199
200// Embedded source types (for macros)
201pub use embedded::{
202 EmbeddedSource, EmbeddedStyles, EmbeddedTemplates, StylesheetResource, TemplateResource,
203};