diff options
Diffstat (limited to 'crates/typst-library/src/pdf')
| -rw-r--r-- | crates/typst-library/src/pdf/embed.rs | 86 |
1 files changed, 27 insertions, 59 deletions
diff --git a/crates/typst-library/src/pdf/embed.rs b/crates/typst-library/src/pdf/embed.rs index db498622..f9ca3ca0 100644 --- a/crates/typst-library/src/pdf/embed.rs +++ b/crates/typst-library/src/pdf/embed.rs @@ -1,13 +1,10 @@ use ecow::EcoString; -use typst_syntax::{Span, Spanned}; +use typst_syntax::Spanned; -use crate::diag::{At, SourceResult, StrResult}; +use crate::diag::{At, SourceResult}; use crate::engine::Engine; -use crate::foundations::{ - elem, func, scope, Cast, Content, NativeElement, Packed, Show, StyleChain, -}; +use crate::foundations::{elem, Bytes, Cast, Content, Derived, Packed, Show, StyleChain}; use crate::introspection::Locatable; -use crate::loading::Readable; use crate::World; /// A file that will be embedded into the output PDF. @@ -33,33 +30,40 @@ use crate::World; /// - This element is ignored if exporting to a format other than PDF. /// - File embeddings are not currently supported for PDF/A-2, even if the /// embedded file conforms to PDF/A-1 or PDF/A-2. -#[elem(scope, Show, Locatable)] +#[elem(Show, Locatable)] pub struct EmbedElem { - /// Path to a file to be embedded. + /// Path of the file to be embedded. /// - /// For more details, see the [Paths section]($syntax/#paths). + /// Must always be specified, but is only read from if no data is provided + /// in the following argument. + /// + /// For more details about paths, see the [Paths section]($syntax/#paths). #[required] #[parse( let Spanned { v: path, span } = - args.expect::<Spanned<EcoString>>("path to the file to be embedded")?; + args.expect::<Spanned<EcoString>>("path")?; let id = span.resolve_path(&path).at(span)?; - let data = engine.world.file(id).at(span)?; - path + // The derived part is the project-relative resolved path. + let resolved = id.vpath().as_rootless_path().to_string_lossy().replace("\\", "/").into(); + Derived::new(path.clone(), resolved) )] #[borrowed] - pub path: EcoString, - - /// The resolved project-relative path. - #[internal] - #[required] - #[parse(id.vpath().as_rootless_path().to_string_lossy().replace("\\", "/").into())] - pub resolved_path: EcoString, + pub path: Derived<EcoString, EcoString>, - /// The raw file data. - #[internal] + /// Raw file data, optionally. + /// + /// If omitted, the data is read from the specified path. + #[positional] + // Not actually required as an argument, but always present as a field. + // We can't distinguish between the two at the moment. #[required] - #[parse(Readable::Bytes(data))] - pub data: Readable, + #[parse( + match args.find::<Bytes>()? { + Some(data) => data, + None => engine.world.file(id).at(span)?, + } + )] + pub data: Bytes, /// The relationship of the embedded file to the document. /// @@ -75,42 +79,6 @@ pub struct EmbedElem { pub description: Option<EcoString>, } -#[scope] -impl EmbedElem { - /// Decode a file embedding from bytes or a string. - #[func(title = "Embed Data")] - fn decode( - /// The call span of this function. - span: Span, - /// The path that will be written into the PDF. Typst will not read from - /// this path since the data is provided in the following argument. - path: EcoString, - /// The data to embed as a file. - data: Readable, - /// The relationship of the embedded file to the document. - #[named] - relationship: Option<Option<EmbeddedFileRelationship>>, - /// The MIME type of the embedded file. - #[named] - mime_type: Option<Option<EcoString>>, - /// A description for the embedded file. - #[named] - description: Option<Option<EcoString>>, - ) -> StrResult<Content> { - let mut elem = EmbedElem::new(path.clone(), path, data); - if let Some(description) = description { - elem.push_description(description); - } - if let Some(mime_type) = mime_type { - elem.push_mime_type(mime_type); - } - if let Some(relationship) = relationship { - elem.push_relationship(relationship); - } - Ok(elem.pack().spanned(span)) - } -} - impl Show for Packed<EmbedElem> { fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> { Ok(Content::empty()) |
