Add support for file embedding

This commit is contained in:
Laurenz Stampfl 2025-03-10 11:05:56 +01:00
parent ea021a29e3
commit 9622906e69
3 changed files with 64 additions and 10 deletions

View File

@ -1,5 +1,15 @@
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
use crate::embed::embed_files;
use crate::image::handle_image;
use crate::link::handle_link;
use crate::metadata::build_metadata;
use crate::outline::build_outline;
use crate::page::PageLabelExt;
use crate::shape::handle_shape;
use crate::text::handle_text;
use crate::util::{convert_path, display_font, AbsExt, TransformExt};
use crate::PdfOptions;
use krilla::annotation::Annotation; use krilla::annotation::Annotation;
use krilla::configure::{Configuration, PdfVersion, ValidationError}; use krilla::configure::{Configuration, PdfVersion, ValidationError};
use krilla::destination::{NamedDestination, XyzDestination}; use krilla::destination::{NamedDestination, XyzDestination};
@ -19,16 +29,6 @@ use typst_library::text::{Font, Lang};
use typst_library::visualize::{Geometry, Paint}; use typst_library::visualize::{Geometry, Paint};
use typst_syntax::Span; use typst_syntax::Span;
use crate::image::handle_image;
use crate::link::handle_link;
use crate::metadata::build_metadata;
use crate::outline::build_outline;
use crate::page::PageLabelExt;
use crate::shape::handle_shape;
use crate::text::handle_text;
use crate::util::{convert_path, display_font, AbsExt, TransformExt};
use crate::PdfOptions;
pub fn convert( pub fn convert(
typst_document: &PagedDocument, typst_document: &PagedDocument,
options: &PdfOptions, options: &PdfOptions,
@ -53,6 +53,7 @@ pub fn convert(
); );
convert_pages(&mut gc, &mut document)?; convert_pages(&mut gc, &mut document)?;
embed_files(&typst_document, &mut document)?;
document.set_outline(build_outline(&gc)); document.set_outline(build_outline(&gc));
document.set_metadata(build_metadata(&gc)); document.set_metadata(build_metadata(&gc));

View File

@ -0,0 +1,52 @@
use krilla::embed::{AssociationKind, EmbeddedFile};
use krilla::Document;
use std::sync::Arc;
use typst_library::diag::{bail, SourceResult};
use typst_library::foundations::{NativeElement, StyleChain};
use typst_library::layout::PagedDocument;
use typst_library::pdf::{EmbedElem, EmbeddedFileRelationship};
use typst_syntax::Span;
pub(crate) fn embed_files(
typst_doc: &PagedDocument,
document: &mut Document,
) -> SourceResult<()> {
let elements = typst_doc.introspector.query(&EmbedElem::elem().select());
for elem in &elements {
let embed = elem.to_packed::<EmbedElem>().unwrap();
let derived_path = &embed.path.derived;
let path = derived_path.to_string();
let mime_type =
embed.mime_type(StyleChain::default()).clone().map(|s| s.to_string());
let description = embed
.description(StyleChain::default())
.clone()
.map(|s| s.to_string());
let association_kind = match embed.relationship(StyleChain::default()) {
None => AssociationKind::Unspecified,
Some(e) => match e {
EmbeddedFileRelationship::Source => AssociationKind::Source,
EmbeddedFileRelationship::Data => AssociationKind::Data,
EmbeddedFileRelationship::Alternative => AssociationKind::Alternative,
EmbeddedFileRelationship::Supplement => AssociationKind::Supplement,
},
};
let data: Arc<dyn AsRef<[u8]> + Send + Sync> = Arc::new(embed.data.clone());
let file = EmbeddedFile {
path,
mime_type,
description,
association_kind,
data: data.into(),
compress: true,
};
if document.embed_file(file).is_none() {
bail!(Span::detached(), "attempted to embed file {derived_path} twice");
}
}
Ok(())
}

View File

@ -1,6 +1,7 @@
//! Exporting Typst documents to PDF. //! Exporting Typst documents to PDF.
mod convert; mod convert;
mod embed;
mod image; mod image;
mod link; mod link;
mod metadata; mod metadata;