asset/
lib.rs

1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
3
4pub use manganis_macro::*;
5
6/// An image asset that is built by the [`mg!`] macro
7#[derive(Debug, PartialEq, PartialOrd, Clone, Hash)]
8pub struct ImageAsset {
9    /// The path to the image
10    path: &'static str,
11    /// A low quality preview of the image that is URL encoded
12    preview: Option<&'static str>,
13    /// A caption for the image
14    caption: Option<&'static str>,
15}
16
17impl ImageAsset {
18    /// Creates a new image asset
19    pub const fn new(path: &'static str) -> Self {
20        Self {
21            path,
22            preview: None,
23            caption: None,
24        }
25    }
26
27    /// Returns the path to the image
28    pub const fn path(&self) -> &'static str {
29        self.path
30    }
31
32    /// Returns the preview of the image
33    pub const fn preview(&self) -> Option<&'static str> {
34        self.preview
35    }
36
37    /// Sets the preview of the image
38    pub const fn with_preview(self, preview: Option<&'static str>) -> Self {
39        Self { preview, ..self }
40    }
41
42    /// Returns the caption of the image
43    pub const fn caption(&self) -> Option<&'static str> {
44        self.caption
45    }
46
47    /// Sets the caption of the image
48    pub const fn with_caption(self, caption: Option<&'static str>) -> Self {
49        Self { caption, ..self }
50    }
51}
52
53impl std::ops::Deref for ImageAsset {
54    type Target = str;
55
56    fn deref(&self) -> &Self::Target {
57        self.path
58    }
59}
60
61impl std::fmt::Display for ImageAsset {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        self.path.fmt(f)
64    }
65}
66
67#[cfg(feature = "dioxus")]
68impl dioxus_core::prelude::IntoAttributeValue for ImageAsset {
69    fn into_value(self) -> dioxus_core::AttributeValue {
70        dioxus_core::AttributeValue::Text(self.path.to_string())
71    }
72}
73
74/// The type of an image. You can read more about the tradeoffs between image formats [here](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types)
75#[derive(Debug, PartialEq, PartialOrd, Clone, Copy, Hash)]
76pub enum ImageType {
77    /// A png image. Png images cannot contain transparency and tend to compress worse than other formats
78    Png,
79    /// A jpg image. Jpg images can contain transparency and tend to compress better than png images
80    Jpg,
81    /// A webp image. Webp images can contain transparency and tend to compress better than jpg images
82    Webp,
83    /// An avif image. Avif images can compress slightly better than webp images but are not supported by all browsers
84    Avif,
85}
86
87/// A builder for an image asset. This must be used in the [`mg!`] macro.
88///
89/// > **Note**: This will do nothing outside of the `mg!` macro
90pub struct ImageAssetBuilder;
91
92impl ImageAssetBuilder {
93    /// Sets the format of the image
94    ///
95    /// > **Note**: This will do nothing outside of the `mg!` macro
96    ///
97    /// The choosing the right format can make your site load much faster. Webp and avif images tend to be a good default for most images
98    ///
99    /// ```rust
100    /// const _: manganis::ImageAsset = manganis::mg!(image("https://avatars.githubusercontent.com/u/79236386?s=48&v=4").format(ImageType::Webp));
101    /// ```
102    #[allow(unused)]
103    pub const fn format(self, format: ImageType) -> Self {
104        Self
105    }
106
107    /// Sets the size of the image
108    ///
109    /// > **Note**: This will do nothing outside of the `mg!` macro
110    ///
111    /// If you only use the image in one place, you can set the size of the image to the size it will be displayed at. This will make the image load faster
112    ///
113    /// ```rust
114    /// const _: manganis::ImageAsset = manganis::mg!(image("https://avatars.githubusercontent.com/u/79236386?s=48&v=4").size(512, 512));
115    /// ```
116    #[allow(unused)]
117    pub const fn size(self, x: u32, y: u32) -> Self {
118        Self
119    }
120
121    /// Make the image use a low quality preview
122    ///
123    /// > **Note**: This will do nothing outside of the `mg!` macro
124    ///
125    /// A low quality preview is a small version of the image that will load faster. This is useful for large images on mobile devices that may take longer to load
126    ///
127    /// ```rust
128    /// const _: manganis::ImageAsset = manganis::mg!(image("https://avatars.githubusercontent.com/u/79236386?s=48&v=4").low_quality_preview());
129    /// ```
130    #[allow(unused)]
131    pub const fn low_quality_preview(self) -> Self {
132        Self
133    }
134
135    /// Make the image preloaded
136    ///
137    /// > **Note**: This will do nothing outside of the `mg!` macro
138    ///
139    /// Preloading an image will make the image start to load as soon as possible. This is useful for images that will be displayed soon after the page loads or images that may not be visible immediately, but should start loading sooner
140    ///
141    /// ```rust
142    /// const _: manganis::ImageAsset = manganis::mg!(image("https://avatars.githubusercontent.com/u/79236386?s=48&v=4").preload());
143    /// ```
144    #[allow(unused)]
145    pub const fn preload(self) -> Self {
146        Self
147    }
148
149    /// Make the image URL encoded
150    ///
151    /// > **Note**: This will do nothing outside of the `mg!` macro
152    ///
153    /// URL encoding an image inlines the data of the image into the URL. This is useful for small images that should load as soon as the html is parsed
154    ///
155    /// ```rust
156    /// const _: manganis::ImageAsset = manganis::mg!(image("https://avatars.githubusercontent.com/u/79236386?s=48&v=4").url_encoded());
157    /// ```
158    #[allow(unused)]
159    pub const fn url_encoded(self) -> Self {
160        Self
161    }
162}
163
164/// Create an image asset from the local path or url to the image
165///
166/// > **Note**: This will do nothing outside of the `mg!` macro
167///
168/// You can collect images which will be automatically optimized with the image builder:
169/// ```rust
170/// const _: manganis::ImageAsset = manganis::mg!(image("rustacean-flat-gesture.png"));
171/// ```
172/// Resize the image at compile time to make the assets file size smaller:
173/// ```rust
174/// const _: manganis::ImageAsset = manganis::mg!(image("rustacean-flat-gesture.png").size(52, 52));
175/// ```
176/// Or convert the image at compile time to a web friendly format:
177/// ```rust
178/// const _: manganis::ImageAsset = manganis::mg!(image("rustacean-flat-gesture.png").format(ImageType::Avif).size(52, 52));
179/// ```
180/// You can mark images as preloaded to make them load faster in your app
181/// ```rust
182/// const _: manganis::ImageAsset = manganis::mg!(image("rustacean-flat-gesture.png").preload());
183/// ```
184#[allow(unused)]
185pub const fn image(path: &'static str) -> ImageAssetBuilder {
186    ImageAssetBuilder
187}
188
189/// A builder for a font asset. This must be used in the `mg!` macro.
190///
191/// > **Note**: This will do nothing outside of the `mg!` macro
192pub struct FontAssetBuilder;
193
194impl FontAssetBuilder {
195    /// Sets the font family of the font
196    ///
197    /// > **Note**: This will do nothing outside of the `mg!` macro
198    ///
199    /// ```rust
200    /// const _: &str = manganis::mg!(font().families(["Roboto"]));
201    /// ```
202    #[allow(unused)]
203    pub const fn families<const N: usize>(self, families: [&'static str; N]) -> Self {
204        Self
205    }
206
207    /// Sets the font weight of the font
208    ///
209    /// > **Note**: This will do nothing outside of the `mg!` macro
210    ///
211    /// ```rust
212    /// const _: &str = manganis::mg!(font().families(["Roboto"]).weights([200]));
213    /// ```
214    #[allow(unused)]
215    pub const fn weights<const N: usize>(self, weights: [u32; N]) -> Self {
216        Self
217    }
218
219    /// Sets the subset of text that the font needs to support. The font will only include the characters in the text which can make the font file size significantly smaller
220    ///
221    /// > **Note**: This will do nothing outside of the `mg!` macro
222    ///
223    /// ```rust
224    /// const _: &str = manganis::mg!(font().families(["Roboto"]).weights([200]).text("Hello, world!"));
225    /// ```
226    #[allow(unused)]
227    pub const fn text(self, text: &'static str) -> Self {
228        Self
229    }
230
231    /// Sets the [display](https://www.w3.org/TR/css-fonts-4/#font-display-desc) of the font. The display control what happens when the font is unavailable
232    ///
233    /// > **Note**: This will do nothing outside of the `mg!` macro
234    ///
235    /// ```rust
236    /// const _: &str = manganis::mg!(font().families(["Roboto"]).weights([200]).text("Hello, world!").display("swap"));
237    /// ```
238    #[allow(unused)]
239    pub const fn display(self, display: &'static str) -> Self {
240        Self
241    }
242}
243
244/// Create a font asset
245///
246/// > **Note**: This will do nothing outside of the `mg!` macro
247///
248/// You can use the font builder to collect fonts that will be included in the final binary from google fonts
249/// ```rust
250/// const _: &str = manganis::mg!(font().families(["Roboto"]));
251/// ```
252/// You can specify weights for the fonts
253/// ```rust
254/// const _: &str = manganis::mg!(font().families(["Roboto"]).weights([200]));
255/// ```
256/// Or set the text to only include the characters you need
257/// ```rust
258/// const _: &str = manganis::mg!(font().families(["Roboto"]).weights([200]).text("Hello, world!"));
259/// ```
260#[allow(unused)]
261pub const fn font() -> FontAssetBuilder {
262    FontAssetBuilder
263}
264
265/// Create an file asset from the local path or url to the file
266///
267/// > **Note**: This will do nothing outside of the `mg!` macro
268///
269/// The file builder collects an arbitrary file. Relative paths are resolved relative to the package root
270/// ```rust
271/// const _: &str = manganis::mg!(file("src/asset.txt"));
272/// ```
273/// Or you can use URLs to read the asset at build time from a remote location
274/// ```rust
275/// const _: &str = manganis::mg!(file("https://rustacean.net/assets/rustacean-flat-happy.png"));
276/// ```
277#[allow(unused)]
278pub const fn file(path: &'static str) -> ImageAssetBuilder {
279    ImageAssetBuilder
280}
281
282/// A trait for something that can be used in the `mg!` macro
283///
284/// > **Note**: These types will do nothing outside of the `mg!` macro
285pub trait ForMgMacro: __private::Sealed + Sync + Send {}
286
287mod __private {
288    use super::*;
289
290    pub trait Sealed {}
291
292    impl Sealed for ImageAssetBuilder {}
293    impl Sealed for FontAssetBuilder {}
294    impl Sealed for &'static str {}
295}
296
297impl ForMgMacro for ImageAssetBuilder {}
298impl ForMgMacro for FontAssetBuilder {}
299impl ForMgMacro for &'static str {}