Skip to main content

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};