html_to_pdf_lib/
lib.rs

1use printpdf::*;
2use scraper::{Html, Selector};
3use std::fs::File;
4use std::io::BufWriter;
5use std::path::Path;
6use anyhow::{Context, Result};
7
8// Convert HTML to plain text
9fn html_to_text(html: &str) -> String {
10    let document = Html::parse_document(html);
11    let body_selector = Selector::parse("body").unwrap();
12    let mut text_content = String::new();
13
14    // Select and process body content
15    if let Some(body) = document.select(&body_selector).next() {
16        for node in body.text() {
17            text_content.push_str(node.trim());
18            text_content.push('\n'); // Add a newline for each text block
19        }
20    }
21
22    text_content
23}
24
25// Convert plain text to PDF
26pub fn html_to_pdf(html: &str, output_path: &Path) -> Result<()> {
27    let text = html_to_text(html);
28    let (document, page1, layer1) = PdfDocument::new("HTML to PDF", Mm(210.0), Mm(297.0), "Layer 1");
29
30    // Load a built-in font and create an indirect font reference
31    let font = document.add_builtin_font(BuiltinFont::Helvetica)
32        .context("Failed to add built-in font")?;
33    let font_size = 12.0;
34    let mut y_position = 287.0; // Start near the top of the page
35
36    // Prepare file output
37    let file = File::create(output_path).context("Failed to create output file")?;
38    let mut buffer = BufWriter::new(file);
39
40    // Get the current page's layer
41    let mut current_layer = document.get_page(page1).get_layer(layer1);
42
43    // Render text onto the PDF
44    for line in text.lines() {
45        if !line.trim().is_empty() {
46            // Ensure text fits within the page
47            if y_position < 10.0 {
48                // Create a new page if necessary
49                let (new_page, new_layer) = document.add_page(Mm(210.0), Mm(297.0), "New Page");
50                current_layer = document.get_page(new_page).get_layer(new_layer);
51                y_position = 287.0; // Reset y-position on new page
52            }
53
54            // Add the text to the PDF
55            current_layer.use_text(line, font_size, Mm(10.0), Mm(y_position), &font);
56            y_position -= font_size + 2.0; // Move to the next line
57        }
58    }
59
60    // Save the PDF and ensure it's written
61    document.save(&mut buffer).context("Failed to save PDF")?;
62
63    Ok(())
64}