♻️ Use of the SCSS variables to compute the width of the inner panels
This commit is contained in:
138
build.rs
138
build.rs
@@ -1,4 +1,5 @@
|
||||
use std::env;
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::io::{self, BufRead};
|
||||
@@ -10,14 +11,32 @@ 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");
|
||||
println!("cargo:rerun-if-changed=src/ui/**/*.scss");
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
|
||||
let style_src_path = PathBuf::from("src/ui/_base.scss");
|
||||
let style_dst_path = Path::new(&out_dir).join("style_vars.rs");
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
export_color_variables(&style_src_path, &style_dst_path)
|
||||
// Global tokens
|
||||
tasks.push(Task::new(
|
||||
PathBuf::from("src/ui/_base.scss"),
|
||||
Path::new(&out_dir).join("style_tokens.rs"),
|
||||
"style".to_string(),
|
||||
));
|
||||
// variables defined by the Panel component
|
||||
tasks.push(Task::new(
|
||||
PathBuf::from("src/ui/components/_panel.scss"),
|
||||
Path::new(&out_dir).join("style_component_panel.rs"),
|
||||
"panel".to_string(),
|
||||
));
|
||||
// Variables set by the Conversations layout
|
||||
tasks.push(Task::new(
|
||||
PathBuf::from("src/ui/layouts/conversations.scss"),
|
||||
Path::new(&out_dir).join("style_layout_conversations.rs"),
|
||||
"conversations".to_string(),
|
||||
));
|
||||
|
||||
export_variables(tasks)
|
||||
}
|
||||
|
||||
// From https://doc.rust-lang.org/rust-by-example/std_misc/file/read_lines.html
|
||||
@@ -32,14 +51,21 @@ where
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CssColorVariable<'a> {
|
||||
name: &'a str,
|
||||
value: &'a str,
|
||||
struct ColorVariable {
|
||||
name: String,
|
||||
value: String,
|
||||
}
|
||||
|
||||
impl<'a> CssColorVariable<'a> {
|
||||
pub fn to_rust(&self) -> String {
|
||||
format!(
|
||||
impl ColorVariable {
|
||||
pub fn new(name: String, value: String) -> Self {
|
||||
Self { name, value }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ColorVariable {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"const {name}: &str = \"{value}\";",
|
||||
name = self.name.replace('-', "_").to_uppercase(),
|
||||
value = self.value
|
||||
@@ -47,35 +73,83 @@ impl<'a> CssColorVariable<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
#[derive(Debug)]
|
||||
struct FloatVariable {
|
||||
name: String,
|
||||
value: f64,
|
||||
}
|
||||
|
||||
let re = Regex::new(r"^\$([^:]+):[[:space:]]*#([^$]+);[[:space:]]*$").unwrap();
|
||||
impl FloatVariable {
|
||||
pub fn new(name: String, value: f64) -> Self {
|
||||
Self { name, value }
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(lines) = read_lines(src_path) {
|
||||
for line in lines.map_while(Result::ok) {
|
||||
let Some(groups) = re.captures(&line) else {
|
||||
continue;
|
||||
};
|
||||
impl Display for FloatVariable {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"const {name}: f64 = {value};",
|
||||
name = self.name.replace('-', "_").to_uppercase(),
|
||||
value = self.value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let var = CssColorVariable {
|
||||
name: &groups[1],
|
||||
value: &groups[2],
|
||||
};
|
||||
struct Task {
|
||||
src_path: PathBuf,
|
||||
dst_path: PathBuf,
|
||||
module_name: String,
|
||||
}
|
||||
|
||||
let rust_export = var.to_rust();
|
||||
if let Err(err) = dst_file.write_fmt(format_args!(" pub {}\n", rust_export)) {
|
||||
impl Task {
|
||||
pub fn new(src_path: PathBuf, dst_path: PathBuf, module_name: String) -> Self {
|
||||
Self {
|
||||
src_path,
|
||||
dst_path,
|
||||
module_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fn export_variables(src_path: &PathBuf, dst_path: &PathBuf) {
|
||||
fn export_variables(tasks: Vec<Task>) {
|
||||
let color_re = Regex::new(r"^\$([^:]+):[[:space:]]*#([^$]+);[[:space:]]*$").unwrap();
|
||||
let variable_re = Regex::new(r"^\$([^:]+):[[:space:]]*([^;]+)[[:space:]]*;").unwrap();
|
||||
|
||||
for task in tasks {
|
||||
let mut dst_file = File::create(task.dst_path).unwrap();
|
||||
if let Err(err) = dst_file.write_fmt(format_args!(
|
||||
"#[allow(dead_code)]\nmod {} {{\n",
|
||||
task.module_name
|
||||
)) {
|
||||
println!("{}", err);
|
||||
return;
|
||||
};
|
||||
|
||||
let mut variables = Vec::<Box<dyn Display>>::new();
|
||||
if let Ok(lines) = read_lines(task.src_path) {
|
||||
for line in lines.map_while(Result::ok) {
|
||||
if let Some(groups) = color_re.captures(&line) {
|
||||
let var = ColorVariable::new(groups[1].to_string(), groups[2].to_string());
|
||||
variables.push(Box::new(var));
|
||||
} else if let Some(groups) = variable_re.captures(&line) {
|
||||
if let Ok(value) = groups[2].parse::<f64>() {
|
||||
variables.push(Box::new(FloatVariable::new(groups[1].to_string(), value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for variable in variables {
|
||||
if let Err(err) = dst_file.write_fmt(format_args!(" pub {}\n", variable)) {
|
||||
println!("{}", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(err) = dst_file.write(b"}\n") {
|
||||
println!("{}", err);
|
||||
};
|
||||
if let Err(err) = dst_file.write(b"}\n") {
|
||||
println!("{}", err);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user