nmd_core/dossier/document/chapter/
heading.rs

1use getset::{Getters, Setters};
2use serde::Serialize;
3use crate::{codex::{modifier::ModifiersBucket, Codex}, compilable_text::{compilable_text_part::{CompilableTextPart, CompilableTextPartType}, CompilableText}, compilation::{compilable::Compilable, compilation_configuration::{compilation_configuration_overlay::CompilationConfigurationOverLay, CompilationConfiguration}, compilation_error::CompilationError, compilation_outcome::CompilationOutcome}, output_format::OutputFormat, resource::resource_reference::ResourceReference, utility::nmd_unique_identifier::NmdUniqueIdentifier};
4
5
6#[derive(Debug, Clone, Serialize)]
7pub enum HeadingLevel {
8    Explicit(u32),
9    Minor,
10    Major,
11    Same
12}
13
14
15#[derive(Debug, Getters, Setters, Clone, Serialize)]
16pub struct Heading {
17
18    #[getset(get = "pub", set = "pub")]
19    level: HeadingLevel,
20
21    #[getset(get = "pub", set = "pub")]
22    title: String,
23
24    #[getset(get = "pub", set = "pub")]
25    resource_reference: Option<ResourceReference>,
26
27    #[getset(get = "pub", set = "pub")]
28    nuid: Option<NmdUniqueIdentifier>,
29}
30
31impl Heading {
32    pub fn new(level: HeadingLevel, title: String) -> Self {
33
34        Self {
35            level,
36            title,
37            resource_reference: None,
38            nuid: None,
39        }
40    }
41}
42
43impl Compilable for Heading {
44    fn standard_compile(&mut self, format: &OutputFormat, codex: &Codex, compilation_configuration: &CompilationConfiguration, compilation_configuration_overlay: CompilationConfigurationOverLay) -> Result<CompilationOutcome, CompilationError> {
45        
46        let document_name = compilation_configuration_overlay.document_name().as_ref();
47
48        if document_name.is_none() {
49            return Err(CompilationError::DocumentNameNotFound)
50        }
51
52        let document_name = document_name.unwrap();
53
54        let id: ResourceReference = ResourceReference::of_internal_from_without_sharp(&self.title, Some(&document_name))?;
55
56        let mut compiled_title = CompilableText::from(self.title.clone());
57        
58        compiled_title.compile(format, codex, compilation_configuration, compilation_configuration_overlay.clone())?;
59
60        let res = match format {
61            OutputFormat::Html => {
62
63                let nuid_attr: String;
64
65                if let Some(nuid) = &self.nuid {
66                    nuid_attr = format!(r#"data-nuid="{}""#, nuid);
67                } else {
68                    nuid_attr = String::new();
69                }
70
71                let level = match self.level {
72                    HeadingLevel::Explicit(l) => l,
73                    _ => return Err(CompilationError::HeadingLevelNotInferable(self.title.to_string()))
74                };
75
76                let outcome = CompilableText::new(vec![
77
78                    CompilableTextPart::new(
79                        format!(r#"<h{} class="heading-{}" id="{}" {}>"#, level, level, id.build_without_internal_sharp(), nuid_attr),
80                        CompilableTextPartType::Fixed
81                    ),
82                    CompilableTextPart::new(
83                        compiled_title.content(),
84                        CompilableTextPartType::Compilable{ incompatible_modifiers: ModifiersBucket::None }
85                    ),
86                    CompilableTextPart::new(
87                        format!(r#"</h{}>"#, level),
88                        CompilableTextPartType::Fixed
89                    ),
90                ]);
91
92                outcome
93            },
94        };
95
96        self.set_resource_reference(Some(id));      // TODO: is pointless?
97
98        Ok(CompilationOutcome::from(&res))
99    }
100}