use std::env; use std::fs::File; use std::io::Write; use std::io::{self, BufRead}; use std::path::Path; use std::path::PathBuf; use regex::Regex; fn main() { // Tell Cargo to rerun this build script if any SCSS file // in the 'src' directory or its subdirectories changes. println!("cargo:rerun-if-changed=src/**/*.scss"); let out_dir = env::var("OUT_DIR").unwrap(); let style_src_path = PathBuf::from("src/_base.scss"); let style_dst_path = Path::new(&out_dir).join("style_vars.rs"); export_color_variables(&style_src_path, &style_dst_path) } // From https://doc.rust-lang.org/rust-by-example/std_misc/file/read_lines.html // The output is wrapped in a Result to allow matching on errors. // Returns an Iterator to the Reader of the lines of the file. fn read_lines

(filename: P) -> io::Result>> where P: AsRef, { let file = File::open(filename)?; Ok(io::BufReader::new(file).lines()) } #[derive(Debug)] struct CssColorVariable<'a> { name: &'a str, value: &'a str, } impl<'a> CssColorVariable<'a> { pub fn to_rust(&self) -> String { format!( "const {name}: &str = \"{value}\";", name = self.name.replace('-', "_").to_uppercase(), value = self.value ) } } fn export_color_variables(src_path: &PathBuf, dst_path: &PathBuf) { let mut dst_file = File::create(dst_path).unwrap(); if let Err(err) = dst_file.write(b"#[allow(dead_code)]\nmod style {") { println!("{}", err); return; }; let re = Regex::new(r"^\$([^:]+):[[:space:]]*#([^$]+);[[:space:]]*$").unwrap(); if let Ok(lines) = read_lines(src_path) { for line in lines.map_while(Result::ok) { let Some(groups) = re.captures(&line) else { continue; }; let var = CssColorVariable { name: &groups[1], value: &groups[2], }; let rust_export = var.to_rust(); if let Err(err) = dst_file.write_fmt(format_args!(" pub {}\n", rust_export)) { println!("{}", err); break; } } } if let Err(err) = dst_file.write(b"}\n") { println!("{}", err); }; }