@@ -5,13 +5,13 @@ book is loaded and before it gets rendered, allowing you to update and mutate
5
5
the book. Possible use cases are:
6
6
7
7
- Creating custom helpers like ` \{{#include /path/to/file.md}} `
8
- - Updating links so ` [some chapter](some_chapter.md) ` is automatically changed
8
+ - Updating links so ` [some chapter](some_chapter.md) ` is automatically changed
9
9
to ` [some chapter](some_chapter.html) ` for the HTML renderer
10
- - Substituting in latex-style expressions (` $$ \frac{1}{3} $$ ` ) with their
10
+ - Substituting in latex-style expressions (` $$ \frac{1}{3} $$ ` ) with their
11
11
mathjax equivalents
12
12
13
13
14
- ## Implementing a Preprocessor
14
+ ## Implementing a Preprocessor
15
15
16
16
A preprocessor is represented by the ` Preprocessor ` trait.
17
17
@@ -29,4 +29,68 @@ pub struct PreprocessorContext {
29
29
pub root : PathBuf ,
30
30
pub config : Config ,
31
31
}
32
- ```
32
+ ```
33
+
34
+ ## A complete Example
35
+
36
+ The magic happens within the ` run(...) ` method of the [ ` Preprocessor ` ] [ preprocessor-docs ] trait implementation.
37
+
38
+ As direct access to the chapters is not possible, you will probably end up iterating
39
+ them using ` for_each_mut(...) ` :
40
+
41
+ ``` rust
42
+ book . for_each_mut (| item : & mut BookItem | {
43
+ if let BookItem :: Chapter (ref mut chapter ) = * item {
44
+ eprintln! (" {}: processing chapter '{}'" , self . name (), chapter . name);
45
+ res = Some (
46
+ match Deemphasize :: remove_emphasis (& mut num_removed_items , chapter ) {
47
+ Ok (md ) => {
48
+ chapter . content = md ;
49
+ Ok (())
50
+ }
51
+ Err (err ) => Err (err ),
52
+ },
53
+ );
54
+ }
55
+ });
56
+ ```
57
+
58
+ The ` chapter.content ` is just a markdown formatted string, and you will have to
59
+ process it in some way. Even though it's entirely possible to implement some sort of
60
+ manual find & replace operation, if that feels too unsafe you can use [ ` pulldown-cmark ` ] [ pc ]
61
+ to parse the string into events and work on them instead.
62
+
63
+ Finally you can use [ ` pulldown-cmark-to-cmark ` ] [ pctc ] to transform these events back to
64
+ a string.
65
+
66
+ The following code block shows how to remove all emphasis from markdown, and do so
67
+ safely.
68
+
69
+ ``` rust
70
+ fn remove_emphasis (num_removed_items : & mut i32 , chapter : & mut Chapter ) -> Result <String > {
71
+ let mut buf = String :: with_capacity (chapter . content. len ());
72
+ let events = Parser :: new (& chapter . content). filter (| e | {
73
+ let should_keep = match * e {
74
+ Event :: Start (Tag :: Emphasis )
75
+ | Event :: Start (Tag :: Strong )
76
+ | Event :: End (Tag :: Emphasis )
77
+ | Event :: End (Tag :: Strong ) => false ,
78
+ _ => true ,
79
+ };
80
+ if ! should_keep {
81
+ * num_removed_items += 1 ;
82
+ }
83
+ should_keep
84
+ });
85
+ cmark (events , & mut buf , None )
86
+ . map (| _ | buf )
87
+ . map_err (| err | Error :: from (format! (" Markdown serialization failed: {}" , err )))
88
+ }
89
+ ```
90
+
91
+ For everything else, have a look [ at the complete example] [ example ] .
92
+
93
+ [ preprocessor-docs ] : https://docs.rs/mdbook/0.1.3/mdbook/preprocess/trait.Preprocessor.html
94
+ [ pc ] : https://crates.io/crates/pulldown-cmark
95
+ [ pctc ] : https://crates.io/crates/pulldown-cmark-to-cmark
96
+ [ example ] : https://github.com/rust-lang-nursery/mdBook/blob/master/examples/de-emphasize.rs
0 commit comments