22#![ allow( missing_docs) ]
33
44use mdbook:: { errors:: Error , preprocess:: Preprocessor } ;
5+ use sections:: Section ;
56mod argument_visitor;
67mod markdown;
78mod sections;
@@ -10,6 +11,46 @@ const LAD_EXTENSION: &str = "lad.json";
1011
1112pub struct LADPreprocessor ;
1213
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+
1354impl Preprocessor for LADPreprocessor {
1455 fn name ( & self ) -> & str {
1556 "lad-preprocessor"
@@ -20,62 +61,69 @@ impl Preprocessor for LADPreprocessor {
2061 _ctx : & mdbook:: preprocess:: PreprocessorContext ,
2162 mut book : mdbook:: book:: Book ,
2263 ) -> mdbook:: errors:: Result < mdbook:: book:: Book > {
23- let mut errors = Vec :: default ( ) ;
64+ let mut errors = Vec :: new ( ) ;
2465
66+ // first replace children in parents
2567 book. for_each_mut ( |item| {
26- if let mdbook:: BookItem :: Chapter ( chapter) = item {
27- let is_lad_chapter = chapter
28- . source_path
29- . as_ref ( )
30- . and_then ( |a| a. file_name ( ) )
31- . is_some_and ( |a| a. to_string_lossy ( ) . ends_with ( LAD_EXTENSION ) ) ;
68+ if let mdbook:: BookItem :: Chapter ( parent) = item {
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+ }
88+ }
89+ }
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;
98+ }
99+ }
100+ }
101+ } ) ;
32102
33- if !is_lad_chapter {
34- log:: debug!( "Skipping non-LAD chapter: {:?}" , chapter. source_path) ;
35- log:: trace!(
36- "Non-LAD chapter: {}" ,
37- serde_json:: to_string_pretty( & chapter) . unwrap_or_default( )
38- ) ;
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) {
39107 return ;
40108 }
41109
42- let chapter_title = chapter. name . clone ( ) ;
43-
44- let lad = match ladfile:: parse_lad_file ( & chapter. content ) {
45- Ok ( lad) => lad,
110+ let new_chapter = match LADPreprocessor :: process_lad_chapter ( chapter, None , 0 ) {
111+ Ok ( new_chapter) => new_chapter,
46112 Err ( e) => {
47- log:: debug!( "Failed to parse LAD file: {:?}" , e) ;
48- errors. push ( Error :: new ( e) . context ( "Failed to parse LAD file" ) ) ;
113+ errors. push ( e) ;
49114 return ;
50115 }
51116 } ;
52117
53- log:: debug!(
54- "Parsed LAD file: {}" ,
55- serde_json:: to_string_pretty( & lad) . unwrap_or_default( )
56- ) ;
57-
58- let sections = sections:: lad_file_to_sections ( & lad, Some ( chapter_title) ) ;
59-
60- let new_chapter = sections:: section_to_chapter (
61- sections,
62- Some ( chapter) ,
63- chapter. parent_names . clone ( ) ,
64- chapter. number . clone ( ) ,
65- None ,
66- None ,
67- ) ;
68-
69- // serialize chapter to json
70- log:: debug!(
71- "New chapter: {}" ,
72- serde_json:: to_string_pretty( & new_chapter) . unwrap_or_default( )
73- ) ;
74-
75118 * chapter = new_chapter;
76119 }
77120 } ) ;
78121
122+ log:: debug!(
123+ "Book after LAD processing: {}" ,
124+ serde_json:: to_string_pretty( & book) . unwrap_or_default( )
125+ ) ;
126+
79127 if !errors. is_empty ( ) {
80128 // return on first error
81129 for error in errors {
0 commit comments