Combine multiple PDF files into one and insert a generated table of contents page with clickable bookmark links.
// 1.0-compatible equivalent — uses real PdfMerger API.
// Per-input custom TOC titles are tracked for 1.1 (see note above).
use pdfluent::prelude::*;
fn main() -> Result<()> {
let merged = PdfMerger::new()
.add(PdfDocument::open("chapter1.pdf")?)
.add(PdfDocument::open("chapter2.pdf")?)
.add(PdfDocument::open("chapter3.pdf")?)
.with_bookmarks(BookmarkMergeStrategy::Concat)
.build()?;
merged.save("book.pdf")?;
Ok(())
}Each MergeInput specifies a source file and an optional title used for the TOC entry and bookmark.
use pdfluent::merge::MergeInput;
let inputs = vec![
MergeInput::from_file("section1.pdf").title("Section 1"),
MergeInput::from_file("section2.pdf").title("Section 2"),
MergeInput::from_file("appendix.pdf").title("Appendix"),
];Enable TOC generation and optionally configure the TOC page style, font, and bookmark depth.
use pdfluent::merge::MergeOptions;
let opts = MergeOptions::new()
.generate_toc(true)
.toc_title("Table of Contents")
.toc_position(pdfluent::merge::TocPosition::FirstPage)
.generate_bookmarks(true);Document::merge_with_options returns a new Document. The TOC page is inserted at the position specified in the options.
let merged = Document::merge_with_options(inputs, opts)?;The merge operation adds bookmark entries that match the TOC. Verify they are present.
for bookmark in merged.outlines() {
println!(
"'{}' -> page {}",
bookmark.title(),
bookmark.destination_page() + 1,
);
}Write the final merged file.
merged.save("merged_with_toc.pdf")?;No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.