|
|
|
|
@@ -94,12 +94,17 @@ impl Renderer for HtmlHandlebars {
|
|
|
|
|
// Render the handlebars template with the data
|
|
|
|
|
debug!("[*]: Render template");
|
|
|
|
|
let rendered = try!(handlebars.render("index", &data));
|
|
|
|
|
|
|
|
|
|
// create links for headers
|
|
|
|
|
let rendered = build_header_links(rendered);
|
|
|
|
|
|
|
|
|
|
let filename = Path::new(&ch.path).with_extension("html");
|
|
|
|
|
|
|
|
|
|
// create links for headers and fix anchors
|
|
|
|
|
let rendered = build_header_links(rendered, filename.to_str().unwrap_or(""));
|
|
|
|
|
let rendered = fix_anchor_links(rendered, filename.to_str().unwrap_or(""));
|
|
|
|
|
|
|
|
|
|
// fix code blocks
|
|
|
|
|
let rendered = fix_code_blocks(rendered);
|
|
|
|
|
|
|
|
|
|
// Write to file
|
|
|
|
|
let filename = Path::new(&ch.path).with_extension("html");
|
|
|
|
|
info!("[*] Creating {:?} ✓", filename.display());
|
|
|
|
|
try!(book.write_file(filename, &rendered.into_bytes()));
|
|
|
|
|
|
|
|
|
|
@@ -141,7 +146,11 @@ impl Renderer for HtmlHandlebars {
|
|
|
|
|
debug!("[*]: Render template");
|
|
|
|
|
|
|
|
|
|
let rendered = try!(handlebars.render("index", &data));
|
|
|
|
|
let rendered = build_header_links(rendered);
|
|
|
|
|
let rendered = build_header_links(rendered, "print.html");
|
|
|
|
|
let rendered = fix_anchor_links(rendered, "print.html");
|
|
|
|
|
|
|
|
|
|
// fix code blocks
|
|
|
|
|
let rendered = fix_code_blocks(rendered);
|
|
|
|
|
|
|
|
|
|
try!(book.write_file(Path::new("print").with_extension("html"), &rendered.into_bytes()));
|
|
|
|
|
info!("[*] Creating print.html ✓");
|
|
|
|
|
@@ -218,7 +227,7 @@ fn make_data(book: &MDBook) -> Result<serde_json::Map<String, serde_json::Value>
|
|
|
|
|
Ok(data)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn build_header_links(html: String) -> String {
|
|
|
|
|
fn build_header_links(html: String, filename: &str) -> String {
|
|
|
|
|
let regex = Regex::new(r"<h(\d)>(.*?)</h\d>").unwrap();
|
|
|
|
|
|
|
|
|
|
regex.replace_all(&html, |caps: &Captures| {
|
|
|
|
|
@@ -245,6 +254,41 @@ fn build_header_links(html: String) -> String {
|
|
|
|
|
}
|
|
|
|
|
}).collect::<String>();
|
|
|
|
|
|
|
|
|
|
format!("<a class=\"header\" href=\"#{id}\" name=\"{id}\"><h{level}>{text}</h{level}></a>", level=level, id=id, text=text)
|
|
|
|
|
format!("<a class=\"header\" href=\"{filename}#{id}\" name=\"{id}\"><h{level}>{text}</h{level}></a>",
|
|
|
|
|
level=level, id=id, text=text, filename=filename)
|
|
|
|
|
}).into_owned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// anchors to the same page (href="#anchor") do not work because of
|
|
|
|
|
// <base href="../"> pointing to the root folder. This function *fixes*
|
|
|
|
|
// that in a very inelegant way
|
|
|
|
|
fn fix_anchor_links(html: String, filename: &str) -> String {
|
|
|
|
|
let regex = Regex::new(r##"<a([^>]+)href="#([^"]+)"([^>]*)>"##).unwrap();
|
|
|
|
|
regex.replace_all(&html, |caps: &Captures| {
|
|
|
|
|
let before = &caps[1];
|
|
|
|
|
let anchor = &caps[2];
|
|
|
|
|
let after = &caps[3];
|
|
|
|
|
|
|
|
|
|
format!("<a{before}href=\"{filename}#{anchor}\"{after}>",
|
|
|
|
|
before=before, filename=filename, anchor=anchor, after=after)
|
|
|
|
|
}).into_owned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The rust book uses annotations for rustdoc to test code snippets, like the following:
|
|
|
|
|
// ```rust,should_panic
|
|
|
|
|
// fn main() {
|
|
|
|
|
// // Code here
|
|
|
|
|
// }
|
|
|
|
|
// ```
|
|
|
|
|
// This function replaces all commas by spaces in the code block classes
|
|
|
|
|
fn fix_code_blocks(html: String) -> String {
|
|
|
|
|
let regex = Regex::new(r##"<code([^>]+)class="([^"]+)"([^>]*)>"##).unwrap();
|
|
|
|
|
regex.replace_all(&html, |caps: &Captures| {
|
|
|
|
|
let before = &caps[1];
|
|
|
|
|
let classes = &caps[2].replace(",", " ");
|
|
|
|
|
let after = &caps[3];
|
|
|
|
|
|
|
|
|
|
format!("<code{before}class=\"{classes}\"{after}>", before=before, classes=classes, after=after)
|
|
|
|
|
}).into_owned()
|
|
|
|
|
}
|
|
|
|
|
|