ratatui_toolkit/widgets/markdown_widget/extensions/toc/methods/
required_expanded_width.rs

1//! Calculate required width for expanded TOC mode.
2
3use unicode_width::UnicodeWidthStr;
4
5use super::super::Toc;
6
7impl<'a> Toc<'a> {
8    /// Calculate the required width to display all headings without truncation.
9    ///
10    /// Takes into account:
11    /// - Indentation based on heading level (2 chars per level)
12    /// - Actual text width using Unicode width
13    /// - Padding (left and right)
14    /// - Border if enabled
15    ///
16    /// # Arguments
17    ///
18    /// * `content` - The markdown content to scan.
19    /// * `show_border` - Whether the border is shown.
20    ///
21    /// # Returns
22    ///
23    /// The required width in columns.
24    pub fn required_expanded_width(content: &str, show_border: bool) -> u16 {
25        let padding_left: u16 = 2;
26        let padding_right: u16 = 1;
27        let border_width: u16 = if show_border { 2 } else { 0 };
28
29        let mut max_width: u16 = 0;
30
31        for line in content.lines() {
32            let trimmed = line.trim_start();
33            if !trimmed.starts_with('#') {
34                continue;
35            }
36
37            // Count heading level
38            let hash_count = trimmed.chars().take_while(|&c| c == '#').count();
39            if !(1..=6).contains(&hash_count) {
40                continue;
41            }
42
43            // Extract heading text
44            let after_hashes = &trimmed[hash_count..];
45            if !after_hashes.starts_with(' ') && !after_hashes.is_empty() {
46                continue;
47            }
48
49            let text = after_hashes.trim();
50            if text.is_empty() {
51                continue;
52            }
53
54            // Calculate width: indent + text width
55            let indent = ((hash_count - 1) * 2) as u16;
56            let text_width = text.width() as u16;
57            let entry_width = indent + text_width;
58
59            if entry_width > max_width {
60                max_width = entry_width;
61            }
62        }
63
64        // Minimum width if no headings found
65        if max_width == 0 {
66            return if show_border { 10 } else { 8 };
67        }
68
69        max_width + padding_left + padding_right + border_width
70    }
71}