1- use super :: CustomComponent ;
1+ use super :: custom_component :: CustomComponent ;
22use anyhow:: { anyhow, Result } ;
33use lol_html:: html_content:: ContentType ;
44use lol_html:: { element, RewriteStrSettings } ;
55use mdbook:: renderer:: RenderContext ;
66use serde_json:: to_value;
77use std:: collections:: { BTreeMap , HashMap } ;
88use std:: fs;
9- use std:: io:: { Read , Write } ;
10- use std:: path:: { Path , PathBuf } ;
9+ use std:: io:: Write ;
10+ use std:: path:: Path ;
1111use std:: sync:: Arc ;
1212use tera:: Tera ;
1313
14- pub struct RenderingContext < ' a > {
15- pub path : PathBuf ,
16- pub language : Option < String > ,
17- pub serialized_ctx : & ' a serde_json:: Value ,
18- pub ctx : & ' a RenderContext ,
19- }
20-
21- impl < ' a > RenderingContext < ' a > {
22- fn new (
23- path : PathBuf ,
24- language : Option < String > ,
25- serialized_ctx : & ' a serde_json:: Value ,
26- ctx : & ' a RenderContext ,
27- ) -> Result < Self > {
28- Ok ( RenderingContext {
29- path,
30- language,
31- serialized_ctx,
32- ctx,
33- } )
34- }
35- }
36-
3714pub ( crate ) struct Renderer {
3815 ctx : Arc < RenderContext > ,
3916 serialized_ctx : serde_json:: Value ,
4017 components : Vec < CustomComponent > ,
18+ counter : u64 ,
4119 tera_template : Tera ,
4220}
4321
4422impl Renderer {
4523 pub ( crate ) fn new ( ctx : RenderContext , tera_template : Tera ) -> Result < Renderer > {
46- Ok ( Renderer {
24+ let mut renderer = Renderer {
4725 serialized_ctx : serde_json:: to_value ( & ctx) ?,
4826 ctx : Arc :: new ( ctx) ,
4927 components : Vec :: new ( ) ,
28+ counter : 0 ,
5029 tera_template,
51- } )
30+ } ;
31+ renderer
32+ . tera_template
33+ . register_function ( "get_context" , renderer. create_get_context_function ( ) ) ;
34+ Ok ( renderer)
5235 }
5336
5437 pub ( crate ) fn add_component ( & mut self , mut component : CustomComponent ) {
@@ -57,7 +40,7 @@ impl Renderer {
5740 }
5841
5942 fn create_get_context_function ( & self ) -> impl tera:: Function {
60- let ctx_rx = Arc :: clone ( & self . ctx ) ;
43+ let ctx_rc = Arc :: clone ( & self . ctx ) ;
6144 move |args : & HashMap < String , serde_json:: value:: Value > | -> tera:: Result < tera:: Value > {
6245 let key = args
6346 . get ( "key" )
@@ -66,7 +49,7 @@ impl Renderer {
6649 . ok_or_else ( || {
6750 tera:: Error :: from ( format ! ( "Key has invalid type, expected string" ) )
6851 } ) ?;
69- let value = ctx_rx
52+ let value = ctx_rc
7053 . config
7154 . get ( key)
7255 . ok_or_else ( || tera:: Error :: from ( format ! ( "Could not find key {key} in config" ) ) ) ?;
@@ -76,21 +59,11 @@ impl Renderer {
7659 }
7760
7861 pub ( crate ) fn render_book ( & mut self ) -> Result < ( ) > {
79- let dest_dir = & self
80- . ctx
81- . destination
82- . parent ( )
83- . ok_or_else ( || {
84- anyhow ! (
85- "Destination directory {:?} has no parent" ,
86- self . ctx. destination
87- )
88- } ) ?
89- . to_owned ( ) ;
62+ let dest_dir = & self . ctx . destination . parent ( ) . unwrap ( ) ;
9063 if !dest_dir. is_dir ( ) {
91- return Err ( anyhow ! ( "{:?} is not a directory" , dest_dir ) ) ;
64+ return Err ( anyhow ! ( "{dest_dir :?} is not a directory" ) ) ;
9265 }
93- self . render_book_directory ( & dest_dir)
66+ self . render_book_directory ( dest_dir)
9467 }
9568
9669 fn render_book_directory ( & mut self , path : & Path ) -> Result < ( ) > {
@@ -110,39 +83,32 @@ impl Renderer {
11083 if path. extension ( ) . unwrap_or_default ( ) != "html" {
11184 return Ok ( ( ) ) ;
11285 }
113- let mut file_content = String :: new ( ) ;
114- {
115- let mut file = fs:: File :: open ( path) ?;
116- file. read_to_string ( & mut file_content) ?;
117- }
118-
86+ let file_content = std:: fs:: read_to_string ( path) ?;
11987 let output = self . render_components ( & file_content, path) ?;
12088 let mut output_file = fs:: File :: create ( path) ?;
12189 output_file. write_all ( output. as_bytes ( ) ) ?;
12290 Ok ( ( ) )
12391 }
12492
125- fn create_context ( & self , rendering_context : & RenderingContext ) -> tera:: Context {
93+ fn create_context ( & mut self , path : & Path ) -> tera:: Context {
12694 let mut context = tera:: Context :: new ( ) ;
127- context. insert ( "path" , & rendering_context . path ) ;
128- context. insert ( "ctx" , & rendering_context . serialized_ctx ) ;
129- context. insert (
130- "book_dir" ,
131- & rendering_context . ctx . destination . parent ( ) . unwrap ( ) ,
132- ) ;
95+ context. insert ( "path" , path) ;
96+ context. insert ( "ctx" , & self . serialized_ctx ) ;
97+ context. insert ( "book_dir" , & self . ctx . destination . parent ( ) . unwrap ( ) ) ;
98+ context . insert ( "counter" , & self . counter ) ;
99+ context . insert ( "attributes" , & BTreeMap :: < String , String > :: new ( ) ) ;
100+ self . counter += 1 ;
133101
134102 context
135103 }
136104
137105 fn render_components ( & mut self , file_content : & str , path : & Path ) -> Result < String > {
138- let rendering_context = RenderingContext :: new (
139- path. to_owned ( ) ,
140- self . ctx . config . book . language . clone ( ) ,
141- & self . serialized_ctx ,
142- & self . ctx ,
143- ) ?;
144- let tera_context = self . create_context ( & rendering_context) ;
145- let rendered_file = self . tera_template . render_str ( file_content, & tera_context) ?;
106+ let tera_context = self . create_context ( path) ;
107+
108+ let rendered_file = self
109+ . tera_template
110+ . render_str ( file_content, & tera_context)
111+ . map_err ( |e| anyhow ! ( "Error rendering file {path:?}: {e:?}" ) ) ?;
146112 let custom_components_handlers = self
147113 . components
148114 . iter ( )
0 commit comments