nmd_core/dossier/document/chapter/
chapter_header.rs1use getset::{Getters, MutGetters, Setters};
2use serde::Serialize;
3use crate::{codex::{modifier::{base_modifier::BaseModifier, standard_heading_modifier::StandardHeading, Modifier}, Codex}, load::{LoadConfiguration, LoadError}, load_block::{LoadBlock, LoadBlockContent}};
4use super::{chapter_tag::ChapterTag, heading::{Heading, HeadingLevel}};
5
6
7
8#[derive(Debug, Clone, Getters, MutGetters, Setters, Serialize)]
12pub struct ChapterHeader {
13
14 #[getset(get = "pub", get_mut = "pub", set = "pub")]
15 heading: Heading,
16
17 #[getset(get = "pub", get_mut = "pub", set = "pub")]
18 tags: Vec<ChapterTag>,
19}
20
21impl ChapterHeader {
22
23 pub fn new(heading: Heading, tags: Vec<ChapterTag>,) -> Self {
24 Self {
25 heading,
26 tags
27 }
28 }
29
30 pub fn load(content: &str, codex: &Codex, configuration: &LoadConfiguration) -> Result<Vec<LoadBlock>, LoadError> {
32
33 let mut headers: Vec<LoadBlock> = Vec::new();
34
35 for heading in StandardHeading::ordered() { let heading_modifier = Into::<BaseModifier>::into(heading);
38
39 for m in heading_modifier.modifier_pattern_regex().find_iter(content) {
40
41 let matched_str = m.as_str().to_string();
42
43 let m_start = m.start();
44 let m_end = m.end();
45
46 log::debug!("header found (between {} and {}): {:?}", m_start, m_end, &matched_str);
47
48 if let Some((heading, tags)) = Self::parse_chapter_heading_and_tags_from_str(&matched_str, codex, configuration)? {
49
50 headers.push(LoadBlock::new(
51 m_start,
52 m_end,
53 LoadBlockContent::ChapterHeader(ChapterHeader::new(heading, tags))
54 ));
55 }
56
57 };
58 }
59
60 log::debug!("found headers:\n{:#?}", headers);
61
62 Ok(headers)
63 }
64
65 fn parse_chapter_heading_and_tags_from_str(content: &str, _codex: &Codex, _configuration: &LoadConfiguration) -> Result<Option<(Heading, Vec<ChapterTag>)>, LoadError> {
67
68 log::debug!("parse headings and chapter tags from:\n{}", content);
69
70 for heading in StandardHeading::ordered() { let heading_modifier = Into::<BaseModifier>::into(heading.clone());
73
74 if !heading_modifier.modifier_pattern_regex().is_match(content) {
75 continue
76 }
77
78 if let Some(capture) = heading_modifier.modifier_pattern_regex().captures(content) {
79
80 match heading {
81
82 StandardHeading::MinorHeading => {
83
84 let level = HeadingLevel::Minor;
85
86 let title = capture.get(1).unwrap();
87
88 let tags = ChapterTag::load_chapter_tags_from_str(&content[title.end()..])?;
89
90 return Ok(Some((
91 Heading::new(level, title.as_str().to_string()),
92 tags
93 )))
94 },
95
96 StandardHeading::MajorHeading => {
97
98 let level = HeadingLevel::Major;
99
100 let title = capture.get(1).unwrap();
101
102
103 let tags = ChapterTag::load_chapter_tags_from_str(&content[title.end()..])?;
104
105 return Ok(Some((
106 Heading::new(level, title.as_str().to_string()),
107 tags
108 )))
109 },
110
111 StandardHeading::SameHeading => {
112
113
114 let level = HeadingLevel::Same;
115
116 let title = capture.get(1).unwrap();
117
118
119 let tags = ChapterTag::load_chapter_tags_from_str(&content[title.end()..])?;
120
121 return Ok(Some((
122 Heading::new(level, title.as_str().to_string()),
123 tags
124 )))
125 },
126
127 StandardHeading::HeadingGeneralExtendedVersion(_) => {
128 let level: u32 = content.chars().take_while(|&c| c == '#').count() as u32;
129
130 let title = capture.get(1).unwrap();
131
132 let tags = ChapterTag::load_chapter_tags_from_str(&content[title.end()..])?;
133
134 return Ok(Some((
135 Heading::new(HeadingLevel::Explicit(level), title.as_str().to_string()),
136 tags
137 )))
138 },
139
140 StandardHeading::HeadingGeneralCompactVersion(_) => {
141 let matched = heading_modifier.modifier_pattern_regex().captures(content).unwrap();
142
143 let level = HeadingLevel::Explicit(matched.get(1).unwrap().as_str().parse().unwrap());
144 let title = capture.get(2).unwrap();
145
146 let tags = ChapterTag::load_chapter_tags_from_str(&content[title.end()..])?;
147
148 return Ok(Some((
149 Heading::new(level, title.as_str().to_string()),
150 tags
151 )))
152 },
153 }
154 }
155
156 }
157
158 Ok(None)
159 }
160
161}