Combine multiple PDF files into one and insert a generated table of contents page with clickable bookmark links.
use pdfluent::{PdfDocument, PdfMerger, BookmarkMergeStrategy};
fn main() -> pdfluent::Result<()> {
let merged = PdfMerger::new()
.add(PdfDocument::open("intro.pdf")?)
.add(PdfDocument::open("body.pdf")?)
.with_bookmarks(BookmarkMergeStrategy::Concat)
.with_page_labels(true)
.build()?;
merged.save("merged.pdf")?;
Ok(())
}Each MergeInput specifies a source file and an optional title used for the TOC entry and bookmark.
use pdfluent::{PdfDocument, PdfMerger, BookmarkMergeStrategy};
let merger = PdfMerger::new()
.add(PdfDocument::open("section1.pdf")?)
.add(PdfDocument::open("section2.pdf")?)
.add(PdfDocument::open("appendix.pdf")?);Enable TOC generation and optionally configure the TOC page style, font, and bookmark depth.
// Concatenate each source's bookmarks under a top-level entry (navigation TOC).
// Page labels preserve each section's original numbering.
let merger = merger
.with_bookmarks(BookmarkMergeStrategy::Concat)
.with_page_labels(true);Document::merge_with_options returns a new Document. The TOC page is inserted at the position specified in the options.
let merged = merger.build()?;The merge operation adds bookmark entries that match the TOC. Verify they are present.
for bookmark in merged.outlines()? {
println!("'{}' -> page {:?}", bookmark.title, bookmark.page);
}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.