2023-02-08 20:49:05 +01:00
|
|
|
use serde::Deserialize;
|
2023-04-09 16:58:21 +02:00
|
|
|
use std::{
|
|
|
|
fs::{self, read_to_string, remove_dir_all},
|
|
|
|
path::PathBuf,
|
|
|
|
};
|
|
|
|
|
|
|
|
use glob::glob;
|
|
|
|
use minify_html::{minify, Cfg};
|
|
|
|
use std::{fs::File, io::Write, path::Path};
|
2023-02-08 20:49:05 +01:00
|
|
|
|
2023-02-09 11:42:33 +01:00
|
|
|
#[derive(Deserialize, Clone, Default)]
|
2023-04-09 15:19:23 +02:00
|
|
|
pub struct FileConfig {
|
2023-02-09 11:36:22 +01:00
|
|
|
pub scheme: Option<String>,
|
|
|
|
pub port: Option<u16>,
|
2023-02-08 22:14:57 +01:00
|
|
|
pub mail: Option<String>,
|
|
|
|
pub lang: Option<String>,
|
2023-02-16 21:59:04 +01:00
|
|
|
pub onion: Option<String>,
|
2023-02-08 20:49:05 +01:00
|
|
|
}
|
|
|
|
|
2023-04-09 15:19:23 +02:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Config {
|
|
|
|
pub fc: FileConfig,
|
2023-04-09 16:58:21 +02:00
|
|
|
pub static_location: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
struct AskamaConfig {
|
|
|
|
general: AskamaConfigGeneral,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
struct AskamaConfigGeneral {
|
|
|
|
dirs: Vec<String>,
|
2023-04-09 15:19:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FileConfig {
|
2023-02-16 15:58:43 +01:00
|
|
|
fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
scheme: Some("http".to_string()),
|
|
|
|
port: Some(8080),
|
2023-04-09 15:19:23 +02:00
|
|
|
..FileConfig::default()
|
2023-02-16 15:58:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn complete(a: Self) -> Self {
|
|
|
|
// Default config
|
2023-04-09 15:19:23 +02:00
|
|
|
let d = FileConfig::new();
|
2023-02-16 15:58:43 +01:00
|
|
|
|
|
|
|
/// Return the default value if nothing is value is none
|
|
|
|
fn test<T>(val: Option<T>, default: Option<T>) -> Option<T> {
|
|
|
|
if val.is_some() {
|
|
|
|
val
|
|
|
|
} else {
|
|
|
|
default
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Self {
|
|
|
|
scheme: test(a.scheme, d.scheme),
|
|
|
|
port: test(a.port, d.port),
|
|
|
|
mail: test(a.mail, d.mail),
|
|
|
|
lang: test(a.lang, d.lang),
|
2023-02-16 21:59:04 +01:00
|
|
|
onion: test(a.onion, d.onion),
|
2023-02-16 15:58:43 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-09 15:19:23 +02:00
|
|
|
fn get_file_config(file_path: &str) -> FileConfig {
|
2023-02-09 11:42:33 +01:00
|
|
|
match fs::read_to_string(file_path) {
|
2023-02-08 20:49:05 +01:00
|
|
|
Ok(file) => match toml::from_str(&file) {
|
2023-04-09 15:19:23 +02:00
|
|
|
Ok(stored_config) => FileConfig::complete(stored_config),
|
2023-02-08 20:49:05 +01:00
|
|
|
Err(file_error) => {
|
|
|
|
panic!("Error in config file: {file_error}");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(_) =>
|
|
|
|
// No config file
|
|
|
|
{
|
2023-04-09 15:19:23 +02:00
|
|
|
FileConfig::new()
|
2023-02-08 20:49:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-09 15:19:23 +02:00
|
|
|
|
2023-04-09 16:58:21 +02:00
|
|
|
fn get_askama_config() -> AskamaConfig {
|
|
|
|
toml::from_str(&read_to_string("askama.toml").unwrap()).unwrap()
|
|
|
|
}
|
|
|
|
|
2023-04-09 15:19:23 +02:00
|
|
|
pub fn get_config(file_path: &str) -> Config {
|
|
|
|
let internal_config = get_file_config(file_path);
|
|
|
|
|
2023-04-09 16:58:21 +02:00
|
|
|
let static_dir = "static".to_string();
|
2023-04-09 17:35:15 +02:00
|
|
|
let templates_dirs = get_askama_config().general.dirs;
|
|
|
|
if templates_dirs.len() != 1 {
|
|
|
|
panic!("Too many templates directories")
|
|
|
|
}
|
|
|
|
let mut template_data = templates_dirs[0].split('/');
|
|
|
|
|
|
|
|
let files_root = init(
|
|
|
|
template_data.next().unwrap().to_string(),
|
|
|
|
static_dir.clone(),
|
|
|
|
template_data.next().unwrap().to_string(),
|
|
|
|
);
|
2023-04-09 16:58:21 +02:00
|
|
|
|
2023-04-09 15:19:23 +02:00
|
|
|
Config {
|
|
|
|
fc: internal_config,
|
2023-04-09 16:58:21 +02:00
|
|
|
static_location: format!("{}/{}", files_root, static_dir),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-09 17:01:30 +02:00
|
|
|
fn init(dist_dir: String, static_dir: String, templates_dir: String) -> String {
|
2023-04-09 17:35:15 +02:00
|
|
|
// Be sure that we not gonna use the dist folder by deleting it
|
|
|
|
remove_dir_all(&dist_dir).unwrap_or_default();
|
2023-04-09 16:58:21 +02:00
|
|
|
|
2023-04-09 17:35:15 +02:00
|
|
|
let cfg = Cfg::spec_compliant();
|
2023-04-09 16:58:21 +02:00
|
|
|
|
2023-04-09 17:35:15 +02:00
|
|
|
// Static files
|
|
|
|
for entry in glob(&format!("{static_dir}/**/*.*")).unwrap() {
|
|
|
|
let path = entry.unwrap();
|
|
|
|
let path_with_dist = path
|
|
|
|
.to_string_lossy()
|
|
|
|
.replace(&static_dir, &format!("{dist_dir}/{static_dir}"));
|
2023-04-09 16:58:21 +02:00
|
|
|
|
2023-04-09 17:35:15 +02:00
|
|
|
copy_to_dist(&cfg, path, path_with_dist);
|
2023-04-09 16:58:21 +02:00
|
|
|
}
|
2023-04-09 17:35:15 +02:00
|
|
|
|
|
|
|
// Template files
|
|
|
|
for entry in glob(&format!("{templates_dir}/**/*.*")).unwrap() {
|
|
|
|
let path = entry.unwrap();
|
|
|
|
let path_with_dist = path
|
|
|
|
.to_string_lossy()
|
|
|
|
.replace(&templates_dir, &format!("{dist_dir}/{templates_dir}"));
|
|
|
|
|
|
|
|
copy_to_dist(&cfg, path, path_with_dist);
|
|
|
|
}
|
|
|
|
|
|
|
|
dist_dir
|
2023-04-09 16:58:21 +02:00
|
|
|
}
|
|
|
|
|
2023-04-09 17:35:15 +02:00
|
|
|
fn copy_to_dist(cfg: &Cfg, path: PathBuf, path_with_dist: String) {
|
2023-04-09 16:58:21 +02:00
|
|
|
// Create folders
|
|
|
|
let new_path = Path::new(&path_with_dist);
|
|
|
|
fs::create_dir_all(new_path.parent().unwrap()).unwrap();
|
|
|
|
|
|
|
|
let mut copy = true;
|
|
|
|
if let Some(ext) = path.extension() {
|
|
|
|
// List of files who should be minified
|
|
|
|
if ["html", "css", "js", "svg", "webmanifest", "xml"]
|
|
|
|
.iter()
|
|
|
|
.any(|item| ext.to_string_lossy().to_lowercase().contains(item))
|
2023-04-09 17:35:15 +02:00
|
|
|
&& !cfg!(debug_assertions)
|
2023-04-09 16:58:21 +02:00
|
|
|
{
|
|
|
|
// We won't copy, we'll minify
|
|
|
|
copy = false;
|
|
|
|
|
|
|
|
// Minify
|
|
|
|
let data = fs::read(&path).unwrap();
|
|
|
|
let minified = minify(&data, cfg);
|
|
|
|
|
|
|
|
// Write files
|
|
|
|
let file = File::create(&path_with_dist);
|
|
|
|
file.expect("Error when minify the file")
|
|
|
|
.write_all(&minified)
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if copy {
|
|
|
|
// If no minification is needed
|
|
|
|
fs::copy(path, path_with_dist).unwrap();
|
2023-04-09 15:19:23 +02:00
|
|
|
}
|
|
|
|
}
|