Skip to content
90 changes: 62 additions & 28 deletions edge-frame/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ pub mod serve {
#[cfg(feature = "assets-prepare")]
pub mod prepare {
use std::{
env, fs, io,
env,
fs::{self, DirEntry},
io,
iter::repeat,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -260,15 +262,21 @@ pub mod prepare {

for (index, output_file) in output_files.iter().enumerate() {
let file_name = output_file.file_name().unwrap().to_str().unwrap();
let output_folder = output_file
.parent()
.unwrap()
.strip_prefix(&output_dir)
.unwrap();
Comment thread
DaneSlattery marked this conversation as resolved.
Outdated

if file_name == "__empty__" {
println!("cargo:rustc-env={}_EDGE_FRAME_ASSET_URI_{}=", module, index,);
} else {
let file = output_folder.join(file_name);
println!(
"cargo:rustc-env={}_EDGE_FRAME_ASSET_URI_{}=/{}",
module,
index,
output_file.file_name().unwrap().to_str().unwrap()
file.display()
);
}

Expand All @@ -283,40 +291,66 @@ pub mod prepare {
Ok(())
}

fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry) -> PathBuf) -> anyhow::Result<Vec<PathBuf>> {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn visit_files(path: &Path) -> anyhow::Result<Vec<PathBuf>> {
    if path.is_file() {
        Ok(vec![path.to_owned()])
    } else {
        let mut paths = Vec::new();
        for entry in fs::read_dir(dir)? {
            paths.extend(visit_paths(entry?.path())?);
        }

        Ok(paths)
    }
}

Once you have this, you can leave the current compress_file almost intact, and only change the code that derives the compressed file path, as it can no longer use output_dir.join(format!("{}.gz", file.file_name().to_str().unwrap())); but something just a tad more complicated, so that it preserves the relative file path to the assets dir into the output dir, and appends a ".gz" suffix.

Copy link
Copy Markdown
Author

@DaneSlattery DaneSlattery Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but something just a tad more complicated

I think this is the logic in compress_file, so this could work. I can't currently test this because I can't build it on my machine thanks to anymap :-( ,

error[E0804]: cannot add auto trait `Send` to dyn bound via pointer cast                                                                                                                                   
   --> C:\Users\biopl\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\anymap-1.0.0-beta.2\src\any.rs:37:40
    |
 37 |                 unsafe { Box::from_raw(raw as *mut $t) }

Copy link
Copy Markdown
Author

@DaneSlattery DaneSlattery Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I fixed this with a patch, and upstreamed some stuff to yewdux-middleware

let mut output_files = vec![];
if dir.is_dir() {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
output_files.extend(visit_dirs(&path, cb)?);
} else {
output_files.push(cb(&entry));
}
}
}
Ok(output_files)
}

pub fn compress(
assets_dir: impl AsRef<Path>,
output_dir: impl AsRef<Path>,
track: impl Fn(&Path),
) -> anyhow::Result<Vec<PathBuf>> {
let assets_dir = assets_dir.as_ref();
let output_dir = output_dir.as_ref();

let output_files = fs::read_dir(assets_dir)?
Comment thread
DaneSlattery marked this conversation as resolved.
.filter_map(|file| file.ok())
.filter(|file| file.metadata().map(|md| md.is_file()).unwrap_or(false))
.map(|file| {
track(&file.path());

let output_file =
output_dir.join(format!("{}.gz", file.file_name().to_str().unwrap()));

track(&output_file);

fs::create_dir_all(output_dir).unwrap();

io::copy(
&mut fs::File::open(file.path()).unwrap(),
&mut GzEncoder::new(
fs::File::create(&output_file).unwrap(),
Compression::best(),
),
)
.unwrap();

output_file
})
.collect::<Vec<_>>();
let output_files = visit_dirs(assets_dir, &|w| {
compress_file(&track, output_dir, assets_dir, w)
})?;

Ok(output_files)
}

/// Compress and write file
///
/// # Panics
///
/// Panics if .
fn compress_file(
track: impl Fn(&Path),
output_dir: &Path,
root: &Path,
file: &fs::DirEntry,
) -> PathBuf {
track(&file.path());
let output_folder =
output_dir.join(file.path().parent().unwrap().strip_prefix(root).unwrap());
let output_file = output_dir.join(format!(
"{}.gz",
file.path().strip_prefix(root).unwrap().display()
));
// let output_file = output_dir.join(format!("{}.gz", file.file_name().to_str().unwrap()));
Comment thread
DaneSlattery marked this conversation as resolved.
Outdated

track(&output_file);

fs::create_dir_all(output_folder).unwrap();

io::copy(
&mut fs::File::open(file.path()).unwrap(),
&mut GzEncoder::new(fs::File::create(&output_file).unwrap(), Compression::best()),
)
.unwrap();

output_file
}
}