1
1
//! The library crate for the mdbook LAD preprocessor.
2
2
#![ allow( missing_docs) ]
3
3
4
- use mdbook:: { errors:: Error , preprocess:: Preprocessor , BookItem } ;
4
+ use mdbook:: { errors:: Error , preprocess:: Preprocessor } ;
5
5
use sections:: Section ;
6
6
mod argument_visitor;
7
7
mod markdown;
@@ -11,6 +11,46 @@ const LAD_EXTENSION: &str = "lad.json";
11
11
12
12
pub struct LADPreprocessor ;
13
13
14
+ impl LADPreprocessor {
15
+ /// Checks if a chapter is a LAD file.
16
+ fn is_lad_file ( chapter : & mdbook:: book:: Chapter ) -> bool {
17
+ chapter
18
+ . source_path
19
+ . as_ref ( )
20
+ . and_then ( |a| a. file_name ( ) )
21
+ . map ( |s| s. to_string_lossy ( ) . ends_with ( LAD_EXTENSION ) )
22
+ . unwrap_or ( false )
23
+ }
24
+
25
+ /// Process a chapter that is a LAD file.
26
+ ///
27
+ /// `parent` is the optional parent chapter reference,
28
+ /// and `chapter_index` is the index of the chapter among its siblings.
29
+ fn process_lad_chapter (
30
+ chapter : & mdbook:: book:: Chapter ,
31
+ parent : Option < & mdbook:: book:: Chapter > ,
32
+ chapter_index : usize ,
33
+ ) -> Result < mdbook:: book:: Chapter , Error > {
34
+ let chapter_title = chapter. name . trim_end_matches ( ".lad.json" ) . to_owned ( ) ;
35
+ let ladfile = ladfile:: parse_lad_file ( & chapter. content )
36
+ . map_err ( |e| Error :: new ( e) . context ( "Failed to parse LAD file" ) ) ?;
37
+ log:: debug!(
38
+ "Parsed LAD file: {}" ,
39
+ serde_json:: to_string_pretty( & ladfile) . unwrap_or_default( )
40
+ ) ;
41
+ let new_chapter = Section :: Summary {
42
+ ladfile : & ladfile,
43
+ title : Some ( chapter_title) ,
44
+ }
45
+ . into_chapter ( parent, chapter_index) ;
46
+ log:: debug!(
47
+ "New chapter: {}" ,
48
+ serde_json:: to_string_pretty( & new_chapter) . unwrap_or_default( )
49
+ ) ;
50
+ Ok ( new_chapter)
51
+ }
52
+ }
53
+
14
54
impl Preprocessor for LADPreprocessor {
15
55
fn name ( & self ) -> & str {
16
56
"lad-preprocessor"
@@ -21,145 +61,68 @@ impl Preprocessor for LADPreprocessor {
21
61
_ctx : & mdbook:: preprocess:: PreprocessorContext ,
22
62
mut book : mdbook:: book:: Book ,
23
63
) -> mdbook:: errors:: Result < mdbook:: book:: Book > {
24
- let mut errors = Vec :: default ( ) ;
64
+ let mut errors = Vec :: new ( ) ;
25
65
66
+ // first replace children in parents
26
67
book. for_each_mut ( |item| {
27
68
if let mdbook:: BookItem :: Chapter ( parent) = item {
28
- let mut replacements = Vec :: default ( ) ;
29
- for ( ladfile_idx, child) in parent. sub_items . iter ( ) . enumerate ( ) {
30
- if let BookItem :: Chapter ( child) = child {
31
- let is_lad_file = child
32
- . source_path
33
- . as_ref ( )
34
- . and_then ( |a| a. file_name ( ) )
35
- . is_some_and ( |a| a. to_string_lossy ( ) . ends_with ( LAD_EXTENSION ) ) ;
36
-
37
- if !is_lad_file {
38
- continue ;
39
- }
40
-
41
- let chapter_title =
42
- child. name . clone ( ) . trim_end_matches ( ".lad.json" ) . to_owned ( ) ;
43
-
44
- let ladfile = match ladfile:: parse_lad_file ( & child. content ) {
45
- Ok ( lad) => lad,
46
- Err ( e) => {
47
- log:: debug!( "Failed to parse LAD file: {:?}" , e) ;
48
- errors. push ( Error :: new ( e) . context ( "Failed to parse LAD file" ) ) ;
49
- continue ;
69
+ // First, collect the indices and new chapters for LAD file chapters.
70
+ let replacements: Vec < ( usize , mdbook:: book:: Chapter ) > = parent
71
+ . sub_items
72
+ . iter ( )
73
+ . enumerate ( )
74
+ . filter_map ( |( idx, item) | {
75
+ if let mdbook:: BookItem :: Chapter ( chapter) = item {
76
+ if LADPreprocessor :: is_lad_file ( chapter) {
77
+ match LADPreprocessor :: process_lad_chapter (
78
+ chapter,
79
+ Some ( parent) ,
80
+ idx,
81
+ ) {
82
+ Ok ( new_chapter) => return Some ( ( idx, new_chapter) ) ,
83
+ Err ( e) => {
84
+ errors. push ( e) ;
85
+ return None ;
86
+ }
87
+ }
50
88
}
51
- } ;
52
-
53
- log:: debug!(
54
- "Parsed LAD file: {}" ,
55
- serde_json:: to_string_pretty( & ladfile) . unwrap_or_default( )
56
- ) ;
57
-
58
- let new_chapter = Section :: Summary {
59
- ladfile : & ladfile,
60
- title : Some ( chapter_title) ,
61
89
}
62
- . into_chapter ( Some ( parent) , ladfile_idx) ;
63
-
64
- log:: debug!(
65
- "New chapter: {}" ,
66
- serde_json:: to_string_pretty( & new_chapter) . unwrap_or_default( )
67
- ) ;
68
-
69
- // replace
70
- replacements. push ( ( ladfile_idx, BookItem :: Chapter ( new_chapter) ) ) ;
90
+ None
91
+ } )
92
+ . collect ( ) ;
93
+
94
+ // Then, apply the replacements.
95
+ for ( idx, new_chapter) in replacements {
96
+ if let mdbook:: BookItem :: Chapter ( chapter) = & mut parent. sub_items [ idx] {
97
+ * chapter = new_chapter;
71
98
}
72
99
}
73
-
74
- for ( idx, replacement) in replacements {
75
- log:: debug!(
76
- "Replacing chapter at index {}. With : \n {}" ,
77
- idx,
78
- serde_json:: to_string_pretty( & replacement) . unwrap_or_default( )
79
- ) ;
80
- parent. sub_items [ idx] = replacement;
81
- }
82
100
}
83
101
} ) ;
84
102
85
- // book.for_each_mut(|item| {
86
- // if let mdbook::BookItem::Chapter(chapter) = item {
87
- // let is_lad_chapter = chapter
88
- // .source_path
89
- // .as_ref()
90
- // .and_then(|a| a.file_name())
91
- // .is_some_and(|a| a.to_string_lossy().ends_with(LAD_EXTENSION));
92
-
93
- // if !is_lad_chapter {
94
- // log::debug!("Skipping non-LAD chapter: {:?}", chapter.source_path);
95
- // log::trace!(
96
- // "Non-LAD chapter: {}",
97
- // serde_json::to_string_pretty(&chapter).unwrap_or_default()
98
- // );
99
- // return;
100
- // }
101
-
102
- // let chapter_title = chapter
103
- // .name
104
- // .clone()
105
- // .trim_end_matches(".lad.json")
106
- // .to_owned();
107
-
108
- // let lad = match ladfile::parse_lad_file(&chapter.content) {
109
- // Ok(lad) => lad,
110
- // Err(e) => {
111
- // log::debug!("Failed to parse LAD file: {:?}", e);
112
- // errors.push(Error::new(e).context("Failed to parse LAD file"));
113
- // return;
114
- // }
115
- // };
116
-
117
- // log::debug!(
118
- // "Parsed LAD file: {}",
119
- // serde_json::to_string_pretty(&lad).unwrap_or_default()
120
- // );
121
-
122
- // let mut new_chapter = Section::Summary {
123
- // ladfile: &lad,
124
- // title: Some(chapter_title),
125
- // }
126
- // .into_chapter(None, 0);
127
-
128
- // new_chapter.path = new_chapter
129
- // .path
130
- // .map(|m| chapter.path.as_ref().cloned().unwrap_or_default().join(m));
131
-
132
- // new_chapter.source_path = new_chapter.source_path.map(|m| {
133
- // chapter
134
- // .source_path
135
- // .as_ref()
136
- // .cloned()
137
- // .unwrap_or_default()
138
- // .join(m)
139
- // });
140
-
141
- // new_chapter.parent_names = chapter.parent_names.clone();
142
-
143
- // // let sections = sections::lad_file_to_sections(&lad, Some(chapter_title));
103
+ // then try match items themselves
104
+ book. for_each_mut ( |item| {
105
+ if let mdbook:: BookItem :: Chapter ( chapter) = item {
106
+ if !LADPreprocessor :: is_lad_file ( chapter) {
107
+ return ;
108
+ }
144
109
145
- // // let new_chapter = sections::section_to_chapter(
146
- // // sections,
147
- // // Some(chapter),
148
- // // chapter.parent_names.clone(),
149
- // // chapter.number.clone(),
150
- // // None,
151
- // // None,
152
- // // );
110
+ let new_chapter = match LADPreprocessor :: process_lad_chapter ( chapter, None , 0 ) {
111
+ Ok ( new_chapter) => new_chapter,
112
+ Err ( e) => {
113
+ errors. push ( e) ;
114
+ return ;
115
+ }
116
+ } ;
153
117
154
- // // serialize chapter to json
155
- // log::debug!(
156
- // "New chapter: {}",
157
- // serde_json::to_string_pretty(&new_chapter).unwrap_or_default()
158
- // );
118
+ * chapter = new_chapter;
119
+ }
120
+ } ) ;
159
121
160
- // *chapter = new_chapter;
161
- // }
162
- // });
122
+ log:: debug!(
123
+ "Book after LAD processing: {}" ,
124
+ serde_json:: to_string_pretty( & book) . unwrap_or_default( )
125
+ ) ;
163
126
164
127
if !errors. is_empty ( ) {
165
128
// return on first error
0 commit comments