html2pdf_secure/
lib.rs

1//! # html2pdf-secure
2//!
3//! A Rust crate for converting HTML to password-protected PDF files.
4//!
5//! This crate provides functionality to:
6//! - Convert HTML content to PDF using headless Chrome
7//! - Add password protection to generated PDFs
8//! - Support various PDF encryption options
9//!
10//! ## Quick Start
11//!
12//! ```rust,no_run
13//! use html2pdf_secure::{Html2PdfConverter, PdfOptions, PasswordOptions};
14//!
15//! #[tokio::main]
16//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
17//!     let converter = Html2PdfConverter::new().await?;
18//!
19//!     let html = "<html><body><h1>Hello, World!</h1></body></html>";
20//!     let password_opts = PasswordOptions::new("user123", "owner456");
21//!
22//!     let pdf_data = converter
23//!         .convert_html_to_protected_pdf(html, PdfOptions::default(), password_opts)
24//!         .await?;
25//!
26//!     std::fs::write("output.pdf", pdf_data)?;
27//!     Ok(())
28//! }
29//! ```
30
31pub mod converter;
32pub mod encryption;
33pub mod error;
34pub mod options;
35
36pub use converter::Html2PdfConverter;
37pub use encryption::{PasswordOptions, EncryptionLevel, PdfPermissions};
38pub use error::{Html2PdfError, Result};
39pub use options::{PdfOptions, PageFormat, PageOrientation, PageMargins};
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[tokio::test]
46    async fn test_converter_creation() {
47        let result = Html2PdfConverter::new().await;
48        assert!(result.is_ok(), "Should be able to create converter");
49    }
50
51    #[tokio::test]
52    async fn test_html_to_pdf_conversion() {
53        let converter = Html2PdfConverter::new().await.unwrap();
54        let html = "<html><body><h1>Test</h1></body></html>";
55        let options = PdfOptions::default();
56
57        let result = converter.convert_html_to_pdf(html, options).await;
58        assert!(result.is_ok(), "Should be able to convert HTML to PDF");
59
60        let pdf_data = result.unwrap();
61        assert!(!pdf_data.is_empty(), "PDF data should not be empty");
62        assert!(pdf_data.starts_with(b"%PDF"), "Should start with PDF header");
63    }
64
65    #[test]
66    fn test_password_options() {
67        let options = PasswordOptions::new("user", "owner");
68        assert_eq!(options.user_password, "user");
69        assert_eq!(options.owner_password, "owner");
70        assert!(matches!(options.encryption_level, EncryptionLevel::Aes256));
71    }
72
73    #[test]
74    fn test_pdf_options_default() {
75        let options = PdfOptions::default();
76        assert!(matches!(options.page_format, PageFormat::A4));
77        assert!(matches!(options.orientation, PageOrientation::Portrait));
78        assert_eq!(options.scale, 1.0);
79        assert!(options.print_background);
80    }
81
82    #[test]
83    fn test_pdf_permissions() {
84        let permissions = PdfPermissions::allow_all();
85        assert!(permissions.allow_printing);
86        assert!(permissions.allow_copy);
87        assert!(permissions.allow_modify_contents);
88
89        let permissions = PdfPermissions::deny_all();
90        assert!(!permissions.allow_printing);
91        assert!(!permissions.allow_copy);
92        assert!(!permissions.allow_modify_contents);
93    }
94
95    #[test]
96    fn test_page_format_dimensions() {
97        let (width, height) = PageFormat::A4.dimensions();
98        assert!((width - 8.27).abs() < 0.01);
99        assert!((height - 11.7).abs() < 0.01);
100    }
101
102    #[test]
103    fn test_page_margins() {
104        let margins = PageMargins::uniform(2.0);
105        assert_eq!(margins.top, 2.0);
106        assert_eq!(margins.bottom, 2.0);
107        assert_eq!(margins.left, 2.0);
108        assert_eq!(margins.right, 2.0);
109
110        let margins = PageMargins::symmetric(1.0, 1.5);
111        assert_eq!(margins.top, 1.0);
112        assert_eq!(margins.bottom, 1.0);
113        assert_eq!(margins.left, 1.5);
114        assert_eq!(margins.right, 1.5);
115    }
116}