dioxus_cli_opt/
file.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use anyhow::Context;
use manganis_core::{AssetOptions, CssAssetOptions, ImageAssetOptions, JsAssetOptions};
use std::path::Path;

use crate::css::process_scss;

use super::{
    css::process_css, folder::process_folder, image::process_image, js::process_js,
    json::process_json,
};

/// Process a specific file asset with the given options reading from the source and writing to the output path
pub fn process_file_to(
    options: &AssetOptions,
    source: &Path,
    output_path: &Path,
) -> anyhow::Result<()> {
    process_file_to_with_options(options, source, output_path, false)
}

/// Process a specific file asset with additional options
pub(crate) fn process_file_to_with_options(
    options: &AssetOptions,
    source: &Path,
    output_path: &Path,
    in_folder: bool,
) -> anyhow::Result<()> {
    // If the file already exists, then we must have a file with the same hash
    // already. The hash has the file contents and options, so if we find a file
    // with the same hash, we probably already created this file in the past
    if output_path.exists() {
        return Ok(());
    }
    if let Some(parent) = output_path.parent() {
        if !parent.exists() {
            std::fs::create_dir_all(parent)?;
        }
    }

    // Processing can be slow. Write to a temporary file first and then rename it to the final output path. If everything
    // goes well. Without this, the user could quit in the middle of processing and the file will look complete to the
    // caching system even though it is empty.
    let temp_path = output_path.with_file_name(format!(
        "partial.{}",
        output_path
            .file_name()
            .unwrap_or_default()
            .to_string_lossy()
    ));

    match options {
        AssetOptions::Unknown => match source.extension().map(|e| e.to_string_lossy()).as_deref() {
            Some("css") => {
                process_css(&CssAssetOptions::new(), source, &temp_path)?;
            }
            Some("scss" | "sass") => {
                process_scss(&CssAssetOptions::new(), source, &temp_path)?;
            }
            Some("js") => {
                process_js(&JsAssetOptions::new(), source, &temp_path, !in_folder)?;
            }
            Some("json") => {
                process_json(source, &temp_path)?;
            }
            Some("jpg" | "jpeg" | "png" | "webp" | "avif") => {
                process_image(&ImageAssetOptions::new(), source, &temp_path)?;
            }
            Some(_) | None => {
                if source.is_dir() {
                    process_folder(source, &temp_path)?;
                } else {
                    let source_file = std::fs::File::open(source)?;
                    let mut reader = std::io::BufReader::new(source_file);
                    let output_file = std::fs::File::create(&temp_path)?;
                    let mut writer = std::io::BufWriter::new(output_file);
                    std::io::copy(&mut reader, &mut writer).with_context(|| {
                        format!(
                            "Failed to write file to output location: {}",
                            temp_path.display()
                        )
                    })?;
                }
            }
        },
        AssetOptions::Css(options) => {
            process_css(options, source, &temp_path)?;
        }
        AssetOptions::Js(options) => {
            process_js(options, source, &temp_path, !in_folder)?;
        }
        AssetOptions::Image(options) => {
            process_image(options, source, &temp_path)?;
        }
        AssetOptions::Folder(_) => {
            process_folder(source, &temp_path)?;
        }
        _ => {
            tracing::warn!("Unknown asset options: {:?}", options);
        }
    }

    // If everything was successful, rename the temp file to the final output path
    std::fs::rename(temp_path, output_path)?;

    Ok(())
}