rumtk_web/css/
mod.rs

1/*
2 * rumtk attempts to implement HL7 and medical protocols for interoperability in medicine.
3 * This toolkit aims to be reliable, simple, performant, and standards compliant.
4 * Copyright (C) 2025  Luis M. Santos, M.D.
5 * Copyright (C) 2025  MedicalMasses L.L.C.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21use minifier::css::minify;
22use rumtk_core::strings::RUMString;
23use std::fs;
24use std::path;
25
26mod animations;
27mod basic;
28mod default;
29mod fonts;
30mod gap;
31mod index;
32
33pub const DEFAULT_OUT_CSS_DIR: &str = "./static/css";
34pub const DEFAULT_OUT_CSS: &str = "bundle.min.css";
35
36pub fn bundle_css(sources: &[&str], out_dir: &str, out_file: &str) {
37    let mut css: RUMString = RUMString::default();
38
39    css += index::BODY;
40    css += basic::BASIC_CSS;
41    css += default::DEFAULT_CSS;
42    css += fonts::FONTS_CSS;
43    css += gap::GAP_CSS;
44    css += animations::ANIMATIONS_CSS;
45
46    for source in sources {
47        let css_data = fs::read_to_string(source).unwrap_or_default();
48        css += &css_data;
49    }
50
51    fs::create_dir_all(out_dir).unwrap_or_default();
52
53    let out_path = path::Path::new(out_dir)
54        .join(out_file)
55        .with_extension("css")
56        .to_str()
57        .expect("Could not create path to CSS file!")
58        .to_string();
59
60    if let Ok(exists) = fs::exists(&out_path) {
61        if !exists {
62            let minified = minify(&css)
63                .expect("Failed to minify the CSS contents!")
64                .to_string();
65            fs::write(&out_path, minified).expect("Failed to write to CSS file!");
66        }
67    }
68}
69
70pub fn collect_css_sources(root: &str, depth: u8) -> Vec<String> {
71    let mut files = Vec::<String>::new();
72    let dirs = fs::read_dir(root).unwrap();
73    for dir_entry in dirs {
74        let dir = dir_entry.unwrap();
75        let dir_name = dir.file_name().into_string().unwrap();
76        let dir_path = dir.path().to_str().unwrap().to_string();
77        if dir_name.ends_with(".css") {
78            files.push(dir_path.clone());
79        }
80
81        if depth == 255 {
82            return files;
83        }
84
85        if dir.file_type().unwrap().is_dir() {
86            files.extend(collect_css_sources(&dir_path, depth + 1));
87        }
88    }
89
90    files
91}
92
93#[macro_export]
94macro_rules! rumtk_web_compile_css_bundle {
95    (  ) => {{
96        use $crate::css::{bundle_css, collect_css_sources};
97        use $crate::css::{DEFAULT_OUT_CSS, DEFAULT_OUT_CSS_DIR};
98        let sources = collect_css_sources(DEFAULT_OUT_CSS_DIR, 0);
99        bundle_css(&sources, DEFAULT_OUT_CSS_DIR, DEFAULT_OUT_CSS);
100    }};
101    ( $static_dir_path:expr ) => {{
102        use $crate::css::{bundle_css, collect_css_sources};
103        let sources = collect_css_sources($static_dir_path, 0);
104        bundle_css(&sources, DEFAULT_OUT_CSS_DIR, DEFAULT_OUT_CSS);
105    }};
106}