1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#![warn(unused_extern_crates)] #[macro_use] extern crate log; extern crate mdbook; extern crate pulldown_cmark; extern crate pulldown_cmark_to_cmark; extern crate tempfile; #[macro_use] extern crate failure; #[macro_use] extern crate serde_derive; #[cfg(test)] extern crate pretty_assertions; #[cfg(test)] extern crate simulacrum; mod markdown_plantuml_pipeline; mod plantuml_backend; mod plantumlconfig; use failure::Error; use markdown_plantuml_pipeline::{render_plantuml_code_blocks, PlantUMLCodeBlockRenderer}; use mdbook::book::{Book, BookItem}; use mdbook::preprocess::{Preprocessor, PreprocessorContext}; use plantuml_backend::PlantUMLBackend; use plantumlconfig::PlantUMLConfig; impl PlantUMLCodeBlockRenderer for Box<PlantUMLBackend> { fn render(&self, code_block: String) -> String { match self.render_svg_from_string(&code_block) { Ok(svg) => svg, Err(e) => { error!("Failed to generate PlantUML diagram."); String::from(format!("<pre>PlantUML rendering error:\n{}</pre>", e)) } } } } pub struct PlantUMLPreprocessor; impl Preprocessor for PlantUMLPreprocessor { fn name(&self) -> &str { "plantuml" } fn run( &self, ctx: &PreprocessorContext, mut book: Book, ) -> Result<Book, mdbook::errors::Error> { let cfg = get_plantuml_config(ctx); let plantuml_cmd = plantuml_backend::create(&cfg); let res = None; book.for_each_mut(|item: &mut BookItem| { if let BookItem::Chapter(ref mut chapter) = *item { match render_chapter(&plantuml_cmd, &chapter.content) { Ok(md) => chapter.content = md, Err(_) => { return; } }; } }); res.unwrap_or(Ok(())).map(|_| book) } fn supports_renderer(&self, renderer: &str) -> bool { renderer != "not-supported" } } fn render_chapter( plantuml_renderer: &impl PlantUMLCodeBlockRenderer, chapter: &str, ) -> Result<String, Error> { Ok(render_plantuml_code_blocks(chapter, plantuml_renderer)) } fn get_plantuml_config(ctx: &PreprocessorContext) -> PlantUMLConfig { match ctx.config.get("preprocessor.plantuml") { Some(raw) => raw .clone() .try_into() .or_else(|e| { warn!( "Failed to get config from book.toml, using default configuration ({}).", e ); Err(e) }) .unwrap_or(PlantUMLConfig::default()), None => PlantUMLConfig::default(), } }