typst_library/model/asset.rs
1use typst_macros::elem;
2
3use crate::diag::bail;
4use crate::foundations::{BundlePath, Bytes, ShowFn, Str, cast};
5use crate::introspection::Locatable;
6
7/// Adds a custom file to a bundle.
8///
9/// This function creates a single file in a @reference:bundle[bundle], from
10/// @bytes[raw byte data]. Unlike @document[documents], assets will be emitted
11/// as-is without undergoing compilation.
12///
13/// The `asset` function can be combined with @read to copy a file from the
14/// project into the output bundle. The first argument to `asset` defines the
15/// output path for the asset in the bundle, while the path passed to `read`
16/// defines where in the project to read the data from.
17///
18/// ```typ
19/// // Copy the file `styles.css` into the bundle.
20/// #asset("styles.css", read("styles.css"))
21/// ```
22///
23/// That said, `asset` is not tied to `read`. You can also generate bytes
24/// directly or use a function like @json.encode to emit serialized data.
25///
26/// ```typ
27/// // Emits a JSON file with the number
28/// // of headings in the document.
29/// #context {
30/// let headings = query(heading)
31/// let meta = (
32/// count: headings.len(),
33/// )
34/// asset("meta.json", json.encode(meta))
35/// }
36///
37/// #document("doc.pdf")[
38/// = Introduction
39/// = Conclusion
40/// ]
41/// ```
42///
43/// This would emit a `meta.json` file with the following contents into the
44/// resulting bundle:
45///
46/// ```json
47/// {
48/// "count": 2
49/// }
50/// ```
51///
52/// This function may only be used in the @reference:bundle[bundle] target.
53#[elem(Locatable)]
54pub struct AssetElem {
55 /// The path in the bundle at which the asset will be placed.
56 ///
57 /// May contain interior slashes, in which case intermediate directories
58 /// will be automatically created.
59 #[required]
60 pub path: BundlePath,
61
62 /// The raw data that will be written into the file at the specified path.
63 ///
64 /// If a string is given, it will be encoded using UTF-8.
65 #[required]
66 pub data: AssetData,
67}
68
69pub const ASSET_UNSUPPORTED_RULE: ShowFn<AssetElem> = |elem, _, _| {
70 bail!(
71 elem.span(),
72 "assets are only supported in the bundle target";
73 // TODO: Support for CLI-specific hints would be nice.
74 hint: "try enabling the bundle target";
75 )
76};
77
78/// The raw data for an asset.
79#[derive(Debug, Clone, Eq, PartialEq, Hash)]
80pub struct AssetData(pub Bytes);
81
82cast! {
83 AssetData,
84 self => self.0.into_value(),
85 v: Str => Self(Bytes::from_string(v)),
86 v: Bytes => Self(v),
87}