screenplay_doc_parser_rs/
lib.rs1use std::fmt::Error;
2
3pub mod screenplay_document;
4pub mod pdf_document;
5
6pub mod pdf_parser;
7
8#[cfg(test)]
9mod tests {
10
11    use crate::{pdf_document::{get_us_letter_default_indentation_pts, ElementIndentationsPoints, PDFDocument, TextPosition}, screenplay_document::SPType};
12
13    use super::*;
14
15    fn _get_line_with_word(text: String, element_indentation: f64, y_height_inches: Option<f64>) -> pdf_document::Line {
16        let mut new_word = pdf_document::Word::default();
17
18        if let Some(inches) = y_height_inches {
19            new_word = _get_test_pdfword(text, element_indentation, y_height_inches);
20        }
21        else {
22            new_word = _get_test_pdfword(text, element_indentation, None);
23        }
24
25        let new_line:pdf_document::Line = pdf_document::Line { 
26            words: vec![new_word] 
27        };
28        new_line
29    }
30
31    fn _get_test_pdfword(text: String, element_indentation: f64, y_height_inches: Option<f64>) -> pdf_document::Word {
32        let mut y_height_pts = 0.0;
33        if let Some(inches) = y_height_inches {
34            y_height_pts = 72.0 * inches;
35        }
36        else {
37            y_height_pts = 3.0 * 72.0;
38        }
39        
40        let new_word: pdf_document::Word = pdf_document::Word {
41            text: text.clone(), 
42            text_bbox_width: text.len() as f64 * 7.2 as f64, 
43            position: TextPosition {
44                x: element_indentation,
45                y: y_height_pts
46            }, 
47            font_name: None, 
48            font_size: 12.0, 
49            font_character_width: 7.2 
50        };
51        new_word
52    }
53
54    fn it_works() {
56        let mut mock_pdf:pdf_document::PDFDocument = PDFDocument::default();
57        let mut new_page = pdf_document::Page::default();
58        
59        let action_word  = _get_test_pdfword(
60            "Action!".to_string(), 72.0*1.5, None);
61        let mut new_line: pdf_document::Line = pdf_document::Line::default();
62        new_line.words.push(action_word);
63        new_page.lines.push(new_line);
64        mock_pdf.pages.push(new_page);
65        let parse_result_doc = pdf_parser::get_screenplay_doc_from_pdf_obj(mock_pdf, 
67        None,
68        None);
69        if let Some(document) = parse_result_doc {
70            if let Some(first_page) = document.pages.first() {
71                println!("First page exists!");
72                if let Some(first_line) = first_page.lines.first() {
73                    println!("First line exists!");
74                    if let Some (first_word) = first_line.text_elements.first() {
75                        println!("First Word exists!");
76                    }
77                } 
78            }
79
80            let word_text = document.pages.first().unwrap()
81            .lines.first().unwrap()
82            .text_elements.first().unwrap().text.clone();
83            println!("Text: {}", word_text);
84        }
85
86    }
87
88    #[test]
89    fn all_screenplay_element_types() {
90
91        let indentations = get_us_letter_default_indentation_pts();
99
100
101        println!(" ------ Testing Screenplay Element Types ------ ");
102        println!("");
103
104        let mut mock_pdf:pdf_document::PDFDocument = PDFDocument::default();
105        let mut new_page = pdf_document::Page::default();
106        
107        new_page.lines.push(
108            _get_line_with_word("Action!".to_string(), 
109            indentations.action, 
110            None)
111        );
112        new_page.lines.push(
113            _get_line_with_word("CHARACTER".to_string(), 
114            indentations.character, 
115            None)
116        );
117        new_page.lines.push(
118            _get_line_with_word("(wryly)".to_string(), 
119            indentations.parenthetical, 
120            None)
121        );
122        new_page.lines.push(
123            _get_line_with_word("Dialogue".to_string(), 
124            indentations.dialogue, 
125            None)
126        );
127
128        let pn: String = "256ABC.".to_string();
129
130        let mut page_num_line = pdf_document::Line::default();
134        page_num_line.words.push(
135            _get_test_pdfword(
136                "(26/04/25)".to_string(), 
137                indentations.character, 
138                Some(indentations.top))
139        );
140        page_num_line.words.push(
141            _get_test_pdfword(pn.clone(), 
142            (7.5*72.0) - (7.2 * pn.len() as f64), 
143            Some(indentations.top))
144        );
145
146        new_page.lines.push(
147            page_num_line
148        );
149
150        let mut revised_line = pdf_document::Line::default();
152        
153        revised_line.words.push(_get_test_pdfword("revised_scn".to_string(), 
154            indentations.action,
155            None
156        ));
157        revised_line.words.push(_get_test_pdfword("*".to_string(), 
158        (7.5*72.0)+(7.2*2.0), 
159        None));
160        new_page.lines.push(revised_line);
161
162        
163        new_page.lines.push(
169            _get_line_with_word("(MORE)".to_string(), 
170            indentations.parenthetical, 
171            Some(60.0))
172        );
173        
174        let mut scene_heading_line = pdf_document::Line::default();
176        scene_heading_line.words.push(
177            _get_test_pdfword(
178                "INT.".to_string(), indentations.action, 
179                None)
180        );
181        let mut last_word: String = "INT.".to_string();
182        let mut last_word_pos: f64 = scene_heading_line.words.last().unwrap().position.x;
183        let mut _get_word_with_offset_from_previous = |text: String| {
184            let new_x_offset = (last_word.len() as f64 * 7.2) + 7.2
186            + last_word_pos;
187            
188            let new_word =_get_test_pdfword(
190                text.clone(), 
191                new_x_offset, 
192                None);
193
194            last_word = text.clone();
195            last_word_pos = new_x_offset;
196            return new_word;
197
198        };
199
200        scene_heading_line.words.push(
201            _get_word_with_offset_from_previous("HOUSE".to_string(),)
202        );
203        scene_heading_line.words.push(
204            _get_word_with_offset_from_previous("-".to_string(),)
205        );
206        scene_heading_line.words.push(
207            _get_word_with_offset_from_previous("DAY".to_string(), )
208        );
209        scene_heading_line.words.push(
210            _get_word_with_offset_from_previous("-".to_string(), )
211        );
212        scene_heading_line.words.push(
213            _get_word_with_offset_from_previous("CONTINUOUS".to_string(), )
214        );
215        scene_heading_line.words.push(
216            _get_test_pdfword(
217                "*46G*".to_string(), indentations.right, None)
218        );
219        new_page.lines.push(scene_heading_line);
220
221        mock_pdf.pages.push(new_page);
241
242        let parsed_doc = pdf_parser::get_screenplay_doc_from_pdf_obj(
243            mock_pdf, 
244            None,
245            None
246        ).unwrap();
247
248        println!(
249            "\n-----\n\nPage number: {:>8} | Rev. label/date(?): {:12} | {}\n", 
250            format!("{:?}", parsed_doc.pages.first().unwrap().page_number),
251            format!("{:?}",parsed_doc.pages.first().unwrap().revision_label),
252            format!("{:?}",parsed_doc.pages.first().unwrap().revision_date),
253
254        );
255
256        let lines = &parsed_doc.pages.first().unwrap()
257        .lines;
258
259        for line in lines {
262            
263            println!(
264                "LT: {:-<70} \nScene Num: {:8} \nRevised: {}",
265                
266                
267                if let Some(l_type) = line.line_type {
268                    format!("{:?}",l_type).strip_prefix("SP_").unwrap().to_string()
269                } else {
270                    format!("{:?}",SPType::NONE)
271                },
272                if let Some(sc_num) = line.scene_number.clone() {
273                    sc_num
274                } else {
275                    "None".to_string()
276                }
277                ,
278                if line.revised {
279                    "Y"
280                } else {
281                    "N"
282                },
283            );
284            println!("{:^30}|{:^8}{:^8}|{:^8}", "Element",  "x","y", "Text");
285            println!("{:-<58}", "  -");
286            for el in &line.text_elements {
288                println!("     {:24} | {:.2}, {:.2} | '{}'",
289                    if let Some(l_type) = el.element_type.clone() {
290                        format!("{:?}",l_type).strip_prefix("SP_").unwrap().to_string()
291                    } else {
292                        format!("{:?}",SPType::NONE)
293                    },
294                    el.element_position.unwrap().x,
295                    el.element_position.unwrap().y,
296                    el.text,
297                );
298            }
299            println!("");
300
301
302        }
303
304
305
306    }
307}