dioxus_cli_opt/
file.rs

1use anyhow::Context;
2use manganis_core::{AssetOptions, CssAssetOptions, ImageAssetOptions, JsAssetOptions};
3use std::path::Path;
4
5use crate::css::process_scss;
6
7use super::{
8    css::process_css, folder::process_folder, image::process_image, js::process_js,
9    json::process_json,
10};
11
12/// Process a specific file asset with the given options reading from the source and writing to the output path
13pub fn process_file_to(
14    options: &AssetOptions,
15    source: &Path,
16    output_path: &Path,
17) -> anyhow::Result<()> {
18    process_file_to_with_options(options, source, output_path, false)
19}
20
21/// Process a specific file asset with additional options
22pub(crate) fn process_file_to_with_options(
23    options: &AssetOptions,
24    source: &Path,
25    output_path: &Path,
26    in_folder: bool,
27) -> anyhow::Result<()> {
28    // If the file already exists, then we must have a file with the same hash
29    // already. The hash has the file contents and options, so if we find a file
30    // with the same hash, we probably already created this file in the past
31    if output_path.exists() {
32        return Ok(());
33    }
34    if let Some(parent) = output_path.parent() {
35        if !parent.exists() {
36            std::fs::create_dir_all(parent)?;
37        }
38    }
39
40    // Processing can be slow. Write to a temporary file first and then rename it to the final output path. If everything
41    // goes well. Without this, the user could quit in the middle of processing and the file will look complete to the
42    // caching system even though it is empty.
43    let temp_path = output_path.with_file_name(format!(
44        "partial.{}",
45        output_path
46            .file_name()
47            .unwrap_or_default()
48            .to_string_lossy()
49    ));
50
51    match options {
52        AssetOptions::Unknown => match source.extension().map(|e| e.to_string_lossy()).as_deref() {
53            Some("css") => {
54                process_css(&CssAssetOptions::new(), source, &temp_path)?;
55            }
56            Some("scss" | "sass") => {
57                process_scss(&CssAssetOptions::new(), source, &temp_path)?;
58            }
59            Some("js") => {
60                process_js(&JsAssetOptions::new(), source, &temp_path, !in_folder)?;
61            }
62            Some("json") => {
63                process_json(source, &temp_path)?;
64            }
65            Some("jpg" | "jpeg" | "png" | "webp" | "avif") => {
66                process_image(&ImageAssetOptions::new(), source, &temp_path)?;
67            }
68            Some(_) | None => {
69                if source.is_dir() {
70                    process_folder(source, &temp_path)?;
71                } else {
72                    let source_file = std::fs::File::open(source)?;
73                    let mut reader = std::io::BufReader::new(source_file);
74                    let output_file = std::fs::File::create(&temp_path)?;
75                    let mut writer = std::io::BufWriter::new(output_file);
76                    std::io::copy(&mut reader, &mut writer).with_context(|| {
77                        format!(
78                            "Failed to write file to output location: {}",
79                            temp_path.display()
80                        )
81                    })?;
82                }
83            }
84        },
85        AssetOptions::Css(options) => {
86            process_css(options, source, &temp_path)?;
87        }
88        AssetOptions::Js(options) => {
89            process_js(options, source, &temp_path, !in_folder)?;
90        }
91        AssetOptions::Image(options) => {
92            process_image(options, source, &temp_path)?;
93        }
94        AssetOptions::Folder(_) => {
95            process_folder(source, &temp_path)?;
96        }
97        _ => {
98            tracing::warn!("Unknown asset options: {:?}", options);
99        }
100    }
101
102    // If everything was successful, rename the temp file to the final output path
103    std::fs::rename(temp_path, output_path)?;
104
105    Ok(())
106}