1pub mod html;
2
3use crate::api::Presentation;
4use crate::oxml::presentation::PresentationReader;
5use crate::generator::{SlideContent, Shape, ShapeType, TableBuilder, TableRow, TableCell};
6use crate::exc::Result;
7
8pub use html::{parse_html, parse_html_with_options, HtmlParseOptions, Html2Ppt};
9
10pub fn import_pptx(path: &str) -> Result<Presentation> {
12 let reader = PresentationReader::open(path)?;
13 let mut presentation = Presentation::new();
14
15 if let Some(title) = &reader.info().title {
16 presentation = presentation.title(title);
17 }
18
19 for parsed_slide in reader.get_all_slides()? {
20 let mut content = SlideContent::new(parsed_slide.title.as_deref().unwrap_or(""));
21
22 for text in parsed_slide.body_text {
24 content = content.add_bullet(&text);
25 }
26
27 for parsed_shape in parsed_slide.shapes {
29 if !parsed_shape.is_title && !parsed_shape.is_body {
30 let mut shape = Shape::new(
31 map_shape_type(&parsed_shape.shape_type),
32 parsed_shape.x.max(0) as u32,
33 parsed_shape.y.max(0) as u32,
34 parsed_shape.width.max(0) as u32,
35 parsed_shape.height.max(0) as u32
36 );
37
38 let text = parsed_shape.text();
40 if !text.is_empty() {
41 shape = shape.with_text(&text);
42 }
43
44 content.shapes.push(shape);
45 }
46 }
47
48 for parsed_table in parsed_slide.tables {
50 let col_count = parsed_table.rows.first().map(|r| r.len()).unwrap_or(0);
52 if col_count == 0 { continue; }
53
54 let col_widths = vec![1828800; col_count];
56
57 let mut table_builder = TableBuilder::new(col_widths);
58 for row in parsed_table.rows {
59 let cells: Vec<TableCell> = row.into_iter()
60 .map(|cell| TableCell::new(&cell.text))
61 .collect();
62 let table_row = TableRow::new(cells);
63 table_builder = table_builder.add_row(table_row);
64 }
65
66 if content.table.is_none() {
68 content.table = Some(table_builder.build());
69 content.has_table = true;
70 }
71 }
72
73 presentation = presentation.add_slide(content);
74 }
75
76 Ok(presentation)
77}
78
79fn map_shape_type(type_name: &Option<String>) -> ShapeType {
80 if let Some(name) = type_name {
81 match name.as_str() {
82 "rect" => ShapeType::Rectangle,
83 "roundRect" => ShapeType::RoundedRectangle,
84 "ellipse" => ShapeType::Ellipse,
85 "triangle" => ShapeType::Triangle,
86 "rtTriangle" => ShapeType::RightTriangle,
87 "diamond" => ShapeType::Diamond,
88 "pentagon" => ShapeType::Pentagon,
89 "hexagon" => ShapeType::Hexagon,
90 "octagon" => ShapeType::Octagon,
91 "star5" => ShapeType::Star5,
92 "rightArrow" => ShapeType::RightArrow,
93 _ => ShapeType::Rectangle, }
95 } else {
96 ShapeType::Rectangle
97 }
98}