#[cfg(feature = "highlight-code")]
use crate::CodeTheme;
use crate::{DefaultStyleSheet, StyleSheet};
#[non_exhaustive]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum ImageFallback {
#[default]
AltText,
Url,
AltTextAndUrl,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Options<S: StyleSheet = DefaultStyleSheet> {
pub(crate) styles: S,
pub(crate) image_fallback: ImageFallback,
#[cfg(feature = "highlight-code")]
code_theme: Option<CodeTheme>,
}
impl<S: StyleSheet> Options<S> {
pub fn new(styles: S) -> Self {
Self {
styles,
image_fallback: ImageFallback::default(),
#[cfg(feature = "highlight-code")]
code_theme: None,
}
}
#[must_use]
pub fn image_fallback(mut self, image_fallback: ImageFallback) -> Self {
self.image_fallback = image_fallback;
self
}
#[cfg(feature = "highlight-code")]
#[must_use]
pub fn code_theme(mut self, code_theme: impl Into<CodeTheme>) -> Self {
self.code_theme = Some(code_theme.into());
self
}
#[cfg(feature = "highlight-code")]
#[must_use]
pub fn selected_code_theme(&self) -> Option<&CodeTheme> {
self.code_theme.as_ref()
}
}
impl Default for Options<DefaultStyleSheet> {
fn default() -> Self {
Self::new(DefaultStyleSheet)
}
}
#[cfg(test)]
mod tests {
use ratatui_core::style::Style;
use super::*;
#[test]
fn default() {
let options: Options = Default::default();
assert_eq!(
options.styles.heading(1),
Style::new().on_cyan().bold().underlined()
);
}
#[test]
fn custom_style_sheet() {
#[derive(Debug, Clone)]
struct CustomStyleSheet;
impl StyleSheet for CustomStyleSheet {
fn heading(&self, level: u8) -> Style {
match level {
1 => Style::new().red().bold(),
_ => Style::new().green(),
}
}
}
let options = Options {
styles: CustomStyleSheet,
image_fallback: ImageFallback::default(),
#[cfg(feature = "highlight-code")]
code_theme: None,
};
assert_eq!(options.styles.heading(1), Style::new().red().bold());
assert_eq!(options.styles.heading(2), Style::new().green());
assert_eq!(options.styles.code(), Style::new().white().on_black());
assert_eq!(options.styles.link(), Style::new().blue().underlined());
assert_eq!(options.styles.blockquote(), Style::new().green());
assert_eq!(options.styles.heading_meta(), Style::new().dim());
assert_eq!(options.styles.metadata_block(), Style::new().light_yellow());
assert_eq!(options.styles.image_alt(), Style::new().dim().italic());
}
#[test]
fn image_fallback_defaults_to_alt_text() {
let options = Options::default();
assert_eq!(options.image_fallback, ImageFallback::AltText);
}
#[test]
fn image_fallback_setter_updates_mode() {
let options = Options::default().image_fallback(ImageFallback::AltTextAndUrl);
assert_eq!(options.image_fallback, ImageFallback::AltTextAndUrl);
}
#[test]
#[cfg(feature = "highlight-code")]
fn default_has_no_explicit_code_theme() {
let options: Options = Options::default();
assert!(options.selected_code_theme().is_none());
}
#[test]
#[cfg(feature = "highlight-code")]
fn code_theme_selects_theme() {
let options = Options::default().code_theme(crate::BuiltinCodeTheme::SolarizedDark);
assert!(options.selected_code_theme().is_some());
}
}