Skip to main content

vite_static_derive/
lib.rs

1#![warn(clippy::pedantic)]
2#![allow(clippy::ref_option)]
3
4use proc_macro::TokenStream;
5use quote::quote;
6use syn::{DeriveInput, parse_macro_input};
7
8mod embedding;
9mod parse;
10
11use parse::parse_manifest_input;
12
13fn internal_manifest_derive(input: DeriveInput) -> syn::Result<TokenStream> {
14    let settings = parse_manifest_input(&input)?;
15
16    let ident = input.ident;
17
18    let manifest = embedding::get_manifest(&settings.vite_dist.0)
19        .map_err(|err| syn::Error::new(settings.vite_dist.1, format!("{err:#}")))?;
20
21    let (key_output_pairs, chunks) = embedding::generate_manifest_data(&manifest);
22
23    let expanded = quote! {
24        const KEY_OUTPUT_PAIRS: &[(&str, &str)] = &[ #(#key_output_pairs),* ];
25        const CHUNKS: &[(&str, &::vite_static::StaticManifestChunk)] = &[ #(#chunks),* ];
26
27        impl ::vite_static::Manifest<'static> for #ident {
28            fn manifest_key_output_pairs(&self) -> &'static [(&'static str, &'static str)] {
29                KEY_OUTPUT_PAIRS
30            }
31            fn manifest_chunks(&self) -> &'static [(&'static str, &'static ::vite_static::StaticManifestChunk)] {
32                CHUNKS
33            }
34            fn boxed(&self) -> Box<dyn ::vite_static::Manifest<'static>> { Box::new(#ident) }
35        }
36    };
37    Ok(TokenStream::from(expanded))
38}
39
40/// Derive macro, that generates `Manifest` trait implementation from Vite project and
41/// `.vite/manifest.json`.
42///
43/// See examples.
44///
45/// ```rust
46/// #[derive(Manifest)]
47/// #[vite_dist = "path/to/vite-project/dist"]
48/// struct MyViteStatic;
49/// ```
50///
51/// # Options
52///
53/// In all string options, you can use `env:YOUR_ENV_VAR` syntax to reference environment variable.
54///
55/// - `#[vite_dist = "..."]` _(required)_
56///
57///   Specify path to built Vite project files (aka `dist/` folder).
58///
59///   This folder must contain `.vite/manifest.json` file. (enabled by `build.manifest` vite config)
60///
61///   The value can be:
62///
63///     - Relative path (to `Cargo.toml`): `examples/vite-project/dist`
64///     - Absolute path: `/home/user/Projects/vite-project/dist`
65///     - Environment variable with relative/absolute path: `env:YOUR_ENV_VAR`
66#[proc_macro_derive(Manifest, attributes(vite_dist))]
67pub fn manifest_derive(input: TokenStream) -> TokenStream {
68    let input = parse_macro_input!(input as DeriveInput);
69
70    match internal_manifest_derive(input) {
71        Ok(stream) => stream,
72        Err(err) => TokenStream::from(err.to_compile_error()),
73    }
74}