rustyphoenixlecture 1.4.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 crate::phighlighter::PLocation;

use crate::pcontent::{
	PStrBackend,
	plabeler::PLabelId,
	pabstractcontent::{PAbstractContent, PAbstractLectureBackend},
	pveccontent::PVecContent,
	preferenceurl::PReferenceUrl,
};


///Content object of the lecture
#[derive(Debug, Clone, Default, PartialEq)]
pub struct PContentTitle{
	///Title of the PContentTitle
	p_title: PVecContent,
	///Level of the title (1, 2, 3, 4 etc)
	p_level: usize,
	///True if the title needs numeration or false if not
	p_is_enumerated: bool,
	///Number of the title
	p_vec_title_number: Vec<usize>,
	///Output file name for the current title
	p_output_filename: String,
	///Previous file name for the current title (if there is no previous page, it will be the current one)
	p_previous_filename: String,
	///Next file name for the current title (if there is no next page, it will be the current one)
	p_next_filename: String,
	///Location of the definition of the current title in the lecture source
	p_location: PLocation,
}

impl PContentTitle {
	///Constructor of a PContentTitle
	/// # Parameters
	/// - `id` : id of the content
	/// - `level` : level of the title (Part: 1, Chapter: 2, Section: 3, SubSection: 4, SubSubSection: 5, etc)
	/// - `is_enumerated` : true if the title will have a number, false otherwise
	/// - `location` : location of the current source file where the current section is defined
	pub fn new(level: usize, is_enumerated: bool, location: &PLocation) -> Self {
		PContentTitle{
			p_title: Default::default(),
			p_level: level,
			// p_content: Default::default(),
			p_is_enumerated: is_enumerated,
			p_vec_title_number: vec![],
			p_output_filename: String::from(""),
			p_previous_filename: String::from(""),
			p_next_filename: String::from(""),
			p_location: location.clone(),
		}
	}
	///Set the title number of the current PContentTitle
	/// # Parameters
	/// - `vec_title_number` : vector of numbers in the title
	pub fn set_title_number(&mut self, vec_title_number: &Vec<usize>){
		self.p_vec_title_number = vec_title_number.clone();
	}
	///Make the filename with respect to the title number
	pub fn make_filename(&mut self){
		let mut str_title_number = String::from("");
		let mut comma = String::from("");
		for number in self.p_vec_title_number.iter(){
			str_title_number += &format!("{}{}", comma, number);
			comma = String::from("-");
		}
		if str_title_number.is_empty() {
			self.p_output_filename = String::from("index.html");
		}else{
			self.p_output_filename = String::from(format!("web_{}.html", str_title_number));
		}
	}
	///Set the previous filename of the current section
	/// # Parameters
	/// - `previous_filename` : previous filename of the current section
	pub fn set_previous_filename(&mut self, previous_filename: &String){
		self.p_previous_filename = previous_filename.clone();
	}
	///Set the next filename of the current section
	/// # Parameters
	/// - `next_filename` : next filename of the current section
	pub fn set_next_filename(&mut self, next_filename: &String){
		self.p_next_filename = next_filename.clone();
	}
	///Get the title of the PContentTitle
	/// # Returns
	/// Title of the PContentTitle
	pub fn get_title(&self) -> &PVecContent{
		&self.p_title
	}
	///Get the level of the current section
	/// # Returns
	/// Level of the current section
	pub fn get_level(&self) -> usize{
		self.p_level
	}
	///Get the title content
	/// # Returns
	/// Muttable title of the PContentTitle
	pub fn get_title_mut(&mut self) -> &mut PVecContent{
		&mut self.p_title
	}
	///Say if the current section has number or not
	/// # Returns
	/// True if the current section has number, false otherwise
	pub fn is_enumerated(&self) -> bool{
		self.p_is_enumerated
	}
	///Get the output filename
	/// # Returns
	/// Reference to the output filename of the current section
	pub fn get_output_filename(&self) -> &String{
		&self.p_output_filename
	}
	///Get the title number as a string
	/// # Returns
	/// Title number as a string
	pub fn get_str_title_number(&self) -> String{
		let mut str_title_number = String::from("");
		if self.p_is_enumerated {
			for number in self.p_vec_title_number.iter(){
				str_title_number += &format!("{}.", number);
			}
		}
		return str_title_number;
	}
}

impl PAbstractContent for PContentTitle{
	///Say if the PContent has an embeded label
	/// # Returns
	/// True if the PContent has an embeded label, false otherwise
	fn has_embeded_label(&self) -> bool{
		true
	}
	///Get the reference url of the current PContent
	/// # Parameters
	/// - `current_file` : current output file of the PContent
	/// - `id` : id of the current PContent
	/// # Returns
	/// Corresponding PReferenceUrl
	fn get_reference_url(&self, current_file: &String, id: usize) -> PReferenceUrl{
		if self.p_is_enumerated {
			PReferenceUrl::from_text(current_file, id, &String::from(self.get_str_title_number().trim_end_matches(".")))
		}else{
			PReferenceUrl::from_content(current_file, id, self.get_title())
		}
	}
	///Convert the current struct into html
	/// # Parameters
	/// - `backend` : backend which write a lecture in files
	/// - `id` : id of the current PContent
	fn to_html<TLectureBackend>(&self, backend: &mut TLectureBackend, id: &PLabelId)
		where TLectureBackend: PAbstractLectureBackend
	{
		let mut str_title_number = self.get_str_title_number();
		if !str_title_number.is_empty() {
			str_title_number += &String::from(" ");
		}
		let mut backend_str = PStrBackend::new();
		self.p_title.to_html(&mut backend_str, id);
		//If the section is enumerated, it creates a new file
		if self.p_is_enumerated {
			backend.create_file(&self.p_output_filename, backend_str.get_body(), &self.p_location, &self.p_previous_filename, &self.p_next_filename);
		}
		backend.write(&format!("<h{} id=\"{}\">{}", self.p_level, id.get_id(), str_title_number));
		self.p_title.to_html(backend, id);
		id.to_html(backend, false);
		backend.write(&format!("</h{}>\n", self.p_level));
	}
}

#[cfg(test)]
mod tests{
	use super::*;
	use std::path::PathBuf;
	use crate::pcontent::{
		pstrbackend::PStrBackend,
		PContentType,
		plabeler::PLabeler,
		pcontenttext::PContentText
	};
	//In the following, content is supposed to do its work properly, we don't test it here but in PVecContent
	
	///Test the PContentText for a Part
	#[test]
	fn test_content_title_part(){
		let title: PContentTitle = PContentTitle::new(1, false, &PLocation::new(&PathBuf::from("index.md"), 1, 1));
		let mut backend = PStrBackend::new();
		title.to_html(&mut backend, &PLabelId::new(42));
		assert_eq!(backend.get_body(), &String::from("<h1 id=\"42\"></h1>\n"));
	}
	///Test the PContentText for a Part with title number
	#[test]
	fn test_content_title_part_number(){
		let mut title: PContentTitle = PContentTitle::new(1, true, &PLocation::new(&PathBuf::from("index.md"), 1, 1));
		title.set_title_number(&vec![1]);
		title.get_title_mut().add_child(&PContentType::Text(PLabeler::new(42, &PContentText::new(&String::from("Some interesting title")))));
		let mut backend = PStrBackend::new();
		title.to_html(&mut backend, &PLabelId::new(42));
		assert_eq!(backend.get_body(), &String::from("<h1 id=\"42\">1. Some interesting title</h1>\n"));
	}
	///Test the PContentText for a Chapter
	#[test]
	fn test_content_title_chapter(){
		let title: PContentTitle = PContentTitle::new(2, false, &PLocation::new(&PathBuf::from("index.md"), 1, 1));
		let mut backend = PStrBackend::new();
		title.to_html(&mut backend, &PLabelId::new(42));
		assert_eq!(backend.get_body(), &String::from("<h2 id=\"42\"></h2>\n"));
	}
	///Test the PContentText for a Chapter with title number
	#[test]
	fn test_content_title_chapter_number(){
		let mut title: PContentTitle = PContentTitle::new(2, true, &PLocation::new(&PathBuf::from("index.md"), 1, 1));
		title.set_title_number(&vec![1, 2]);
		let mut backend = PStrBackend::new();
		title.to_html(&mut backend, &PLabelId::new(42));
		assert_eq!(backend.get_body(), &String::from("<h2 id=\"42\">1.2. </h2>\n"));
	}
}