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;
142mod error;
143pub mod file_loader;
144pub mod output;
145pub mod prelude;
146pub mod style;
147pub mod tabular;
148pub mod template;
149pub mod theme;
150mod util;
151
152// Error type
153pub use error::RenderError;
154
155// Style module exports (including former stylesheet exports)
156pub use style::{
157 parse_css, parse_stylesheet, ColorDef, StyleAttributes, StyleDefinition, StyleValidationError,
158 StyleValue, Styles, StylesheetError, StylesheetRegistry, ThemeVariants,
159 DEFAULT_MISSING_STYLE_INDICATOR, STYLESHEET_EXTENSIONS,
160};
161
162// Theme module exports
163pub use theme::{detect_color_mode, set_theme_detector, ColorMode, Theme};
164
165// Output module exports
166pub use output::{write_binary_output, write_output, OutputDestination, OutputMode};
167
168// Render module exports
169pub use template::{
170 render,
171 render_auto,
172 render_auto_with_context,
173 render_auto_with_engine,
174 render_auto_with_spec,
175 render_with_context,
176 render_with_mode,
177 render_with_output,
178 render_with_vars,
179 validate_template,
180 // Template registry
181 walk_template_dir,
182 // Template engine abstraction
183 MiniJinjaEngine,
184 RegistryError,
185 Renderer,
186 ResolvedTemplate,
187 TemplateEngine,
188 TemplateFile,
189 TemplateRegistry,
190 TEMPLATE_EXTENSIONS,
191};
192
193// Re-export BBParser types for template validation
194pub use standout_bbparser::{UnknownTagError, UnknownTagErrors, UnknownTagKind};
195
196// Utility exports
197pub use util::{flatten_json_for_csv, rgb_to_ansi256, rgb_to_truecolor, truncate_to_width};
198
199// File loader exports
200pub use file_loader::{
201 build_embedded_registry, extension_priority, strip_extension, walk_dir, FileRegistry,
202 FileRegistryConfig, LoadError, LoadedEntry, LoadedFile,
203};
204
205// Embedded source types (for macros)
206pub use embedded::{
207 EmbeddedSource, EmbeddedStyles, EmbeddedTemplates, StylesheetResource, TemplateResource,
208};