Files
dioxus/packages/cli-opt/src/file.rs
T
Miles MurgawandJonathan Kelley e96550c48c Manganis CSS Modules Support (#3578)
* feat: type safe css selectors

* feat: css modules support

---------

Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
2025-04-15 14:44:22 -07:00

110 lines
4.0 KiB
Rust

use anyhow::Context;
use manganis_core::{AssetOptions, CssAssetOptions, ImageAssetOptions, JsAssetOptions};
use std::path::Path;
use crate::css::{process_css_module, 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::CssModule(options) => {
process_css_module(options, source, output_path, &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(())
}