rustyphoenixlecture 1.3.0

This project aims to provide a simple a powerfull lecture compilation to generate html web sites
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/

use std::path::PathBuf;
use crate::pcontent::{
	pabstractcontent::{PAbstractContent, PAbstractLectureBackend},
	pcontent::PContent,
	pcontentdetail::PContentDetail,
	pcontentenvironment::PContentEnvironment,
	pcontentfootnote::PContentFootnote,
	pcontentformula::PContentFormula,
	pcontentitem::{PContentItem, PItemType, list_item_from_item},
	pcontentmedia::{PContentMedia, PMediaType},
	pcontentparagraph::PContentParagraph,
	pcontentparser::PContentParser,
	pcontentreference::PContentReference,
	pcontentstyle::PContentStyle,
	pcontenttable::PContentTable,
	pcontenttext::PContentText,
	pcontenttitle::PContentTitle,
	pcontenturl::PContentUrl,
	pcontentenvlist::PContentEnvList,
	pcontenttimetable::PContentTimeTable,
	pidcounter::PIdCounter,
	plabeler::{PLabelId, PLabeler},
	preferenceurl::PReferenceUrl
};

///Type of content
#[derive(Debug, Clone, PartialEq)]
pub enum PContentType{
	///An url (and href)
	Url(PLabeler<PContentUrl>),
	///A Media (Image or Video)
	Media(PLabeler<PContentMedia>),
	///A title and an identifier (part, chapter, section, subsection, subsubsection, etc, and with their star equivalent without numeration)
	Title(PLabeler<PContentTitle>),
	///Footnote with some text and an identifier
	FootNote(PLabeler<PContentFootnote>),
	///Just content to speed up passing through the content of the full lecture
	Content(PLabeler<PContent>),
	///Bold text
	TextBf(PLabeler<PVecContent>),
	///Italic text
	TextIt(PLabeler<PVecContent>),
	///Code snipet
	TextCode(PLabeler<PVecContent>),
	///Stylized text with arbitrary css style
	TextStyle(PLabeler<PContentStyle>),
	///Simple text content for all previous PContentType
	Text(PLabeler<PContentText>),
	///Paragraph of PContent
	Paragraph(PLabeler<PContentParagraph>),
	///Mathematic formula
	Formula(PLabeler<PContentFormula>),
	///Code highlighting
	Parser(PLabeler<PContentParser>),
	///Environement with different style (warning, advise, exercice, summary, etc)
	Environment(PLabeler<PContentEnvironment>),
	///Reference to any other PContent of the lecture
	Reference(PLabeler<PContentReference>),
	///List and item
	ListItem(PLabeler<PContentItem>),
	///Table of PContent
	Table(PLabeler<PContentTable>),
	///Detail environment (first line is the title and the rest can be revealed on click)
	Detail(PLabeler<PContentDetail>),
	///List all environments of a certain type at its call
	EnvList(PLabeler<PContentEnvList>),
	///Time table of the lecture
	TimeTable(PLabeler<PContentTimeTable>),
	///New line in the html
	NewLine,
}

impl PContentType{
	///Create a PContentType from a text
	/// # Parameters
	/// - `id` : id of the PContent
	/// - `text` : text of the PContentText
	/// # Returns
	/// Initialised PContentType::Text
	pub fn from_text(id: usize, text: &String) -> Self{
		PContentType::Text(PLabeler::new(id, &PContentText::new(text)))
	}
	///Create a PContentType from a text
	/// # Parameters
	/// - `id_counter` : manager of id
	/// - `text` : text of the PContentText
	/// # Returns
	/// Initialised PContentType::TextBf
	pub fn from_textbf(id_counter: &mut PIdCounter, text: &String) -> Self{
		let text_content = PContentType::from_text(id_counter.get_id(), text);
		let mut vec_content = PVecContent::new();
		vec_content.add_child(&text_content);
		return PContentType::TextBf(PLabeler::new(id_counter.get_id(), &vec_content));
	}
	///Create a PContentType from a text style
	/// # Parameters
	/// - `id_counter` : manager of id
	/// - `style` : style of the text
	/// - `text` : text of the PContentText
	/// # Returns
	/// Initialised PContentType::TextStyle
	pub fn from_text_style(id_counter: &mut PIdCounter, style: &String, text: &String) -> Self{
		let text_content = PContentType::from_text(id_counter.get_id(), text);
		let mut content_style = PContentStyle::new(style);
		content_style.get_content_mut().add_child(&text_content);
		return PContentType::TextStyle(PLabeler::new(id_counter.get_id(), &content_style));
	}
	///Create a PContentType from a media
	/// # Parameters
	/// - `id` : id of the PContent
	/// - `filename` : file name to the media
	/// - `width` : width of the video in the page
	/// - `media_type` : type of the media (Image, Video)
	/// - `is_figure` : true if the current PContentMedia is a figure
	/// # Returns
	/// Initialised PContentType::Media
	pub fn from_media(id: usize, filename: &PathBuf, width: usize, media_type: &PMediaType, is_figure: bool) -> Self{
		let content = PContentMedia::new(filename, width, media_type, is_figure);
		PContentType::Media(PLabeler::new(id, &content))
	}
	///Create a PContentType from a url
	/// # Parameters
	/// - `id` : id of the url
	/// - `text` : text of the url
	/// - `url` : link of the url
	/// # Returns
	/// Initialised PContentType::Url
	pub fn from_url(id: usize, text: &String, url: &String) -> Self{
		let mut content = PContentUrl::new();
		content.set_url(url);
		content.get_text_mut().add_child(&PContentType::from_text(id + 4000000000, text));
		PContentType::Url(PLabeler::new(id, &content))
	}
	///Set the label of the current PContent
	/// # Parameters
	/// - `label` : label of the current PContent
	pub fn set_label(&mut self, label: &String){
		match self {
			PContentType::Url(url) => url.set_label(label),
			PContentType::Media(media) => media.set_label(label),
			PContentType::Title(title) => title.set_label(label),
			PContentType::FootNote(footnote) => footnote.set_label(label),
			PContentType::Content(content) => content.set_label(label),
			PContentType::TextBf(textbf) => textbf.set_label(label),
			PContentType::TextIt(textit) => textit.set_label(label),
			PContentType::TextCode(code) => code.set_label(label),
			PContentType::TextStyle(textstyle) => textstyle.set_label(label),
			PContentType::Text(text) => text.set_label(label),
			PContentType::Paragraph(paragraph) => paragraph.set_label(label),
			PContentType::Parser(parser) => parser.set_label(label),
			PContentType::Environment(env) => env.set_label(label),
			PContentType::Formula(formula) => formula.set_label(label),
			PContentType::Reference(reference) => reference.set_label(label),
			PContentType::ListItem(listitem) => listitem.set_label(label),
			PContentType::Table(table) => table.set_label(label),
			PContentType::Detail(detail) => detail.set_label(label),
			PContentType::EnvList(envlist) => envlist.set_label(label),
			PContentType::TimeTable(timetable) => timetable.set_label(label),
			PContentType::NewLine => {},
		};
	}
	///Get the label of the current PContent
	/// # Returns
	/// Label of the current PContent
	pub fn get_label(&self) -> Option<&String>{
		match self {
			PContentType::Url(url) => Some(url.get_label()),
			PContentType::Media(media) => Some(media.get_label()),
			PContentType::Title(title) => Some(title.get_label()),
			PContentType::FootNote(footnote) => Some(footnote.get_label()),
			PContentType::Content(content) => Some(content.get_label()),
			PContentType::TextBf(textbf) => Some(textbf.get_label()),
			PContentType::TextIt(textit) => Some(textit.get_label()),
			PContentType::TextCode(code) => Some(code.get_label()),
			PContentType::TextStyle(textstyle) => Some(textstyle.get_label()),
			PContentType::Text(text) => Some(text.get_label()),
			PContentType::Paragraph(paragraph) => Some(paragraph.get_label()),
			PContentType::Parser(parser) => Some(parser.get_label()),
			PContentType::Environment(env) => Some(env.get_label()),
			PContentType::Formula(formula) => Some(formula.get_label()),
			PContentType::Reference(reference) => Some(reference.get_label()),
			PContentType::ListItem(listitem) => Some(listitem.get_label()),
			PContentType::Table(table) => Some(table.get_label()),
			PContentType::Detail(detail) => Some(detail.get_label()),
			PContentType::EnvList(envlist) => Some(envlist.get_label()),
			PContentType::TimeTable(timetable) => Some(timetable.get_label()),
			PContentType::NewLine => None,
		}
	}
	///Get the id of the current PContentType
	/// # Returns
	/// Id of the current PContentType
	pub fn get_id(&self) -> usize {
		match &self {
			PContentType::Url(url) => url.get_id(),
			PContentType::Media(media) => media.get_id(),
			PContentType::Title(title) => title.get_id(),
			PContentType::FootNote(footnote) => footnote.get_id(),
			PContentType::Content(content) => content.get_id(),
			PContentType::TextBf(textbf) => textbf.get_id(),
			PContentType::TextIt(textit) => textit.get_id(),
			PContentType::TextCode(code) => code.get_id(),
			PContentType::TextStyle(textstyle) => textstyle.get_id(),
			PContentType::Text(text) => text.get_id(),
			PContentType::Paragraph(paragraph) => paragraph.get_id(),
			PContentType::Parser(parser) => parser.get_id(),
			PContentType::Environment(env) => env.get_id(),
			PContentType::Formula(formula) => formula.get_id(),
			PContentType::Reference(reference) => reference.get_id(),
			PContentType::ListItem(listitem) => listitem.get_id(),
			PContentType::Table(table) => table.get_id(),
			PContentType::Detail(detail) => detail.get_id(),
			PContentType::EnvList(envlist) => envlist.get_id(),
			PContentType::TimeTable(timetable) => timetable.get_id(),
			PContentType::NewLine => 0,
		}
	}
	///Get the reference url of the current PContent
	/// # Parameters
	/// - `current_file` : current output file of the PContent
	/// # Returns
	/// Corresponding PReferenceUrl
	pub fn get_reference_url(&self, current_file: &String) -> PReferenceUrl{
		match &self {
			PContentType::Url(url) => url.get_reference_url(current_file),
			PContentType::Media(media) => media.get_reference_url(current_file),
			PContentType::Title(title) => title.get_reference_url(current_file),
			PContentType::FootNote(footnote) => footnote.get_reference_url(current_file),
			PContentType::Content(content) => content.get_reference_url(current_file),
			PContentType::TextBf(textbf) => textbf.get_reference_url(current_file),
			PContentType::TextIt(textit) => textit.get_reference_url(current_file),
			PContentType::TextCode(code) => code.get_reference_url(current_file),
			PContentType::TextStyle(textstyle) => textstyle.get_reference_url(current_file),
			PContentType::Text(text) => text.get_reference_url(current_file),
			PContentType::Paragraph(paragraph) => paragraph.get_reference_url(current_file),
			PContentType::Parser(parser) => parser.get_reference_url(current_file),
			PContentType::Environment(env) => env.get_reference_url(current_file),
			PContentType::Formula(formula) => formula.get_reference_url(current_file),
			PContentType::Reference(reference) => reference.get_reference_url(current_file),
			PContentType::ListItem(listitem) => listitem.get_reference_url(current_file),
			PContentType::Table(table) => table.get_reference_url(current_file),
			PContentType::Detail(detail) => detail.get_reference_url(current_file),
			PContentType::EnvList(envlist) => envlist.get_reference_url(current_file),
			PContentType::TimeTable(timetable) => timetable.get_reference_url(current_file),
			PContentType::NewLine => PReferenceUrl::from_text(current_file, 0, &String::from("PContentType::NewLine")),
		}
	}
	
	///Say if the current PContentType is in a paragraph or not
	/// # Returns
	/// True if the current PContentType is in a paragraph, false if not
	pub fn is_in_paragraph(&self) -> bool {
		match &self {
			PContentType::Url(_) => true,
			PContentType::Media(media) => !media.get_data().is_figure(),
			PContentType::Title(_) => false,
			PContentType::FootNote(_) => true,
			PContentType::Content(_) => false,
			PContentType::TextBf(_) => true,
			PContentType::TextIt(_) => true,
			PContentType::TextCode(_) => true,
			PContentType::TextStyle(_) => true,
			PContentType::Text(_) => true,
			PContentType::Paragraph(_) => false,
			PContentType::Formula(formula) => formula.get_data().is_inlined(),
			PContentType::Parser(parser) => parser.get_data().is_inlined(),
			PContentType::Environment(_) => false,
			PContentType::Reference(_) => true,
			PContentType::ListItem(_) => false,
			PContentType::Table(_) => false,
			PContentType::Detail(_) => false,
			PContentType::EnvList(_) => false,
			PContentType::TimeTable(_) => false,
			PContentType::NewLine => true,
		}
	}
}


///Vector of Content object of the lecture
#[derive(Debug, Default, Clone, PartialEq)]
pub struct PVecContent{
	///Vector of children
	p_vec_child: Vec<PContentType>,
}

impl PVecContent {
	///Constructor of the PVecContent
	/// # Returns
	/// Initialised PVecContent
	pub fn new() -> Self{
		PVecContent {
			p_vec_child: vec![]
		}
	}
	///Get the number of elements in the content
	/// # Returns
	/// Number of elements in the content
	pub fn len(&self) -> usize{
		self.p_vec_child.len()
	}
	///Add a child into the PVecContent
	/// # Parameters
	/// - `content_type` : PContentType to be added
	pub fn add_child(&mut self, content_type: &PContentType){
		//We could add a witch depending on the content_type and on the type of the last PContent in the p_vec_child
		self.p_vec_child.push(content_type.clone());
	}
	///Append all children of the given PVecContent into the current one
	/// # Parameters
	/// - `content` : content where children have to be appeded
	pub fn append_content(&mut self, content: &PVecContent){
		for child in content.p_vec_child.iter(){
			self.p_vec_child.push(child.clone());
		}
	}
	///Get the vector of child
	/// # Returns
	/// Vector of child
	pub fn get_vec_child(&self) -> &Vec<PContentType> {
		&self.p_vec_child
	}
	///Get the muttable vector of child
	/// # Returns
	/// Muttable vector of child
	pub fn get_vec_child_mut(&mut self) -> &mut Vec<PContentType> {
		&mut self.p_vec_child
	}
	///Update the title number
	/// # Parameters
	/// - `vec_title_number` : vector of title number
	pub fn update_title_number(&mut self, vec_title_number: &mut Vec<usize>){
		for content in self.p_vec_child.iter_mut() {
			match content {
				PContentType::Title(section) => {
					let section_level: usize = section.get_data().get_level();
					let section_data = section.get_data_mut();
					//If the section is enumerated, it has a dedicated file, otherwise there is no file
					if section_data.is_enumerated() {
						if vec_title_number.len() > section_level {
							//If we have more numbers that the level of the current section
							// We have to remove the extra numbers
							vec_title_number.truncate(section_level);
						}
						match vec_title_number.get_mut(section_level - 1) {
							Some(section_number) => {
								*section_number += 1;
								section_data.set_title_number(&vec_title_number);
							},
							None => {
								vec_title_number.push(1);
								section_data.set_title_number(&vec_title_number);
							}
						};
						section_data.make_filename();
					}
				},
				&mut _ => {}
			};
		}
	}
	
	///Add PContent in the current PVecContent by respect to its type
	/// # Parameters
	/// - `id` : id manager
	/// - `content_type` : PContentType to be added in the PVecContent
	/// - `is_paragraph_enabled` : true if the paragraph are enabled, false otherwise
	pub fn add_content(&mut self, id: &mut PIdCounter, content_type: &PContentType, is_paragraph_enabled: bool){
		if !is_paragraph_enabled {	//If there is no paragraph, we just add the PContentType to the p_vec_child
			self.add_child(content_type);
			return;
		}
		if content_type.is_in_paragraph() {	//If the PContentType is in a paragraph we get the last child which is a paragraph, of we create it
			self.add_content_in_paragraph(id, content_type, is_paragraph_enabled);
		}else{
			match content_type {
				//If it is a ListItem we check that the last element is not a ListItem
				PContentType::ListItem(content_list_item) => {
					self.add_content_item(id, content_list_item);
				},
				//If it is not a ListItem and no a content for a paragraph, we add it in the vector of content
				_ => self.add_child(content_type),
			}
		}
	}
	///Add an item to the vec content
	/// - `id` : id manager
	/// - `content_list_item` : PContentItem to be added into the vec content
	fn add_content_item(&mut self, id: &mut PIdCounter, content_list_item: &PLabeler<PContentItem>){
		match self.p_vec_child.last_mut() {
			Some(last_content) => {
				match last_content {
					PContentType::ListItem(last_list_item) => {
						//We have to check if it is a list or an item
						// And we have to check the indentation
						match last_list_item.get_data().get_type() {
							PItemType::Item => {
								//If the item has the same indentation that the previous item, we add it in the vec_content
								if last_list_item.get_data().get_indentation_level() <= content_list_item.get_data().get_indentation_level() {
									self.add_child(&PContentType::ListItem(content_list_item.clone()));
								}else{
									//We need to add a List of item to manage the incoming item
									let list_from_item: PContentItem = list_item_from_item(&content_list_item);
									self.add_child(&PContentType::ListItem(PLabeler::new(content_list_item.get_id(), &list_from_item)));
								}
							},
							PItemType::List => {
								//Do we have to insert the item in the list or in a item sub list
								if last_list_item.get_data().get_indentation_level() <= content_list_item.get_data().get_indentation_level() {
									last_list_item.get_data_mut().get_content_mut().add_child(&PContentType::ListItem(content_list_item.clone()));
								}else{
									//Here we have to go inside the list to get a sub item
									last_list_item.get_data_mut().get_content_mut().add_content_item(id, content_list_item);
								}
							}
						}
					},
					_ => self.add_list_item_in_content(id, content_list_item),
				}
			},
			//Here we add the item into a list
			None => self.add_list_item_in_content(id, content_list_item)
		}
	}
	///Add a ListItem in the content
	/// - `id` : id manager
	/// - `list_item` : PContentItem to be added into the vec content
	fn add_list_item_in_content(&mut self, id: &mut PIdCounter, list_item: &PLabeler<PContentItem>){
		match list_item.get_data().get_type() {
			PItemType::List => self.add_child(&PContentType::ListItem(list_item.clone())),
			PItemType::Item => {
				let mut tmp_list = PContentItem::new(list_item.get_data().get_indentation_level(), &PItemType::List);
				tmp_list.get_content_mut().add_child(&PContentType::ListItem(list_item.clone()));
				self.add_child(&PContentType::ListItem(PLabeler::new(id.get_id(), &tmp_list)));
			}
		}
	}
	///Add PContent in a paragraph in the current PVecContent by respect to its type
	/// # Parameters
	/// - `id` : id manager
	/// - `content_type` : PContentType to be added in the PVecContent
	/// - `is_paragraph_enabled` : true if the paragraph are enabled, false otherwise
	fn add_content_in_paragraph(&mut self, id: &mut PIdCounter, content_type: &PContentType, is_paragraph_enabled: bool){
		match self.p_vec_child.last_mut() {
			Some(last_child) => {
				match last_child {
					PContentType::ListItem(last_list_item) => {
						match last_list_item.get_data().get_type() {
							//If it is a list, we get the last item and add the paragraph content into it
							PItemType::List => last_list_item.get_data_mut().get_content_mut().add_content(id, content_type, is_paragraph_enabled),
							//If it is an item, we add the content_type in it
							PItemType::Item => last_list_item.get_data_mut().get_content_mut().add_content(id, content_type, is_paragraph_enabled),
						}
					},
					//We found the Paragraph, we add the PContentType in it
					PContentType::Paragraph(last_paragraph) => last_paragraph.get_data_mut().get_content_mut().add_child(content_type),
					//If there is no paragraph, we create it
					_ => self.add_content_create_paragraph(id, content_type)
				}
			},
			//If there is no last child, we create it as a paragraph
			None => self.add_content_create_paragraph(id, content_type)
		}
	}
	///Add PContent in a created PContentParagraph in the current PVecContent by respect to its type
	/// # Parameters
	/// - `id` : id manager
	/// - `content_type` : PContentType to be added in the PVecContent
	fn add_content_create_paragraph(&mut self, id: &mut PIdCounter, content_type: &PContentType){
		let mut paragraph: PContentParagraph = PContentParagraph::new();
		paragraph.get_content_mut().add_child(content_type);
		self.add_child(&PContentType::Paragraph(PLabeler::new(id.get_id(), &paragraph)));
	}
	
	///Add text in the PVecContent
	/// # Parameters
	/// - `id` : id manager
	/// - `text` : text to be added to the PVecContent
	/// # Returns
	/// True if the text was added, false if it was only newlines
	pub fn add_text(&mut self, id: &mut PIdCounter, text: &String) -> bool{
		//First we trim the text
		let mut trim_text = String::from(text.trim_matches('\n'));
		if trim_text.is_empty() {	//If the text is empty, we do nothing
			return false;
		}
		if text.starts_with("\n"){
			trim_text = String::from(&format!(" {}", trim_text));
		}
		//Maybe there is a last paragraph
		match self.get_vec_child_mut().last_mut() {
			Some(last_content) => {	//If there is a last content
				match last_content {
					//TODO : here we should add the Table, Row and Cell add text
					
					PContentType::ListItem(last_item) => last_item.get_data_mut().add_text(id, &trim_text),
					//If the last element of the PVecContent is a paragraph we try to add the text in it
					PContentType::Paragraph(last_paragraph) => last_paragraph.get_data_mut().add_text(id, &trim_text),
					//If we get a list, we have to do the same
					//If we get other PContent, we have to create a PContentParagraph
					_ => self.create_paragraph_with_text(id, &trim_text)
				}
			},
			//If there is no PContent, we have to create a PContentParagraph
			None => self.create_paragraph_with_text(id, &trim_text)
		}
		return true;
	}
	///Create PContentParagraph with text in it
	/// # Parameters
	/// - `vec_content` : PVecContent result of the parsing
	/// - `trim_text` : text to be added, without newlines
	pub fn create_paragraph_with_text(&mut self, id: &mut PIdCounter, trim_text: &String){
		//We create the text
		let text_content = PContentType::Text(PLabeler::new(id.get_id(), &PContentText::new(&trim_text)));
		//And we create the PContentParagraph
		let mut paragraph = PContentParagraph::new();
		paragraph.get_content_mut().add_child(&text_content);
		self.add_child(&PContentType::Paragraph(PLabeler::new(id.get_id(), &paragraph)));
	}
}

impl PAbstractContent for PVecContent{
	///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{
		false
	}
	///Get the reference url of the current PContent
	/// # Parameters
	/// - `current_file` : current output file of the PContent
	/// - `id` : id of the PContent
	/// # Returns
	/// Corresponding PReferenceUrl (empty because we cannot reference multiple objects with one reference)
	fn get_reference_url(&self, current_file: &String, id: usize) -> PReferenceUrl{
		PReferenceUrl::from_text(current_file, id, &String::from("PVecContent"))
	}
	///Convert the current struct into html
	/// # Parameters
	/// - `backend` : backend which write a lecture in files
	/// - `_id` : id of the PContent
	fn to_html<TLectureBackend>(&self, backend: &mut TLectureBackend, _id: &PLabelId)
		where TLectureBackend: PAbstractLectureBackend
	{
		for content in self.p_vec_child.iter() {
			match content {
				PContentType::Url(url) => url.to_html(backend),
				PContentType::Media(media) => media.to_html(backend),
				PContentType::Title(title) => title.to_html(backend),
				PContentType::FootNote(footnote) => footnote.to_html(backend),
				PContentType::Content(content) => content.to_html(backend),
				PContentType::TextBf(textbf) => {
					backend.write(&String::from("<b>"));
					textbf.to_html(backend);
					backend.write(&String::from("</b>"));
				},
				PContentType::TextIt(textit) => {
					backend.write(&String::from("<em>"));
					textit.to_html(backend);
					backend.write(&String::from("</em>"));
				},
				PContentType::TextCode(code) => {
					backend.write(&String::from("<span class=\"code_inline\">"));
					code.to_html(backend);
					backend.write(&String::from("</span>"));
				},
				PContentType::TextStyle(textstyle) => textstyle.to_html(backend),
				PContentType::Text(text) => text.to_html(backend),
				PContentType::Paragraph(paragraph) => paragraph.to_html(backend),
				PContentType::Parser(parser) => parser.to_html(backend),
				PContentType::Environment(env) => env.to_html(backend),
				PContentType::Formula(formula) => formula.to_html(backend),
				PContentType::Reference(reference) => reference.to_html(backend),
				PContentType::ListItem(listitem) => listitem.to_html(backend),
				PContentType::Table(table) => table.to_html(backend),
				PContentType::Detail(detail) => detail.to_html(backend),
				PContentType::EnvList(envlist) => envlist.to_html(backend),
				PContentType::TimeTable(timetable) => timetable.to_html(backend),
				PContentType::NewLine => backend.write(&String::from("<br />")),
			};
		}
	}
}

#[cfg(test)]
mod tests{
	use super::*;
	use crate::phighlighter::PLocation;
	use std::path::PathBuf;

	///Test the PVecContent add content title
	#[test]
	fn test_pveccontent_add_content_title(){
		let id = &mut PIdCounter::new(0);	//Just to avoid to have mut everywhere
		let mut vec_content: PVecContent = Default::default();
		let title = PContentTitle::new(1, true, &PLocation::new(&PathBuf::from("index.md"), 1, 1));
		let title_id = id.get_id();
		vec_content.add_content(id, &PContentType::Title(PLabeler::new(title_id, &title.clone())), true);
		
		assert_eq!(vec_content.get_vec_child().len(), 1);
		//Here we should have a title
		assert_eq!(vec_content.get_vec_child().last().unwrap(), &PContentType::Title(PLabeler::new(title_id, &title)));
	}
	///Test the PVecContent add content text
	#[test]
	fn test_pveccontent_add_content_text(){
		let id = &mut PIdCounter::new(0);	//Just to avoid to have mut everywhere
		let mut vec_content: PVecContent = Default::default();
		let text = PContentText::new(&String::from("Hello world"));
		let text_id = id.get_id();
		vec_content.add_content(id, &PContentType::Text(PLabeler::new(text_id, &text)), true);
		
		assert_eq!(vec_content.get_vec_child().len(), 1);
		
		let mut expected_paragraph = PContentParagraph::new();
		expected_paragraph.get_content_mut().add_child(&PContentType::Text(PLabeler::new(text_id, &text)));
		let expected_paragraph_type = PContentType::Paragraph(PLabeler::new(1, &expected_paragraph));
		
		assert_eq!(vec_content.get_vec_child().last().unwrap(), &expected_paragraph_type);
	}
	///Test the PVecContent add content item
	#[test]
	fn test_pveccontent_add_content_item(){
		let id = &mut PIdCounter::new(0);	//Just to avoid to have mut everywhere
		let mut vec_content: PVecContent = Default::default();
		let item = PContentItem::new(1, &PItemType::Item);
		//Let's add an item
		let item_id = id.get_id();
		vec_content.add_content(id, &PContentType::ListItem(PLabeler::new(item_id, &item)), true);
		
		assert_eq!(vec_content.get_vec_child().len(), 1);
		//Let's add a Text
		let text = PContentText::new(&String::from("Hello world"));
		let text_id = id.get_id();
		vec_content.add_content(id, &PContentType::Text(PLabeler::new(text_id, &text)), true);
		assert_eq!(vec_content.get_vec_child().len(), 1);	//Still in the Item in the List
		
		let item1 = PContentItem::new(1, &PItemType::Item);
		let item1_id = id.get_id();
		vec_content.add_content(id, &PContentType::ListItem(PLabeler::new(item1_id, &item1)), true);
		let text1 = PContentText::new(&String::from("Hello world 1"));
		let text1_id = id.get_id();
		vec_content.add_content(id, &PContentType::Text(PLabeler::new(text1_id, &text1)), true);
		
		let item2 = PContentItem::new(2, &PItemType::Item);
		let item2_id = id.get_id();
		vec_content.add_content(id, &PContentType::ListItem(PLabeler::new(item2_id, &item2)), true);
		let text2 = PContentText::new( &String::from("Hello world 2"));
		let text2_id = id.get_id();
		vec_content.add_content(id, &PContentType::Text(PLabeler::new(text2_id, &text2)), true);
		
		let item12 = PContentItem::new(1, &PItemType::Item);
		let item12_id = id.get_id();
		vec_content.add_content(id, &PContentType::ListItem(PLabeler::new(item12_id, &item12)), true);
		let text12 = PContentText::new(&String::from("Hello world 1 2"));
		let text12_id = id.get_id();
		vec_content.add_content(id, &PContentType::Text(PLabeler::new(text12_id, &text12)), true);
		
		assert_eq!(vec_content.get_vec_child().len(), 1);	//Still in the Item in the List
	}
	///Test PVecContent::append_content
	#[test]
	fn test_veccontent_append_content(){
		let mut content_base = PVecContent::new();
		content_base.add_child(&PContentType::NewLine);
		let mut content_dest = PVecContent::new();
		content_dest.add_child(&PContentType::NewLine);
		content_dest.append_content(&content_base);
		assert_eq!(content_dest.len(), 2);
	}
}