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