use std::{ env, fs::{self, DirEntry, File}, io::{self, Write}, path::{Path, PathBuf}, }; fn main() -> Result<(), Box> { let out_dir = env::var("OUT_DIR").unwrap(); compile( PathBuf::from("scss/index.scss"), PathBuf::from(out_dir).join("styles.css"), )?; let here = Path::new(".").canonicalize()?; visit_dirs(&here, &handle_dir)?; Ok(()) } fn handle_dir(e: &DirEntry) -> Result<(), Box> { let path = e.path(); if path.extension().is_some() && path.extension().unwrap().eq("scss") { let mut output = path.clone(); output.set_extension("css"); compile(path, output)?; } Ok(()) } fn compile(input: PathBuf, output: PathBuf) -> Result<(), Box> { if PathBuf::from("scss/index.scss").canonicalize()?.eq(&input) { return Ok(()); } let out_dir = env::var("OUT_DIR").unwrap(); let output = PathBuf::from(out_dir).join(output.file_name().unwrap()); let mut output = File::create(output)?; let opts = grass::Options::default(); let opts = opts.style(grass::OutputStyle::Compressed); let css_text = grass::from_path(input, &opts).unwrap_or_else(|e| { panic!("Sass Error: {e:#?}"); }); output.write_all(css_text.as_bytes())?; Ok(()) } #[allow(clippy::type_complexity)] fn visit_dirs( dir: &Path, cb: &dyn Fn(&DirEntry) -> Result<(), Box>, ) -> io::Result<()> { let ignore = |pattern: &str| -> bool { dir.file_name().unwrap().eq(pattern) }; if dir.is_dir() && !ignore(".git") && !ignore("target") && !ignore("scss") { for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); if path.is_dir() { visit_dirs(&path, cb)?; } else { cb(&entry).unwrap(); } } } Ok(()) }