vite-static-derive 0.5.0

Derive macro support for `vite-static`
Documentation
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::Ident;

use crate::parse::ManifestSettings;

pub fn generate(ident: &Ident, settings: &ManifestSettings) -> TokenStream {
    let (vite_dist, _) = &settings.vite_dist;

    let vite_dist = if vite_dist.starts_with('/') {
        quote! { #vite_dist }
    } else {
        quote! { concat!(env!("CARGO_MANIFEST_DIR"), "/", #vite_dist) }
    };

    let vite_dist_ident = format_ident!("{}_VITE_DIST", ident);
    let manifest_ident = format_ident!("{}_MANIFEST", ident);

    quote! {
        #[allow(non_upper_case_globals)]
        const #vite_dist_ident: &str = #vite_dist;

        #[allow(non_upper_case_globals)]
        static #manifest_ident: ::std::sync::LazyLock<::vite_static::ViteManifest> =
            ::std::sync::LazyLock::new(|| {
                ::vite_static::parsing::parse_manifest(std::path::Path::new(#vite_dist_ident))
                    .unwrap_or_else(|err| panic!("{err:?}"))
            });

        impl ::vite_static::Manifest<'static> for #ident {
            fn resolve_output(&self, key: &str) -> Option<::std::borrow::Cow<'static, str>> {
                #manifest_ident
                    .get(key)
                    .map(|chunk| chunk.file.clone())
            }

            fn iter_keys(&self) -> Box<dyn Iterator<Item = &str> + '_> {
                Box::new(#manifest_ident.keys().map(|key| key.as_ref()))
            }

            fn iter_outputs(&self) -> Box<dyn Iterator<Item = &str> + '_> {
                Box::new(
                    #manifest_ident
                        .values()
                        .map(|chunk| chunk.file.as_ref()),
                )
            }

            fn chunk(
                &self,
                output: &str,
            ) -> Option<::std::borrow::Cow<'static, vite_static::ManifestChunk<'static>>> {
                #manifest_ident
                    .iter()
                    .find(|(_, chunk)| chunk.file == output)
                    .map(|(_, chunk)| {
                        let mut chunk = chunk.clone();

                        ::vite_static::parsing::read_manifest_chunk(
                            ::std::path::Path::new(#vite_dist_ident),
                            &mut chunk,
                        )
                        .unwrap_or_else(|err| panic!("{err:?}"));

                        ::std::borrow::Cow::Owned(chunk)
                    })
            }
        }
    }
}