From 1073a592ed3059859fddccf11daddac2e34ea14a Mon Sep 17 00:00:00 2001 From: Adrien Date: Sun, 10 Mar 2024 11:40:00 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A8=20Make=20the=20Design=20System=20c?= =?UTF-8?q?olor=20tokens=20reachable=20from=20the=20rust=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The design system tokens are specified in the _base.scss file. To avoid to duplicate their value in a rust file, a new step has been added to the building process to generate the `style_vars.rs` file which make the color tokens reachable to the app. --- Cargo.toml | 2 ++ build.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index f548ef5..be469de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,3 +31,5 @@ futures = "0.3.29" [build] target = "x86_64-unknown-linux-gnu" +[build-dependencies] +regex = "1.10.3" diff --git a/build.rs b/build.rs index 30524a9..785f8c1 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,81 @@ +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.flatten() { + 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); + }; }