1#![deny(
4 clippy::all,
5 missing_debug_implementations,
6 missing_copy_implementations,
7 missing_docs
8)]
9#![warn(clippy::pedantic, clippy::nursery)]
10
11use mdbook_preprocessor::{
12 book::{Book, BookItem, Chapter},
13 errors::Error,
14 Preprocessor, PreprocessorContext,
15};
16use pulldown_cmark::{CodeBlockKind, CowStr, Event, Options, Parser, Tag, TagEnd};
17use pulldown_cmark_to_cmark::cmark;
18
19mod backend;
20use backend::{Backend, RenderContext};
21
22mod config;
23
24#[derive(Default, Clone, Copy, Debug)]
26pub struct D2;
27
28impl Preprocessor for D2 {
29 fn name(&self) -> &'static str {
30 "d2"
31 }
32
33 fn run(&self, ctx: &PreprocessorContext, mut book: Book) -> Result<Book, Error> {
34 let backend = Backend::from_context(ctx);
35
36 book.for_each_mut(|section| {
37 if let BookItem::Chapter(chapter) = section {
38 let events = process_events(
39 &backend,
40 chapter,
41 Parser::new_ext(&chapter.content, Options::all()),
42 );
43
44 let mut buf = String::with_capacity(chapter.content.len() + 128);
46
47 cmark(events, &mut buf).unwrap();
49 chapter.content = buf;
50 }
51 });
52
53 Ok(book)
54 }
55}
56
57fn process_events<'a>(
58 backend: &'a Backend,
59 chapter: &'a Chapter,
60 events: impl Iterator<Item = Event<'a>> + 'a,
61) -> impl Iterator<Item = Event<'a>> + 'a {
62 let mut in_block = false;
63 let mut diagram = String::new();
67 let mut diagram_index = 0;
68
69 events.flat_map(move |event| {
70 match (&event, in_block) {
71 (
73 Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(CowStr::Borrowed("d2")))),
74 false,
75 ) => {
76 in_block = true;
77 diagram.clear();
78 diagram_index += 1;
79 vec![]
80 }
81 (Event::Text(content), true) => {
83 diagram.push_str(content);
84 vec![]
85 }
86 (Event::End(TagEnd::CodeBlock), true) => {
88 in_block = false;
89 let render_context = RenderContext::new(
90 chapter.source_path.as_ref().unwrap(),
91 &chapter.name,
92 chapter.number.as_ref(),
93 diagram_index,
94 );
95 backend
96 .render(&render_context, &diagram)
97 .unwrap_or_else(|e| {
98 eprintln!("{e}");
101 vec![]
102 })
103 }
104 _ => vec![event],
106 }
107 })
108}