Rust排版引擎插件库typst-realize的使用,高效实现文档生成与格式化

Rust排版引擎插件库typst-realize的使用,高效实现文档生成与格式化

Typst是一个基于标记的新型排版系统,设计目标是拥有LaTeX的强大功能,同时更加易于学习和使用。Typst具有以下特点:

  • 内置常见格式化任务的标记
  • 灵活的函數处理其他需求
  • 紧密集成的脚本系统
  • 数学排版、文献管理等功能
  • 增量编译带来的快速编译时间
  • 出错时提供友好的错误信息

Typst示例代码

#set page(width: 10cm, height: auto)
#set heading(numbering: "1.")

= Fibonacci sequence
The Fibonacci sequence is defined through the
recurrence relation $F_n = F_(n-1) + F_(n-2)$.
It can also be expressed in _closed form:_

$ F_n = round(1 / sqrt(5) phi.alt^n), quad
  phi.alt = (1 + sqrt(5)) / 2 $

#let count = 8
#let nums = range(1, count + 1)
#let fib(n) = (
  if n <= 2 { 1 }
  else { fib(n - 1) + fib(n - 2) }
)

The first #count numbers of the sequence are:

#align(center, table(
  columns: count,
  ..nums.map(n => $F_#n$),
  ..nums.map(n => str(fib(n))),
))

Rust中使用typst-realize的完整示例

use typst_realize::{
    compile_to_pdf, 
    FontPaths,
    World,
};

// 创建一个包含多种格式元素的Typst文档
const TYPST_DOC: &str = r#"
#set page(width: 10cm, height: auto)
#set heading(numbering: "1.")

= 完整示例文档
这是使用typst-realize生成的完整文档示例。

## 章节标题
这是一个章节内容示例,展示文本格式化功能。

* 项目符号列表项1
* 项目符号列表项2
* 项目符号列表项3

## 数学公式
我们可以轻松插入各种数学公式:
$ \sum_{i=1}^n i = \frac{n(n+1)}{2} $

$ \int_a^b f(x)dx = F(b) - F(a) $

## 表格和布局
#align(center, [
  #table(
    columns: 3,
    [姓名], [年龄], [职业],
    [张三], [28], [工程师],
    [李四], [32], [设计师],
  )
  
  #box(width: 100%, height: 0.5em)
  
  #lorem(50)
])

## 条件内容
#let show_extra = true
#if show_extra {
  这是条件显示的内容
}
"#;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建SystemWorld实例,用于提供字体等资源
    let world = typst_realize::SystemWorld::new(FontPaths::new());
    
    // 编译Typst文档为PDF二进制数据
    let pdf_data = compile_to_pdf(&world, TYPST_DOC)?;
    
    // 将PDF数据写入文件
    std::fs::write("complete_example.pdf", pdf_data)?;
    
    println!("完整示例PDF文档已生成: complete_example.pdf");
    Ok(())
}

安装typst-realize

在您的Rust项目中添加typst-realize依赖:

[dependencies]
typst-realize = "0.13.1"

或者运行以下Cargo命令:

cargo add typst-realize

设计原则

Typst遵循三个核心设计原则:

  1. 一致性带来的简单性:在Typst中学习一种操作后,可以轻松将这种知识迁移到其他操作中
  2. 组合性带来的强大功能:通过少量可组合的功能实现灵活性,而非为每件事提供单独的功能
  3. 增量带来的性能:所有Typst语言特性都支持增量编译,以实现快速预览

Typst-realize作为Typst的Rust接口,让您可以在Rust应用程序中轻松集成文档生成功能,特别适合需要程序化生成格式化文档的场景。


1 回复

Rust排版引擎插件库typst-realize使用指南

介绍

typst-realize是一个基于Rust的排版引擎插件库,它构建在typst排版系统之上,专注于高效实现文档生成与格式化。这个库特别适合需要自动化生成格式精美文档的场景,如报告生成、发票制作、批量文档处理等。

typst-realize的主要特点:

  • 高性能的文档渲染引擎
  • 简洁的API设计
  • 支持动态内容生成
  • 可定制的文档样式
  • 与Rust生态无缝集成

安装方法

在Cargo.toml中添加依赖:

[dependencies]
typst-realize = "0.5"  # 请使用最新版本

完整示例代码

1. 创建带样式的完整文档

use typst_realize::{Document, Style, Table};

fn main() {
    // 创建样式
    let style = Style::new()
        .font("SimSun")  // 使用宋体支持中文
        .font_size(14.0)
        .line_spacing(1.8)
        .margin(2.0);  // 2厘米页边距

    // 创建表格数据
    let sales_data = vec![
        ("产品A".into(), 1250.50),
        ("产品B".into(), 3200.75),
        ("产品C".into(), 980.25),
    ];

    // 生成表格
    let mut table = Table::new()
        .header(["产品名称", "销售额"])
        .alignments(&["left", "right"]);
    
    for (product, amount) in sales_data {
        table = table.row([product, format!("¥{:.2}", amount)]);
    }

    // 创建完整文档
    let doc = Document::new()
        .title("2023年销售报告")
        .author("销售部")
        .date("2023-12-31")
        .style(style)
        .content(r#"
            # 2023年度销售报告

            ## 销售概览
            
            本年度的销售情况如下:

            [table]

            ## 总结

            本年度总销售额达到XXXX元,同比增长XX%。
            
            ### 注意事项
            
            [warning]
        "#)
        .component(WarningBox {
            message: "数据仅供参考,正式报告以财务部为准".into(),
        })
        .content(table.to_string());

    // 渲染PDF
    doc.render_to_file("annual_report.pdf").unwrap();
}

// 自定义警告框组件
struct WarningBox {
    message: String,
}

impl typst_realize::Component for WarningBox {
    fn render(&self) -> String {
        format!(
            r#"
            #box(
                fill: yellow.lighten(90%),
                border: 1pt solid orange,
                inset: 10pt,
                radius: 5pt,
                [⚠️ **重要提示**: {}]
            )
            "#,
            self.message
        )
    }
}

2. 使用模板生成合同文档

use typst_realize::{Document, Template};
use serde_json::json;

fn main() {
    // 编译并缓存模板
    let template = Template::compile("contract_template.typ").unwrap();

    // 合同数据
    let contract_data = json!({
        "title": "技术开发合同",
        "contract_no": "TD2023001",
        "parties": {
            "party_a": "XX科技有限公司",
            "party_b": "YY信息技术有限公司"
        },
        "effective_date": "2023-01-01",
        "terms": [
            "项目内容:开发企业管理系统",
            "开发周期:6个月",
            "合同金额:人民币150,000元",
            "付款方式:分期付款",
            "违约责任:按合同法执行"
        ]
    });

    // 应用模板生成文档
    let doc = template.apply_context(contract_data).unwrap();
    
    // 保存PDF
    doc.render_to_file("tech_contract.pdf").unwrap();
}

3. 批量生成文档

use typst_realize::{Document, BatchRender};
use std::path::Path;

fn generate_invoice(data: &(String, f64, String)) -> Document {
    Document::new()
        .title(format!("发票-{}", data.2))
        .content(format!(
            r#"
            # 发票

            **客户**: {}  
            **金额**: ¥{:.2}  
            **发票编号**: {}  
            **日期**: {}

            [payment_info]
            "#,
            data.0, data.1, data.2, "2023-12-15"
        ))
}

fn main() {
    // 准备批量数据
    let invoices = vec![
        ("客户A".into(), 1250.50, "INV2023001".into()),
        ("客户B".into(), 3200.75, "INV2023002".into()),
        ("客户C".into(), 980.25, "INV2023003".into()),
    ];

    // 创建批量渲染任务
    let mut batch = BatchRender::new()
        .parallel(true)  // 启用并行渲染
        .timeout(30);    // 30秒超时

    // 添加文档到批量任务
    for (i, data) in invoices.iter().enumerate() {
        let doc = generate_invoice(data);
        let output_path = format!("invoices/invoice_{}.pdf", i + 1);
        batch.add_document(doc, output_path);
    }

    // 确保输出目录存在
    std::fs::create_dir_all("invoices").unwrap();

    // 执行批量渲染
    match batch.execute() {
        Ok(_) => println!("批量发票生成完成!"),
        Err(e) => eprintln!("生成失败: {}", e),
    }
}

最佳实践建议

  1. 项目结构组织
// 推荐的项目结构:
// src/
//   components/     // 自定义组件
//     warning_box.rs
//     invoice_header.rs
//   templates/      // 模板文件
//     contract.typ
//     report.typ
//   models/         // 数据模型
//     invoice.rs
//     report.rs
//   main.rs         // 主程序
  1. 错误处理优化
use typst_realize::RenderError;

fn render_document() -> Result<(), RenderError> {
    let doc = Document::new()
        .content("# 重要文档")
        .render_to_file("important.pdf")?;
    
    Ok(())
}

fn main() {
    if let Err(e) = render_document() {
        eprintln!("文档渲染失败: {}", e);
        std::process::exit(1);
    }
}
  1. 配置管理
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct AppConfig {
    default_font: String,
    output_dir: String,
    template_dir: String,
}

fn load_config() -> AppConfig {
    // 可以从配置文件加载
    AppConfig {
        default_font: "SimSun".into(),
        output_dir: "output".into(),
        template_dir: "templates".into(),
    }
}
回到顶部