4个版本 (2个重大更改)

0.3.0 2023年9月5日
0.2.0 2023年9月3日
0.1.1 2023年8月27日
0.1.0 2023年8月27日

#234 in 模板引擎


用于 invoicero

MIT 协议

28KB
322

简单PDF生成器

Rust库,用于将HTML5文件转换为PDF。这是simple-pdf-generator的Rust版本simple-pdf-generator

安装

这是一个通过crates.io提供的Rust库。

使用cargo add命令进行安装

$ cargo add simple_pdf_generator

功能

简单PDF生成器

  • 支持 Option 类型;
  • 支持自定义CSS和JS;
  • 在HTML模板中填充自定义字段;
  • 清理值以防止XSS攻击;
  • 可以自动生成动态表格。

限制

  • 由于 chromiumoxide 没有实现基于Chromium的浏览器的自动下载,您必须手动安装它

快速入门

为了有一个模板,您必须创建一个使用 PdfTemplate derive 的结构体

use simple_pdf_generator::{Asset, AssetType};
use simple_pdf_generator_derive::PdfTemplate;

struct Example {
    id: i64,
    name: Option<String>,
    opt_value: Option<String>,
    surname: String,
    is_true: bool,
}

并添加HTML文件

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title></title>
    </head>

    <body>
        <div class="container">
            <div class="row">
                <div class="col">Id</div>
                <div class="col">%%id%%</div>

                <div class="col">Name</div>
                <div class="col">%%name%%</div>

                <div class="col">Opt Value</div>
                <div class="col">%%opt_value%%</div>

                <div class="col">Surname</div>
                <div class="col">%%surname%%</div>

                <div class="col">Is True</div>
                <div class="col">%%is_true%%</div>
            </div>
        </div>
    </body>
</html>

现在您可以使用 Example 结构体生成PDF文件

use std::env;

use simple_pdf_generator::{Asset, AssetType};
use simple_pdf_generator_derive::PdfTemplate;

#[tokio::main]
async fn main() {
    // fill the struct
    let example = Example {
        id: 1,
        name: Some("Foo".to_string()),
        opt_value: None,
        surname: "Bar".to_string(),
        is_true: true,
    };

    // get the html template path
    let html_path = env::current_dir()
        .unwrap()
        .join("test_suite")
        .join("src/template/index.html");

    // inject some assets, in this case the bootstrap css
    let assets = [Asset {
        path: env::current_dir()
            .unwrap()
            .join("test_suite")
            .join("src/template/css/bootstrap.min.css"),
        r#type: AssetType::Style,
    }];

    // generate the pdf file
    let pdf_buf = example.generate_pdf(html_path, &assets).await;
    tokio::fs::write("example.pdf", pdf_buf).await.expect("Unable to write file");
}

生成表格

为了生成一个表格,您必须在数据属性上使用 PdfTableData

use std::env;

use serde::Serialize;
use simple_pdf_generator::{Asset, AssetType};
use simple_pdf_generator_derive::PdfTemplate;

struct Example {
    id: i64,
    name: Option<String>,
    opt_value: Option<String>,
    surname: String,
    is_true: bool,
    #[PdfTableData]
    my_table: Vec<MyTableData>,
}

#[derive(Serialize)]
struct MyTableData {
    index: u8,
    name: String,
    surname: String,
    email: String,
}

#[tokio::main]
async fn main() {
    // fill the struct
    let example = Example {
        id: 1,
        name: Some("Foo".to_string()),
        opt_value: None,
        surname: "Bar".to_string(),
        is_true: true,
        my_table: vec![
            MyTableData {
                index: 1,
                name: "James".to_string(),
                surname: "Smith".to_string(),
                email: "[email protected]".to_string(),
            },
            MyTableData {
                index: 2,
                name: "Robert".to_string(),
                surname: "Johnson".to_string(),
                email: "[email protected]".to_string(),
            },
        ],
    };

    // get the html template path
    let html_path = env::current_dir()
        .unwrap()
        .join("test_suite")
        .join("src/template/index.html");

    // inject some assets, in this case the bootstrap css
    let assets = [Asset {
        path: env::current_dir()
            .unwrap()
            .join("test_suite")
            .join("src/template/css/bootstrap.min.css"),
        r#type: AssetType::Style,
    }];

    // define the print options
    let print_options = PrintOptions {
        paper_width: Some(210.0), // A4 paper size in mm
        paper_height: Some(297.0), // A4 paper size in mm
        margin_top: Some(10.0), // 10mm margin
        margin_bottom: Some(10.0), // 10mm margin
        margin_left: Some(10.0), // 10mm margin
        margin_right: Some(10.0), // 10mm margin
        ..PrintOptions::default()
    };

    // generate the pdf file
    let pdf_buf = example.generate_pdf(html_path, &assets, &print_options).await;
    tokio::fs::write("example.pdf", pdf_buf).await.expect("Unable to write file");
}

在HTML文件中写入以下内容

<inject-table items="my_table">
    <inject-column prop="index" label="#" />
    <inject-column prop="name" label="Name" />
    <inject-column prop="surname" label="Surname" />
    <inject-column prop="email" label="Email" />
</inject-table>

API

目的 HTML使用
PdfTemplate 定义包含HTML占位符值的结构体 %%prop_name%%
PdfTableData 定义表格数据。必须是 serde::Serialize 结构体的向量 <inject-table items="prop_name">
    <inject-column prop="struct_prop_name" label="Something"/>
</inject-table>

generate_pdf

async generate_pdf(
    html_path: std::path::PathBuf,
    assets: &[simple_pdf_generator::Asset],
    print_options: &simple_pdf_generator::PrintOptions
) -> std::result::Result<Vec<u8>, simple_pdf_generator::SimplePdfGeneratorError>

返回一个PDF文件作为 Vec<u8>

参数 描述
html_path: std::path::PathBuf PDF输出目录
资产: &[simple_pdf_generator::资产类型] 资产向量(可以为空 vec![]
打印选项: &simple_pdf_generator::PrintOptions 打印选项(具有默认值 PrintOptions::default()

simple_pdf_generator::SimplePdfGeneratorError

enum SimplePdfGeneratorError {
    BrowserError(String),
    IoError(String),
    PdfError(String),
}

simple_pdf_generator::{资产类型,AssetType}

struct Asset {
    pub path: PathBuf,
    pub r#type: AssetType,
}

enum AssetType {
    Style,
    Script,
}

### simple_pdf_generator::PrintOptions

struct PrintOptions {
    pub print_background: bool,
    pub paper_width: Option<f64>,
    pub paper_height: Option<f64>,
    pub margin_top: Option<f64>,
    pub margin_bottom: Option<f64>,
    pub margin_left: Option<f64>,
    pub margin_right: Option<f64>,
    pub page_ranges: Option<String>,
    pub prefer_css_page_size: bool,
    pub landscape: bool,
}

人员

本库由以下人员开发

许可证

MIT

依赖项

~16–33MB
~535K SLoC