1use std::path::PathBuf;
2
3use printpdf::{Color, Pt, Rgb};
4
5use super::layout::{PageBuilder, Span};
6
7pub struct TocEntry {
9 pub path: PathBuf,
10 pub line_count: usize,
11 pub size_str: String,
12 pub last_modified: String,
13 pub start_page: usize,
14}
15
16pub fn render(builder: &mut PageBuilder, entries: &[TocEntry]) {
17 let bold = builder.font(true, false).clone();
18 let regular = builder.font(false, false).clone();
19 let gray = Color::Rgb(Rgb::new(0.47, 0.47, 0.47, None));
20 let black = Color::Rgb(Rgb::new(0.0, 0.0, 0.0, None));
21
22 builder.write_centered("Table of Contents", &bold, Pt(16.0), black);
23 builder.vertical_space(10.0);
24
25 entries.iter().for_each(|entry| {
26 let meta = format!(
27 "p.{} {} LOC \u{00B7} {} \u{00B7} {}",
28 entry.start_page, entry.line_count, entry.size_str, entry.last_modified
29 );
30 builder.write_line_justified(
31 &[Span {
32 text: entry.path.display().to_string(),
33 font_id: regular.clone(),
34 size: Pt(8.0),
35 color: gray.clone(),
36 }],
37 &[Span {
38 text: meta,
39 font_id: regular.clone(),
40 size: Pt(7.0),
41 color: gray.clone(),
42 }],
43 );
44 });
45
46 builder.page_break();
47}
48
49#[cfg(test)]
50mod tests {
51 use crate::pdf;
52 use crate::types::Config;
53 use std::path::PathBuf;
54
55 fn make_entry(path: &str, lines: usize, page: usize) -> super::TocEntry {
56 super::TocEntry {
57 path: PathBuf::from(path),
58 line_count: lines,
59 size_str: "1.2 KB".to_string(),
60 last_modified: "2024-01-15".to_string(),
61 start_page: page,
62 }
63 }
64
65 #[test]
66 fn render_toc_does_not_panic() {
67 let mut doc = printpdf::PdfDocument::new("test");
68 let fonts = pdf::fonts::load_fonts(&mut doc).unwrap();
69 let config = Config::test_default();
70 let mut builder = pdf::create_builder(&config, fonts);
71 let entries = vec![
72 make_entry("src/main.rs", 20, 5),
73 make_entry("src/lib.rs", 50, 7),
74 ];
75 super::render(&mut builder, &entries);
76 }
77
78 #[test]
79 fn render_toc_empty_files() {
80 let mut doc = printpdf::PdfDocument::new("test");
81 let fonts = pdf::fonts::load_fonts(&mut doc).unwrap();
82 let config = Config::test_default();
83 let mut builder = pdf::create_builder(&config, fonts);
84 super::render(&mut builder, &[]);
85 }
86
87 #[test]
88 fn render_toc_many_files() {
89 let mut doc = printpdf::PdfDocument::new("test");
90 let fonts = pdf::fonts::load_fonts(&mut doc).unwrap();
91 let config = Config::test_default();
92 let mut builder = pdf::create_builder(&config, fonts);
93 let entries: Vec<_> = (0..100)
94 .map(|i| make_entry("src/file.rs", i * 10, i + 5))
95 .collect();
96 super::render(&mut builder, &entries);
97 }
98}