mirror of
https://github.com/typst/typst
synced 2025-08-15 15:38:33 +08:00
Add support for file embedding
This commit is contained in:
parent
ea021a29e3
commit
9622906e69
@ -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));
|
||||||
|
52
crates/typst-pdf/src/embed.rs
Normal file
52
crates/typst-pdf/src/embed.rs
Normal 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(())
|
||||||
|
}
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user