easypdf_markdown/table/
detector.rs1use crate::{MarkdownProcessorCapabilities, MarkdownWarning, PdfMarkdownProcessor};
4use easypdf_core::PdfInput;
5use easypdf_core::Result;
6use easypdf_core::{PdfBlock, PdfDocumentModel, PdfPageModel};
7
8use super::config::TableDetectionConfig;
9use super::heuristic::detect_table_region;
10
11#[derive(Clone, Debug)]
35pub struct TableDetectorProcessor {
36 config: TableDetectionConfig,
37}
38
39impl TableDetectorProcessor {
40 #[must_use]
42 pub fn new() -> Self {
43 Self {
44 config: TableDetectionConfig::default(),
45 }
46 }
47
48 #[must_use]
50 pub fn with_config(config: TableDetectionConfig) -> Self {
51 Self { config }
52 }
53}
54
55impl Default for TableDetectorProcessor {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl PdfMarkdownProcessor for TableDetectorProcessor {
62 fn capabilities(&self) -> MarkdownProcessorCapabilities {
63 MarkdownProcessorCapabilities::new().with_table_detection()
64 }
65
66 fn process(
67 &self,
68 _input: &PdfInput,
69 document: PdfDocumentModel,
70 ) -> Result<(PdfDocumentModel, Vec<MarkdownWarning>)> {
71 let mut new_pages = Vec::with_capacity(document.page_count());
72
73 for page in document.pages() {
74 let new_page = process_page(page, &self.config);
75 new_pages.push(new_page);
76 }
77
78 Ok((
79 PdfDocumentModel::new(document.metadata().clone(), new_pages),
80 Vec::new(),
81 ))
82 }
83}
84
85fn process_page(page: &PdfPageModel, config: &TableDetectionConfig) -> PdfPageModel {
87 let blocks = page.blocks();
88 let mut new_blocks = Vec::new();
89 let mut i = 0;
90
91 while i < blocks.len() {
92 if let Some(region) = detect_table_region(blocks, i, config) {
93 let source = *blocks[i].source();
95 new_blocks.push(PdfBlock::table(region.headers, region.rows, source));
96 i = region.end_index + 1;
97 } else {
98 new_blocks.push(blocks[i].clone());
99 i += 1;
100 }
101 }
102
103 let mut new_page = PdfPageModel::new(page.index());
105 if let (Some(w), Some(h)) = (page.width_pt(), page.height_pt()) {
106 new_page = new_page.with_dimensions(w, h);
107 }
108 new_page = new_page.with_rotation(page.rotation());
109 for block in new_blocks {
110 new_page = new_page.with_block(block);
111 }
112 new_page
113}