tui_markdown/style_sheet.rs
1//! Style sheet abstraction for tui-markdown.
2//!
3//! The library used to hard–code all color and attribute choices in an internal `styles` module.
4//! That made it impossible for downstream crates to provide their own look-and-feel. The
5//! [`StyleSheet`] trait makes it possible to customize the styles used to display the
6//! [`ratatui_core::style::Style`] values the renderer needs.
7//!
8//! Users that are happy with the stock colors do not have to do anything – the crate exports a
9//! [`DefaultStyleSheet`] which matches the old behaviour and is used by default. Projects that want
10//! to theme the output can implement the trait for their own type and pass an instance via
11//! [`crate::Options`].
12
13use ratatui_core::style::Style;
14
15/// A collection of `ratatui_core::style::Style`s consumed by the renderer.
16///
17/// The trait purposefully stays tiny: whenever the renderer needs a color choice we add a new
18/// getter here. The default implementation maintains full backward-compatibility with the styles
19/// that lived in the old `mod styles`.
20pub trait StyleSheet: Clone + Send + Sync + 'static {
21 /// Style for a Markdown heading.
22 ///
23 /// `level` is one-based (`1` for `# H1`, …).
24 fn heading(&self, level: u8) -> Style;
25
26 /// Style for inline `code` spans and fenced code blocks when syntax highlighting is disabled.
27 fn code(&self) -> Style;
28
29 /// Style for the text of an inline or reference link.
30 fn link(&self) -> Style;
31
32 /// Base style applied to blockquotes (`>` prefix and body text).
33 fn blockquote(&self) -> Style;
34
35 /// Style for heading attribute metadata appended to the heading text.
36 fn heading_meta(&self) -> Style;
37
38 /// Style for metadata blocks (front matter).
39 fn metadata_block(&self) -> Style;
40}
41
42/// The default style set
43///
44/// This style sheet will be used by default if the user does not provide their own implementation.
45///
46/// Styles are:
47/// - H1: white on cyan, bold, underlined
48/// - H2: cyan, bold
49/// - H3: cyan, bold, italic
50/// - H4-H6: light cyan, italic
51/// - code: white on black
52/// - link: blue, underlined
53/// - blockquote: green
54/// - metadata block: light yellow
55#[derive(Clone, Copy, Debug, Default)]
56pub struct DefaultStyleSheet;
57
58impl StyleSheet for DefaultStyleSheet {
59 fn heading(&self, level: u8) -> Style {
60 match level {
61 1 => Style::new().on_cyan().bold().underlined(),
62 2 => Style::new().cyan().bold(),
63 3 => Style::new().cyan().bold().italic(),
64 4 => Style::new().light_cyan().italic(),
65 5 => Style::new().light_cyan().italic(),
66 _ => Style::new().light_cyan().italic(),
67 }
68 }
69
70 fn code(&self) -> Style {
71 Style::new().white().on_black()
72 }
73
74 fn link(&self) -> Style {
75 Style::new().blue().underlined()
76 }
77
78 fn blockquote(&self) -> Style {
79 Style::new().green()
80 }
81
82 fn heading_meta(&self) -> Style {
83 // De-emphasize metadata so the heading text stays primary.
84 Style::new().dim()
85 }
86
87 fn metadata_block(&self) -> Style {
88 Style::new().light_yellow()
89 }
90}