rustyphoenixlecture 1.1.0

This project aims to provide a simple a powerfull lecture compilation to generate html web sites
/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/

use std::{collections::HashMap, fs, path::PathBuf};
use serde::Deserialize;
use toml::{self, de::Error};

///Configuration of the full lecture serde compatible (yes, there is no Path or PathBuf in it which is very anoying)
#[derive(Debug, Clone, Deserialize)]
pub struct LectureConfig{
	///Vector of files of the lecture
	vec_file: Vec<PathBuf>,
	///Title of the lecture
	title: String,
	///Name of the lecture
	name: String,
	///Vector of authors of the lecture
	vec_author: Vec<String>,
	///Path to the theme directory
	theme_path: PathBuf,
	///Url to the current project (example on gitlab)
	project_url: String,
	/// Url where to find the documentation of the project or the generated lecture (i.e. pages for gitlab)
	documentation_url: String,
	///Url of the master project if the lecture is a part of a bigger project
	master_project: String,
	///Main contact for the lecture
	contact_mail: String,
	///Vector of all parser directories to be used
	vec_parser: Vec<PathBuf>,
	///Vector of all environment directories to be used
	vec_environment: Vec<PathBuf>,
	///Map of lectures from which labels have to be used (key: LectureName, value: lecture documentation url)
	dependencies: HashMap<String, String>,
}

impl LectureConfig{
	///Get the vector of files
	/// # Returns
	/// Vector of files of the lecture
	pub fn get_vec_file(&self) -> &Vec<PathBuf>{
		&self.vec_file
	}
	///Get the title
	/// # Returns
	/// Title of the lecture
	pub fn get_title(&self) -> &String{
		&self.title
	}
	///Get the name
	/// # Returns
	/// Name of the lecture
	pub fn get_name(&self) -> &String{
		&self.name
	}
	///Get the vector of author
	/// # Returns
	/// Vector of author
	pub fn get_vec_author(&self) -> &Vec<String>{
		&self.vec_author
	}
	///Get the theme path
	/// # Returns
	/// Theme path of the lecture
	pub fn get_theme_path(&self) -> &PathBuf{
		&self.theme_path
	}
	///Get url of the project
	/// # Returns
	/// Url of the project
	pub fn get_project_url(&self) -> &String{
		&self.project_url
	}
	///Get url of the project documentation or published lecture
	/// # Returns
	/// Url of the project or published lecture
	pub fn get_documentation_url(&self) -> &String{
		&self.documentation_url
	}
	///Get url of the master project
	/// # Returns
	/// Url of the master project
	pub fn get_master_project(&self) -> &String{
		&self.master_project
	}
	///Get contact mail
	/// # Returns
	/// Contact mail
	pub fn get_contact_mail(&self) -> &String{
		&self.contact_mail
	}
	///Get the vector of parser directories
	/// # Returns
	/// Vector of parser directories of the lecture
	pub fn get_vec_parser(&self) -> &Vec<PathBuf>{
		&self.vec_parser
	}
	///Get the vector of environment directories
	/// # Returns
	/// Vector of environment directories of the lecture
	pub fn get_vec_environment(&self) -> &Vec<PathBuf>{
		&self.vec_environment
	}
	///Get the map of dependencies of the lecture
	/// # Returns
	/// Map of dependencies of the lecture (key: LectureName, value: url of the lecture documentation i.e. pages for gitlab)
	pub fn get_map_dependency(&self) -> &HashMap<String, String>{
		&self.dependencies
	}
}

///Load the lecture configuration file
/// # Parameters
/// - `filename` : name of the highlighter configuration file (in toml)
/// # Returns
/// Lecture configuration or error on fail
pub fn load_lecture_config(filename: &String) -> Result<LectureConfig, Error> {
	let mut config: LectureConfig = match fs::read_to_string(filename) {
		Ok(str) => match toml::from_str(&str){
			Ok(value) => value,
			Err(error) => panic!("load_lecture_config : cannot parse file '{}', parsing error {}", filename, error)
		},
		Err(err) => panic!("load_lecture_config : cannot read file '{}', error: {}", filename, err)
	};
	let config_path = PathBuf::from(filename);
	let absolute_config = match config_path.canonicalize() {
		Ok(absolute_config_path) => absolute_config_path,
		Err(err) => panic!("load_lecture_config : cannot get absolute path of '{}'. Error {}", filename, err)
	};
	let absolute_config_parent = match absolute_config.parent() {
		Some(abs_path) => abs_path,
		None => panic!("load_lecture_config : no parent found for file {:?}", absolute_config)
	};
	
	let theme_path = PathBuf::from(config.get_theme_path());
	if theme_path.is_relative() {
		//Let's make the theme path absolute
		config.theme_path = absolute_config_parent.join(config.theme_path);
	}
	//Let's make the vec_file absolute
	for input_file in config.vec_file.iter_mut() {
		if input_file.is_relative() {
			*input_file = absolute_config_parent.join(&input_file);
		}
	}
	//Let's make the vec_parser absolute
	for input_dir in config.vec_parser.iter_mut() {
		if input_dir.is_relative() {
			*input_dir = absolute_config_parent.join(&input_dir);
		}
	}
	//Let's make the vec_environment absolute
	for input_dir in config.vec_environment.iter_mut() {
		if input_dir.is_relative() {
			*input_dir = absolute_config_parent.join(&input_dir);
		}
	}
	
	Ok(config)
}

#[cfg(test)]
mod tests{
	use super::*;
	
	///Test the load lecture config
	#[test]
	fn test_load_lecture_config(){
		let config: LectureConfig = load_lecture_config(&String::from("tests/LectureWithDependency/lecture.toml")).unwrap();
		assert_eq!(config.get_vec_file().len(), 1);
		assert!(config.get_vec_file().get(0).unwrap().ends_with(&String::from("index.md")));
		
		assert_eq!(config.get_title().clone(), String::from("A great lecture"));
		assert_eq!(config.get_name().clone(), String::from("TestLecture"));
		assert_eq!(config.get_project_url().clone(), String::from("https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS2/static-site-generator/RustyPhoenixLecture"));
		assert_eq!(config.get_documentation_url().clone(), String::from("https://cta-lapp.pages.in2p3.fr/PHOENIX_LIBS2/static-site-generator/RustyPhoenixLecture"));
		assert_eq!(config.get_master_project().clone(), String::from("https://paubert.pages.in2p3.fr/Lectures/"));
		assert_eq!(config.get_contact_mail().clone(), String::from("pierre.aubert@lapp.in2p3.fr"));
		
		assert_eq!(config.get_vec_author().len(), 1);
		assert_eq!(config.get_vec_author().get(0).unwrap().clone(), String::from("Pierre Aubert"));
		assert!(config.get_theme_path().ends_with(&String::from("themes/book")));
		
		assert_eq!(config.get_map_dependency().len(), 1);
		assert_eq!(config.get_map_dependency().get(&String::from("performance_with_stencil")).unwrap(), &String::from("https://pages.gitlab.com/url/to/this/lecture/"));
	}
}