summaryrefslogtreecommitdiff
path: root/crates/typst-library/src/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'crates/typst-library/src/pdf')
-rw-r--r--crates/typst-library/src/pdf/embed.rs86
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())