@@ -95,14 +95,16 @@ impl Renderer for HtmlHandlebars {
95
95
debug ! ( "[*]: Render template" ) ;
96
96
let rendered = try!( handlebars. render ( "index" , & data) ) ;
97
97
98
- // create links for headers
99
- let rendered = build_header_links ( rendered) ;
98
+ let filename = Path :: new ( & ch. path ) . with_extension ( "html" ) ;
99
+
100
+ // create links for headers and fix anchors
101
+ let rendered = build_header_links ( rendered, filename. to_str ( ) . unwrap_or ( "" ) ) ;
102
+ let rendered = fix_anchor_links ( rendered, filename. to_str ( ) . unwrap_or ( "" ) ) ;
100
103
101
104
// fix code blocks
102
105
let rendered = fix_code_blocks ( rendered) ;
103
106
104
107
// Write to file
105
- let filename = Path :: new ( & ch. path ) . with_extension ( "html" ) ;
106
108
info ! ( "[*] Creating {:?} ✓" , filename. display( ) ) ;
107
109
try!( book. write_file ( filename, & rendered. into_bytes ( ) ) ) ;
108
110
@@ -144,7 +146,8 @@ impl Renderer for HtmlHandlebars {
144
146
debug ! ( "[*]: Render template" ) ;
145
147
146
148
let rendered = try!( handlebars. render ( "index" , & data) ) ;
147
- let rendered = build_header_links ( rendered) ;
149
+ let rendered = build_header_links ( rendered, "print.html" ) ;
150
+ let rendered = fix_anchor_links ( rendered, "print.html" ) ;
148
151
149
152
// fix code blocks
150
153
let rendered = fix_code_blocks ( rendered) ;
@@ -224,7 +227,7 @@ fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>
224
227
Ok ( data)
225
228
}
226
229
227
- fn build_header_links ( html : String ) -> String {
230
+ fn build_header_links ( html : String , filename : & str ) -> String {
228
231
let regex = Regex :: new ( r"<h(\d)>(.*?)</h\d>" ) . unwrap ( ) ;
229
232
230
233
regex. replace_all ( & html, |caps : & Captures | {
@@ -251,10 +254,27 @@ fn build_header_links(html: String) -> String {
251
254
}
252
255
} ) . collect :: < String > ( ) ;
253
256
254
- format ! ( "<a class=\" header\" href=\" #{id}\" name=\" {id}\" ><h{level}>{text}</h{level}></a>" , level=level, id=id, text=text)
257
+ format ! ( "<a class=\" header\" href=\" {filename}#{id}\" name=\" {id}\" ><h{level}>{text}</h{level}></a>" ,
258
+ level=level, id=id, text=text, filename=filename)
255
259
} ) . into_owned ( )
256
260
}
257
261
262
+ // anchors to the same page (href="#anchor") do not work because of
263
+ // <base href="../"> pointing to the root folder. This function *fixes*
264
+ // that in a very inelegant way
265
+ fn fix_anchor_links ( html : String , filename : & str ) -> String {
266
+ let regex = Regex :: new ( r##"<a([^>]+)href="#([^"]+)"([^>]*)>"## ) . unwrap ( ) ;
267
+ regex. replace_all ( & html, |caps : & Captures | {
268
+ let before = & caps[ 1 ] ;
269
+ let anchor = & caps[ 2 ] ;
270
+ let after = & caps[ 3 ] ;
271
+
272
+ format ! ( "<a{before}href=\" {filename}#{anchor}\" {after}>" ,
273
+ before=before, filename=filename, anchor=anchor, after=after)
274
+ } ) . into_owned ( )
275
+ }
276
+
277
+
258
278
// The rust book uses annotations for rustdoc to test code snippets, like the following:
259
279
// ```rust,should_panic
260
280
// fn main() {
0 commit comments